diff -r -c3 sdsi/Acl.java sdsi-new/Acl.java
*** sdsi/Acl.java	Wed Jun  3 10:35:56 1998
--- sdsi-new/Acl.java	Thu May 25 21:04:42 2000
***************
*** 2,14 ****
  
  import sdsi.sexp.*;
  import java.security.*;
! /**
  The class which implements acl's in SDSI/SPKI 2.0.  Acl's are currently considered
  as SDSIObjects, but the grammar of SDSI/SPKI has changed so that acl's are
  not specified.
  @author Alex Morcos
  @see SDSIObject
  */
  public class Acl extends SDSIObject{
    SDSIPrincipal creatingPrincipal; //may not need to carry this around
    //may only need for creation
--- 2,24 ----
  
  import sdsi.sexp.*;
  import java.security.*;
! 
! /*
  The class which implements acl's in SDSI/SPKI 2.0.  Acl's are currently considered
  as SDSIObjects, but the grammar of SDSI/SPKI has changed so that acl's are
  not specified.
  @author Alex Morcos
  @see SDSIObject
  */
+ /**
+  * Changed Morcos' class to use a more meaningful intersection test
+  * than just ``has a non-null intersection.'' See dissertation
+  * Section {@tex \ref{tag_meaning_intersection}}.
+  *
+  * @author Alex Morcos
+  * @author changed by jonh@cs.dartmouth.edu
+  * @classSummaryOnly true
+  */
  public class Acl extends SDSIObject{
    SDSIPrincipal creatingPrincipal; //may not need to carry this around
    //may only need for creation
***************
*** 128,134 ****
      }
      public boolean allows(SDSIPublicKey applicant, Name applicantName, Tag request) {
        if (v.valid()) {
!         if (t.intersect(request) == true) { 
            if (s instanceof SDSIPublicKey) {
              if (applicant.equals((SDSIPublicKey)s) && applicantName == null)
                return true;
--- 138,144 ----
      }
      public boolean allows(SDSIPublicKey applicant, Name applicantName, Tag request) {
        if (v.valid()) {
!         if (t.hasSubset(request) == true) { 
            if (s instanceof SDSIPublicKey) {
              if (applicant.equals((SDSIPublicKey)s) && applicantName == null)
                return true;
diff -r -c3 sdsi/Auth.java sdsi-new/Auth.java
*** sdsi/Auth.java	Wed Jun  3 10:35:58 1998
--- sdsi-new/Auth.java	Thu Jan 13 13:33:34 2000
***************
*** 27,32 ****
--- 27,44 ----
        authParts[4+pExists+i] = valids[i];
      srep = new SexpList(authParts);
    }
+ 
+ 
+ 	/**
+ 	 * [jonh] (apparently) Create an Auth certificate issued by
+ 	 * 'issuer' with subject and issuer info included by reference
+ 	 * (URIs). That strikes me as creepy.
+ 	 *
+ 	 * <p>
+ 	 * To load an authorization certificate from an S-expression,
+ 	 * use Cert.create(SexpList).
+ 	 * @see Cert.create(SexpList).
+ 	 */
    public Auth(SexpList l, SDSIPrincipal issuer) throws SexpParseException {
      super(l);
      boolean delegateDefined, issuerLocDefined, subjectLocDefined;
***************
*** 81,86 ****
--- 93,99 ----
      if (s == null || t == null) 
        throw new SexpParseException("Need subject and tag in cert");
    }
+ 
    public String getType() {
      return "Authorization Certificate";
    }
diff -r -c3 sdsi/Cert.java sdsi-new/Cert.java
*** sdsi/Cert.java	Wed Jun  3 10:36:00 1998
--- sdsi-new/Cert.java	Thu Feb 10 12:37:10 2000
***************
*** 104,110 ****
          if (potentialSubject instanceof Subject)
            s = (Subject)potentialSubject;
          else 
!           throw new SexpParseException("Subject is not one of the allowed Subject objects");
        }
      }
      else if (label.equals("version")) {
--- 104,110 ----
          if (potentialSubject instanceof Subject)
            s = (Subject)potentialSubject;
          else 
!           throw new SexpParseException("Subject is not one of the allowed Subject objects; it's a "+potentialSubject.getClass().getName());
        }
      }
      else if (label.equals("version")) {
diff -r -c3 sdsi/Def.java sdsi-new/Def.java
*** sdsi/Def.java	Wed Jun  3 10:36:02 1998
--- sdsi-new/Def.java	Sat Mar 11 10:29:02 2000
***************
*** 9,15 ****
    /** MUST CHANGE BOTH CONSTRUCTORS SO WE CAN HAVE ONLY ONE ISSUER NAME*/
    /**Creates a new Def from an issuer name, a subject, and a Validity*/
    public Def(SDSIPrincipal issuer, String name, Subject s, Validity v) throws SDSIException{
!     super(issuer,s,new Tag(),true,v);
      this.issuerName = new Name(issuer, new String[] {name});
      Sexp[] nameParts = new Sexp[2];
      nameParts[0] = new SexpString("issuer");
--- 9,15 ----
    /** MUST CHANGE BOTH CONSTRUCTORS SO WE CAN HAVE ONLY ONE ISSUER NAME*/
    /**Creates a new Def from an issuer name, a subject, and a Validity*/
    public Def(SDSIPrincipal issuer, String name, Subject s, Validity v) throws SDSIException{
!     super(issuer,s,Tag.getTagStar(),true,v);
      this.issuerName = new Name(issuer, new String[] {name});
      Sexp[] nameParts = new Sexp[2];
      nameParts[0] = new SexpString("issuer");
***************
*** 40,46 ****
        throw new SexpParseException("Only one name can be used as an issuer");
      this.issuerName = issuerName;
      this.issuer = issuerName.getPrincipal();
!     this.t = new Tag();
      Sexp[] certParts = l.arrayOfElements(); 
      for (int j = 1; j < certParts.length; j++) {
        Sexp element = certParts[j];
--- 40,46 ----
        throw new SexpParseException("Only one name can be used as an issuer");
      this.issuerName = issuerName;
      this.issuer = issuerName.getPrincipal();
!     this.t = Tag.getTagStar();
      Sexp[] certParts = l.arrayOfElements(); 
      for (int j = 1; j < certParts.length; j++) {
        Sexp element = certParts[j];
diff -r -c3 sdsi/Hash.java sdsi-new/Hash.java
*** sdsi/Hash.java	Wed Jun  3 10:36:04 1998
--- sdsi-new/Hash.java	Wed Jan 19 07:42:28 2000
***************
*** 59,64 ****
--- 59,69 ----
      srep = new SexpList(list);
    }
     
+ 	/**
+ 	 * Returns the string that describes the algorithm used to compute
+ 	 * this hash. This same string can be passed into the constructor
+ 	 * to compute a new hash of the same type.
+ 	 */
    public String getHashID() { //do we want getAlgID and share Key interface? what else is in key interface
      return ((SexpString)srep.elementAt(1)).stringContent();
    }
***************
*** 75,81 ****
    public boolean equals(Object otherHash) {     //no maybe we want everything to be the same; change later
      //at least want algorithms to be the same!!
      if (otherHash instanceof Hash)
!       return MessageDigest.isEqual(this.getHashValue(),((Hash)otherHash).getHashValue());
      else
        return false;
    }
--- 80,88 ----
    public boolean equals(Object otherHash) {     //no maybe we want everything to be the same; change later
      //at least want algorithms to be the same!!
      if (otherHash instanceof Hash)
!       return
! 		MessageDigest.isEqual(this.getHashValue(),
! 			((Hash)otherHash).getHashValue());
      else
        return false;
    }
diff -r -c3 sdsi/Name.java sdsi-new/Name.java
*** sdsi/Name.java	Wed Jun  3 10:36:08 1998
--- sdsi-new/Name.java	Wed Apr  5 07:02:52 2000
***************
*** 2,8 ****
  
  import sdsi.sexp.*;
  
! public class Name extends SDSIObject implements Subject{
    SDSIPrincipal owner;
    SexpString[] names;
    
--- 2,17 ----
  
  import sdsi.sexp.*;
  
! public class Name
! //	extends SDSIObject implements Subject
! 	extends SDSIPrincipal
! 		// in the semantics supported by Snowflake, there's no distinction,
! 		// so strongly-typing this to Subject makes it too weak to be
! 		// passed around where other issuers are. That's a pain;
! 		// in a rewrite, we wouldn't distinguish between 'issuers' and
! 		// 'subjects' statically. (They would be distinguished in which
! 		// handoff rules are believed, evaluated dynamically.)
! 	{
    SDSIPrincipal owner;
    SexpString[] names;
    
Only in sdsi-new: NullTagException.java
diff -r -c3 sdsi/ObjectHash.java sdsi-new/ObjectHash.java
*** sdsi/ObjectHash.java	Wed Jun  3 10:36:10 1998
--- sdsi-new/ObjectHash.java	Thu May 25 21:03:32 2000
***************
*** 2,13 ****
  
  import sdsi.sexp.*;
  
! public class ObjectHash extends SDSIObject implements Subject{
    //not actually store the reference to the hash, just return it when necessary
    //is that the best way to go?
    public ObjectHash(SexpList l) throws SexpParseException {
      super(l);
!     if (!l.getType().equals("object-hash"))
        throw new SexpParseException("Not a object hash");
      if (!(l.size() == 2) || !(l.elementAt(1) instanceof SexpList))
        throw new SexpParseException("Incorrectly formatted object hash");
--- 2,36 ----
  
  import sdsi.sexp.*;
  
! /**
!  * This subject is an s-expression representing the hash of some
!  * (external?) object. Its representation is a list
!  * <pre> (object-hash <em>the-hash</em>) </pre>
!  * which clearly indicates what the heck the hash is. [jonh]
!  *
!  *
!  * @author jonh made this into a principal, since it can speak for
!  * others in Snowflake. Example: proof.MacProof. Also added the (Hash)
!  * constructor.
!  * @classSummaryOnly true
!  */
! public class ObjectHash
! 	extends SDSIPrincipal
! 	implements Subject {
    //not actually store the reference to the hash, just return it when necessary
    //is that the best way to go?
+ 
+   public ObjectHash(Hash h) {
+ 		Sexp[] sexpary = new Sexp[2];
+ 		sexpary[0] = new SexpString(OBJECT_HASH);
+ 		sexpary[1] = h.getSrep();
+ 		srep = new SexpList(sexpary);
+   }
+ 
+   /** Parse a SexpList (object-hash <em>the-hash</em>). */
    public ObjectHash(SexpList l) throws SexpParseException {
      super(l);
!     if (!l.getType().equals(OBJECT_HASH))
        throw new SexpParseException("Not a object hash");
      if (!(l.size() == 2) || !(l.elementAt(1) instanceof SexpList))
        throw new SexpParseException("Incorrectly formatted object hash");
***************
*** 25,28 ****
--- 48,53 ----
    public String toShortString() {
      return "Obj " + this.getHash().toShortString();
    }
+ 
+   static final String OBJECT_HASH = "object-hash";
  }   
Only in sdsi-new: PseudoPrincipal.java
Only in sdsi-new: Quoting.java
Only in sdsi-new: RCAlpha.java
Only in sdsi-new: RCAny.java
Only in sdsi-new: README
Only in sdsi-new: RangeComparator.java
diff -r -c3 sdsi/SDSIObject.java sdsi-new/SDSIObject.java
*** sdsi/SDSIObject.java	Wed Jun  3 10:36:16 1998
--- sdsi-new/SDSIObject.java	Thu May 25 21:04:32 2000
***************
*** 4,10 ****
  import sdsi.sexp.*;
  import java.math.*;
  import java.io.*;
! /**
   Class to represent SDSI objects.  The many subclasses are useful for providing specific 
   functionality inherent to individual types of objects.
   @author Alex Morcos
--- 4,12 ----
  import sdsi.sexp.*;
  import java.math.*;
  import java.io.*;
! import Tools.ByteBuffer;
! 
! /*
   Class to represent SDSI objects.  The many subclasses are useful for providing specific 
   functionality inherent to individual types of objects.
   @author Alex Morcos
***************
*** 22,35 ****
   @see Sequence
   @see SDSISignature
  */
  public class SDSIObject implements Serializable{
   /* public interface Key {
      public String getAlgID();
    }
    */
!   SexpList srep; //make private eventually!
    
!   SDSIObject() {} 
    /**
    Create a new SDSIObject from a SexpList.
    @param s the SexpList that represents the SDSIObject.
--- 24,61 ----
   @see Sequence
   @see SDSISignature
  */
+ /**
+  * Added support for parsing Quoting, PseudoPrincipal, and
+  * ThresholdSubject principals.
+  * 
+  * Added performance optimizations for {@link #equals} and {@link
+  * hashCode}, which were previously pretty appalling. Now they're only
+  * fairly appalling.
+  * 
+  * @todo Made <code>srep</code> and the constructors public so that I
+  * could extend it outside of this package (so my code was a
+  * <em>little</em> factored). A production implementation should clean
+  * up the package hierarchy and decide whether this class should really
+  * be public anymore.
+  *
+  * @author Alex Morcos
+  * @author changed by jonh@cs.dartmouth.edu
+  * @classSummaryOnly true
+  */
  public class SDSIObject implements Serializable{
   /* public interface Key {
      public String getAlgID();
    }
    */
!   public SexpList srep; //make private eventually!
! 	// [jonh] made srep public so this class can be extended by other
! 	// packages.
! 	// TODO: 'protected' should have been enough, though.
    
!   public SDSIObject() {} 
! 	// [jonh] made constructor public so it could be extended from packages
! 	// outside here.
! 	// TODO: 'protected' should have been enough, though.
    /**
    Create a new SDSIObject from a SexpList.
    @param s the SexpList that represents the SDSIObject.
***************
*** 40,50 ****
     /** Generates the SDSI object that is represented by the SexpList in the argument.
         Parses the SexpList in the argument and returns the appropriate subclass
         of SDSIObject that has been initialized by the SexpList.  Is capable of parsing
!        Acl's, KeyHolder's, and Name's that may require a creating princpal to be known.
         @param l the SexpLIst to be parsed.
         @param p the SDSIPrincipal that should be treated as having created the object
!        @return the SDSI objecet represented
!        @exception SexpParseException if the SexpList can not be succesfully parsed into a SDSIObject
     */
    public static SDSIObject principalParse(SexpList l, SDSIPrincipal p) throws SexpParseException{
      String type = l.getType();
--- 66,76 ----
     /** Generates the SDSI object that is represented by the SexpList in the argument.
         Parses the SexpList in the argument and returns the appropriate subclass
         of SDSIObject that has been initialized by the SexpList.  Is capable of parsing
!        Acl's, KeyHolder's, and Name's that may require a creating principal to be known.
         @param l the SexpLIst to be parsed.
         @param p the SDSIPrincipal that should be treated as having created the object
!        @return the SDSI object represented
!        @exception SexpParseException if the SexpList can not be successfully parsed into a SDSIObject
     */
    public static SDSIObject principalParse(SexpList l, SDSIPrincipal p) throws SexpParseException{
      String type = l.getType();
***************
*** 55,60 ****
--- 81,92 ----
          return new KeyHolder(l,p);
        if (type.equals("name"))
          return new Name(l,p);
+       if (type.equals(Quoting.LABEL))
+         return new Quoting(l,p);
+       if (type.equals(PseudoPrincipal.LABEL))
+         return new PseudoPrincipal(l,p);
+       if (type.equals(ThresholdSubject.LABEL))
+         return new ThresholdSubject(l,p);
        else
          return SDSIObject.parse(l);
      }
***************
*** 71,78 ****
         Parses the SexpList in the argument and returns the appropriate subclass
         of SDSIObject that has been initialized by the SexpList.  
         @param l the SexpLIst to be parsed.
!        @return the SDSI objecet represented
!        @exception SexpParseException if the SexpList can not be succesfully parsed into a SDSIObject
     */
    private static SDSIObject parse(SexpList l) throws SexpParseException, SDSIException{
      String type = l.getType();
--- 103,110 ----
         Parses the SexpList in the argument and returns the appropriate subclass
         of SDSIObject that has been initialized by the SexpList.  
         @param l the SexpLIst to be parsed.
!        @return the SDSI object represented
!        @exception SexpParseException if the SexpList can not be successfully parsed into a SDSIObject
     */
    private static SDSIObject parse(SexpList l) throws SexpParseException, SDSIException{
      String type = l.getType();
***************
*** 162,165 ****
--- 194,260 ----
    public SexpList getSrep() {
      return srep;
    }
+ 
+ 	/**
+ 	 * Compares two SDSIObjects based on their canonical Sexp
+ 	 * representations.
+ 	 *
+ 	 * TODO: performance tweaks:
+ 	 * It may be faster (certainly fewer byte[] allocations in
+ 	 * ByteBuffer) to just implement equals() recursively.
+ 	 *
+ 	 * It may also be faster to cache the canonically-expanded srep, but
+ 	 * that could waste a lot of memory if we aren't really clever about
+ 	 * letting sub-sexps borrow their parent's buffer space.
+ 	 *
+ 	 * @author Jon Howell jonh@cs.dartmouth.edu
+ 	 */
+ 	public boolean equals(Object o) {
+ //		Tools.Timer t = new Tools.Timer();
+ 		if (o==this) {
+ 			return true;
+ 		} else if (o instanceof SDSIObject) {
+ 			SDSIObject sobject = (SDSIObject) o;
+ 
+ 			ByteBuffer bb0 = new ByteBuffer();
+ 			ByteBuffer bb1 = new ByteBuffer();
+ 			getSrep().getCanonRep(bb0);
+ 			sobject.getSrep().getCanonRep(bb1);
+ 			return bb0.equals(bb1);
+ 
+ // Sanity-checking on ByteBuffer (this was ByteBuffer's first client)
+ //			if (!java.util.Arrays.equals(bb0.toByteArray(),
+ //					getSrep().getCanonRep())) {
+ //				throw new RuntimeException("crud ByteBuffer broke");
+ //			}
+ //			if (!java.util.Arrays.equals(bb1.toByteArray(),
+ //					sobject.getSrep().getCanonRep())) {
+ //				throw new RuntimeException("crud ByteBuffer broke");
+ //			}
+ //			System.out.println("ByteBuffer alive and well");
+ 		} else {
+ 			return false;
+ 		}
+ //		System.out.println("SDSIObject.equals: "+t);
+ 	}
+ 
+ 	/**
+ 	 * Computes a hashCode of a SDSIPrivateKey based on its canonical
+ 	 * Sexp representation.
+ 	 * I think SDSIObjects are supposed to be immutable, so we cache
+ 	 * this hashCode value to save future recursive expansions of
+ 	 * the Srep.
+ 	 *
+ 	 * @author Jon Howell jonh@cs.dartmouth.edu
+ 	 */
+ 	int cachedHashCode = -1;	// note there's one hash value (-1) that
+ 								// will cause poor performance. :v/
+ 	public int hashCode() {
+ 		if (cachedHashCode==-1) {
+ 			ByteBuffer bb0 = new ByteBuffer();
+ 			srep.getCanonRep(bb0);
+ 			cachedHashCode = bb0.hashCode();
+ 		}
+ 		return cachedHashCode;
+ 	}
  }  
diff -r -c3 sdsi/SDSIPrivateKey.java sdsi-new/SDSIPrivateKey.java
*** sdsi/SDSIPrivateKey.java	Wed Jun  3 10:36:20 1998
--- sdsi-new/SDSIPrivateKey.java	Thu Mar 30 16:33:04 2000
***************
*** 49,53 ****
    public String toShortString() {
      return "Private Key";
    }
- 
  }
--- 49,52 ----
diff -r -c3 sdsi/SDSIRSAPrivateKey.java sdsi-new/SDSIRSAPrivateKey.java
*** sdsi/SDSIRSAPrivateKey.java	Wed Jun  3 10:36:24 1998
--- sdsi-new/SDSIRSAPrivateKey.java	Thu Mar 30 16:36:04 2000
***************
*** 4,10 ****
  import java.security.interfaces.*;
  import java.math.*;
  
! public class SDSIRSAPrivateKey extends SDSIPrivateKey implements RSAPrivateKey {
    byte[] modulus;
    byte[] exponent; 
    
--- 4,14 ----
  import java.security.interfaces.*;
  import java.math.*;
  
! public class SDSIRSAPrivateKey
! 	extends SDSIPrivateKey
! 	implements RSAPrivateKey,
! 		CryptixRSAPrivateKey /* jonh */
! 		{
    byte[] modulus;
    byte[] exponent; 
    
***************
*** 50,58 ****
      if (!eDefined || !nDefined)
        throw new SexpParseException("Must define exponent and modulus in RSA Private Key");
    }
!   public SDSIRSAPrivateKey(RSAPrivateKey k) {
      modulus = k.getModulus().toByteArray();
      exponent = k.getExponent().toByteArray();
      Sexp[] eParts = new Sexp[2];
      eParts[0] = new SexpString("e");
      eParts[1] = new SexpString(exponent);
--- 54,93 ----
      if (!eDefined || !nDefined)
        throw new SexpParseException("Must define exponent and modulus in RSA Private Key");
    }
! 
! 	// [jonh] I think Cryptix 3.1 has a bug in that CryptixRSAPrivateKey
! 	// extends RSAKey and PrivateKey, but not RSAPrivateKey.
! 	// This extra constructor accepts a CryptixRSAPrivateKey directly,
! 	// but is basically identical to the original ctor below. (Other
! 	// than the one commented change to deal with a changed interface.)
! 
!   public SDSIRSAPrivateKey(CryptixRSAPrivateKey k) {
      modulus = k.getModulus().toByteArray();
      exponent = k.getExponent().toByteArray();
+ 		// this is the call (getExponent) that's different btwn cryptix 3.1
+ 		// and jdk1.2.
+     Sexp[] eParts = new Sexp[2];
+     eParts[0] = new SexpString("e");
+     eParts[1] = new SexpString(exponent);
+     Sexp[] nParts = new Sexp[2];
+     nParts[0] = new SexpString("n");
+     nParts[1] = new SexpString(modulus);
+     Sexp[] rsaParts = new Sexp[3];
+     rsaParts[0] = new SexpString("rsa-pkcs1-md5");
+     rsaParts[1] = new SexpList(eParts);
+     rsaParts[2] = new SexpList(nParts);
+     Sexp[] keyParts = new Sexp[2];
+     keyParts[0] = new SexpString("private-key");
+     keyParts[1] = new SexpList(rsaParts);
+     
+     srep = new SexpList(keyParts);
+   }
+ 
+   public SDSIRSAPrivateKey(RSAPrivateKey k) {
+     modulus = k.getModulus().toByteArray();
+     exponent = k.getPrivateExponent().toByteArray();
+ 		// jonh: interface has apparently changed since the version this
+ 		// was coded to. I'm compiling against jdk1.2.
      Sexp[] eParts = new Sexp[2];
      eParts[0] = new SexpString("e");
      eParts[1] = new SexpString(exponent);
***************
*** 81,87 ****
--- 116,126 ----
    public BigInteger getModulus() {
      return new BigInteger(modulus);
    }
+   public BigInteger getPrivateExponent() {
+ 	return getExponent();
+   }
    public BigInteger getExponent() {
+ 	// jonh: and restored to be Cryptix-compatible. What a mess.
      return new BigInteger(exponent);
    }
  }  
diff -r -c3 sdsi/SDSIRSAPublicKey.java sdsi-new/SDSIRSAPublicKey.java
*** sdsi/SDSIRSAPublicKey.java	Wed Jun  3 10:36:26 1998
--- sdsi-new/SDSIRSAPublicKey.java	Thu Mar 30 12:04:22 2000
***************
*** 5,11 ****
  import java.math.*;
  import java.security.*;
  
! public class SDSIRSAPublicKey extends SDSIPublicKey implements RSAPublicKey {
    byte[] modulus;
    byte[] exponent; 
    
--- 5,19 ----
  import java.math.*;
  import java.security.*;
  
! public class SDSIRSAPublicKey
! 	extends SDSIPublicKey
! 	implements RSAPublicKey,
! 		CryptixRSAPublicKey /* jonh */ {
! 
! 	public BigInteger getExponent() {	// jonh big hack to work with cryptix
! 		return getPublicExponent();
! 	}
! 
    byte[] modulus;
    byte[] exponent; 
    
***************
*** 50,58 ****
      if (!eDefined || !nDefined)
        throw new SexpParseException("Must define exponent and modulus in RSA Public Key");
    }
!   public SDSIRSAPublicKey(RSAPublicKey k) {
      modulus = k.getModulus().toByteArray();
      exponent = k.getExponent().toByteArray();
      Sexp[] eParts = new Sexp[2];
      eParts[0] = new SexpString("e");
      eParts[1] = new SexpString(exponent);
--- 58,93 ----
      if (!eDefined || !nDefined)
        throw new SexpParseException("Must define exponent and modulus in RSA Public Key");
    }
!   // [jonh] workaround interface decl bug in Cryptix 3.1
!   // see related comment near constructors for SDSIRSAPrivateKey.
!   // Exactly the same code as the other (original) constructor;
!   // just a different interface. Hmm.
!   public SDSIRSAPublicKey(java.security.interfaces.CryptixRSAPublicKey k) {
      modulus = k.getModulus().toByteArray();
      exponent = k.getExponent().toByteArray();
+ 		// [jonh] okay, this line isn't exactly the same, because the
+ 		// interface changed in jdk1.2
+     Sexp[] eParts = new Sexp[2];
+     eParts[0] = new SexpString("e");
+     eParts[1] = new SexpString(exponent);
+     Sexp[] nParts = new Sexp[2];
+     nParts[0] = new SexpString("n");
+     nParts[1] = new SexpString(modulus);
+     Sexp[] rsaParts = new Sexp[3];
+     rsaParts[0] = new SexpString("rsa-pkcs1-md5");
+     rsaParts[1] = new SexpList(eParts);
+     rsaParts[2] = new SexpList(nParts);
+     Sexp[] keyParts = new Sexp[2];
+     keyParts[0] = new SexpString("public-key");
+     keyParts[1] = new SexpList(rsaParts);
+     
+     srep = new SexpList(keyParts);
+   }
+ 
+   public SDSIRSAPublicKey(RSAPublicKey k) {
+     modulus = k.getModulus().toByteArray();
+     exponent = k.getPublicExponent().toByteArray();
+ 		// jonh: interface has changed
      Sexp[] eParts = new Sexp[2];
      eParts[0] = new SexpString("e");
      eParts[1] = new SexpString(exponent);
***************
*** 81,87 ****
    public BigInteger getModulus() {
      return new BigInteger(modulus);
    }
!   public BigInteger getExponent() {
      return new BigInteger(exponent);
    }
    public String toShortString() {
--- 116,123 ----
    public BigInteger getModulus() {
      return new BigInteger(modulus);
    }
!   public BigInteger getPublicExponent() {
! 	// jonh: interface changed
      return new BigInteger(exponent);
    }
    public String toShortString() {
diff -r -c3 sdsi/SDSISignature.java sdsi-new/SDSISignature.java
*** sdsi/SDSISignature.java	Wed Jun  3 10:36:30 1998
--- sdsi-new/SDSISignature.java	Thu Mar 30 08:09:56 2000
***************
*** 5,10 ****
--- 5,12 ----
  import java.math.*;
  import java.util.*;
  
+ import Tools.Timer;
+ 
  public class SDSISignature extends SDSIObject {
    SDSIPrincipal principal;
    Hash hashOfObject;
***************
*** 13,24 ****
--- 15,28 ----
                         SDSIPrivateKey privKey, 
                         SDSIPublicKey pubKey) throws SignatureException{
      try {
+ //  Timer t = new Timer();
        this.principal = pubKey; 
        this.hashOfObject = new Hash("md5",signedObject);
        Signature privSign = Signature.getInstance(privKey.getAlgorithm());
        privSign.initSign(privKey);
        privSign.update(signedObject.getSrep().getCanonRep());
        byte[] signature = privSign.sign();
+ //  System.out.println("Public key signature: "+t);
        Sexp[] sigParts = new Sexp[4];
        sigParts[0] = new SexpString("signature");
        sigParts[1] = hashOfObject.getSrep();
***************
*** 63,68 ****
--- 67,76 ----
    public String getType() {
      return "Signature";
    }
+   /**
+    * Returns the public part of the key crafted this signature; this is the
+    * public key that can verify the signature.
+    */
    public SDSIPrincipal getPrincipal() {
      return principal;
    }
***************
*** 76,84 ****
--- 84,130 ----
    public byte[] getSignatureValue() { //need to worry about display type???
      return ((SexpString)srep.elementAt(3)).bytesContent(); 
    }
+ 
+   /**
+    * Automatically dispatch based on type of verifyPrincipal.
+    *
+    * <p> jonh wonders why these routines can 'return false' AND
+    * throw exceptions -- there should be only one form for success and
+    * failure, so that the contract is clear to the caller.
+    */
+   public boolean verify(SDSIPrincipal verifyPrincipal, SDSIObject objToVerify)
+ 	throws SexpParseException, NoSuchAlgorithmException,
+ 	SignatureException, InvalidKeyException {
+ 	if (verifyPrincipal instanceof SDSIPublicKey) {
+ 		return verify((SDSIPublicKey) verifyPrincipal, objToVerify);
+ 	} else if (verifyPrincipal instanceof Hash) {
+ 		return verify((Hash) verifyPrincipal, objToVerify);
+ 	} else {
+       throw new SignatureException("What am I supposed to do with this thing? "
+ 		+verifyPrincipal.getClass());
+ 	}
+   }
+ 
+   /**
+    * Caller provides only a hash of the key they want to be sure this
+    * signature represents; that means our principal had better actually
+    * be a public key, so we have something to verify with! 
+    */
+   public boolean verify(Hash verifyKeyHash, SDSIObject objToVerify)
+ 	throws SexpParseException, NoSuchAlgorithmException,
+ 	SignatureException, InvalidKeyException {
+ 
+ 	if (principal instanceof SDSIPublicKey) {
+ 		return verify((SDSIPublicKey) principal, objToVerify);
+ 	} else {
+       throw new SignatureException("No public key available to check signature with.");
+ 	}
+   }
+ 
    public boolean verify(SDSIPublicKey verifyKey, SDSIObject objToVerify) throws SexpParseException, NoSuchAlgorithmException,
                                              SignatureException, InvalidKeyException {
      //watch for cast class exceptions when using SexpString/SexpList
+ //	Timer t = new Timer();
      byte[] sig = this.getSignatureValue();
      Signature verifySign = Signature.getInstance(verifyKey.getAlgorithm());
      verifySign.initVerify(verifyKey);
***************
*** 95,103 ****
      }
      //Checking Hash
      Hash HashObjToVerify = new Hash(hashOfObject.getHashID(),objToVerify);
!     if (hashOfObject.equals(HashObjToVerify))
!       return verifySign.verify(sig);
!     else
        throw new SignatureException("Hash in signature doesn't match hash of object"); //might want to treat this differently
    }
  }
--- 141,152 ----
      }
      //Checking Hash
      Hash HashObjToVerify = new Hash(hashOfObject.getHashID(),objToVerify);
!     if (hashOfObject.equals(HashObjToVerify)) {
!       boolean result = verifySign.verify(sig);
! //	  System.out.println("Public key signature verify: "+t);
!       return result;
!     } else {
        throw new SignatureException("Hash in signature doesn't match hash of object"); //might want to treat this differently
+   	}
    }
  }
Only in sdsi-new: SignedCertificate.java
Only in sdsi-new: TEByteString.java
Only in sdsi-new: TEList.java
Only in sdsi-new: TENull.java
Only in sdsi-new: TEParse.java
Only in sdsi-new: TEPrefix.java
Only in sdsi-new: TERange.java
Only in sdsi-new: TESDSIObject.java
Only in sdsi-new: TESet.java
Only in sdsi-new: TESpecial.java
Only in sdsi-new: TEStar.java
diff -r -c3 sdsi/Tag.java sdsi-new/Tag.java
*** sdsi/Tag.java	Wed Jun  3 10:36:36 1998
--- sdsi-new/Tag.java	Thu May 25 21:05:32 2000
***************
*** 1,290 ****
! package sdsi;  //should extend SDSIObject????
  
  import sdsi.sexp.*;
  import java.io.*;
  
! public class Tag extends SDSIObject {
!   TagExpression t;  //may not want to carry this around 
!   //may just want to create it when needed and once at the beginning to check formatting
!   public Tag() {//the (*) tag with no S-exp representation
!     t = new TagStar();
!     srep = new SexpList(new Sexp[] {new SexpString("tag"),
!                                     new SexpList(new Sexp[] {new SexpString("*")})}); 
!   }
!   public Tag(SexpList l) throws SexpParseException{
!     super(l);
!     if (!(l.size() == 2)) 
!       throw new SexpParseException("Incorrectly formatted tag");
!     SexpList pTagStar;
!     if (l.elementAt(1) instanceof SexpList 
!        && (pTagStar = ((SexpList)l.elementAt(1))).size() == 1 
!        && pTagStar.elementAt(0) instanceof SexpString 
!        && ((SexpString)pTagStar.elementAt(0)).stringContent().equals("*"))
!       t = new TagStar();
!     else
!       t = TagExpression.parse(l.elementAt(1));
!   }
!   public String toShortString() {
!     String s = srep.toReadableString(0,200,0);
!     return s.substring(5,(s.length() < 21) ? s.length()-1 : 20);
!   }
!   public boolean intersect(Tag starFree) { //don't really like this
!     TagExpression sf = starFree.t;
!     if (t.intersect(sf) != null)
!       return true;
!     else
!       return false;
!   }
!   public abstract static class TagExpression implements Serializable{
!     public static TagExpression parse(Sexp s) throws SexpParseException{
!       if (s instanceof SexpString)
!         return new TagByteString((SexpString)s);
!       else { //s is a SexpList
!         SexpList l = (SexpList) s;
!         if (l.elementAt(0) instanceof SexpList)
!           throw new SexpParseException("First element in tag can't be list");
!         if (((SexpString)l.elementAt(0)).stringContent().equals("*")) {
!           return StarTag.parse(l);
!         }
!         else
!           return new SimpleTag(l);
!       }
!     }
!     public abstract TagExpression intersect(TagExpression starFree);
!   }
!   
!   public static class SimpleTag extends TagExpression{
!     /*  so we don't allow tags that look like
!     ((* set read write) file foo) ?
!     */
!     SexpString first;
!     TagExpression[] rest;
!     public SimpleTag(SexpList l) throws SexpParseException {
!       int size = l.size();
!       first = (SexpString)l.elementAt(0);
!       rest = new TagExpression[size - 1];
!       for (int i =0;i<size-1;i++)
!         rest[i] = TagExpression.parse(l.elementAt(i+1));
!     }
!     public TagExpression intersect(TagExpression starFree) {
!       if (starFree instanceof StarTag)
!         return null;
!       else {
!         if (starFree instanceof SimpleTag) {
!           SimpleTag simpTag = (SimpleTag)starFree;
!           if (simpTag.rest.length != this.rest.length) //require lengths equal
!             return null;
!           if (simpTag.first.equals(this.first)) {
!             for (int i = 0;i<this.rest.length;i++) {
!               if ((simpTag.rest[i] = this.rest[i].intersect(simpTag.rest[i])) == null)
!                 return null;
!             }
!             return simpTag;
!           }
!           else
!             return null;
!         }
!         else
!           return null;
!       }
!     }
!   }
!   
!   public abstract static class StarTag extends TagExpression{
!     public static StarTag parse(SexpList l) throws SexpParseException{
!       if (l.size() < 2 || !(l.elementAt(1) instanceof SexpString))
!         throw new SexpParseException("Tag with star not encoded properly");
!       String starType = ((SexpString)l.elementAt(1)).stringContent();
!       if (starType.equals("set"))
!         return new TagSet(l);
!       else if (starType.equals("range"))
!         return new TagRange(l);
!       else if (starType.equals("prefix"))
!         return new TagPrefix(l);
!       else
!         throw new SexpParseException("Unknown star type in tag");
!     }
!   }
!   
!   public static class TagStar extends StarTag{
!     public TagStar() {;}
!     public TagExpression intersect(TagExpression starFree) {
!       if (starFree instanceof StarTag)
!         return null;
!       else 
!         return starFree;
!     }
!   }
!   
!   public static class TagRange extends StarTag{
!     boolean stringCompare = false;
!     boolean strictlyGreater = false;
!     boolean strictlyLess = false;
!     SexpString lowerLimit = null;  //can store these as strings if we're not carrying them everywhere
!     SexpString upperLimit = null;  //same in prefix
!     public TagRange(SexpList l) throws SexpParseException { 
!       int size = l.size();
!       if (!(size == 3 || size ==5 || size == 7)) 
!         throw new SexpParseException("*-range type tag not encoded properly");
!       for (int i=2;i<size;i++) {
!         if (!(l.elementAt(i) instanceof SexpString))
!           throw new SexpParseException("*-range type tag not encoded properly");
!       }  
!       String rangeType = ((SexpString)l.elementAt(2)).stringContent();
!       if (rangeType.equals("alpha") || rangeType.equals("numeric") || rangeType.equals("time")
!                                     || rangeType.equals("binary") || rangeType.equals("date")) {
!         stringCompare = true;
!       }    
!       else
!         throw new SexpParseException("Unknown range type in tag");
!       if (size == 5) {
!         String strictness = ((SexpString)l.elementAt(3)).stringContent();
!         if (strictness.equals("l")) {
!           strictlyLess = true;
!           upperLimit = (SexpString)l.elementAt(4);
!         }
!         else if (strictness.equals("le")) {
!           strictlyLess = false;
!           upperLimit = (SexpString)l.elementAt(4);
!         }
!         else if (strictness.equals("g")) {
!           strictlyGreater = true;
!           lowerLimit = (SexpString)l.elementAt(4);
!         }
!         else if (strictness.equals("ge")) {
!           strictlyGreater = false;
!           lowerLimit = (SexpString)l.elementAt(4);
!         }
!         else 
!           throw new SexpParseException("*-range type tag not encoded properly");
!       }
!       if (size == 7) {
!         String strictness = ((SexpString)l.elementAt(3)).stringContent();
!         if (strictness.equals("g")) 
!           strictlyGreater = true;
!         else if (strictness.equals("ge")) 
!           strictlyGreater = false;
!         else 
!           throw new SexpParseException("*-range type tag not encoded properly");
!         strictness = ((SexpString)l.elementAt(5)).stringContent();
!         if (strictness.equals("l")) 
!           strictlyLess = true;
!         else if (strictness.equals("le")) 
!           strictlyLess = false;
!         else 
!           throw new SexpParseException("*-range type tag not encoded properly");
!         lowerLimit = (SexpString)l.elementAt(4);
!         upperLimit = (SexpString)l.elementAt(6);
!       }
!     }
!     public TagExpression intersect(TagExpression starFree) {
!       if (starFree instanceof StarTag)
!         return null;
!       else {
!         if (!(starFree instanceof TagByteString))
!           return null;
!         SexpString starFreeString = ((TagByteString)starFree).value;
!         try {
!           if (upperLimit != null) { //no upper and lower limit means all range
!             if (strictlyLess) {
!               if (stringCompare)  //may want to move these??
!                 if (starFreeString.compareTo(upperLimit) >= 0)
!                   return null;
!               else
!                 return null;
!             }
!             else {
!               if (stringCompare)
!                 if (starFreeString.compareTo(upperLimit) > 0)
!                   return null;
!               else
!                 return null;
!             }
!           }
!           if (lowerLimit != null) {
!             if (strictlyGreater) {
!               if (stringCompare)
!                 if (starFreeString.compareTo(lowerLimit) <= 0)
!                   return null;
!               else
!                 return null;
!             }
!             else {
!               if (stringCompare)
!                 if (starFreeString.compareTo(upperLimit) < 0)
!                   return null;
!               else 
!                 return null;
!             }
!           }
!          return starFree;
!         }
!         catch (SexpException e) {
!           return null;
!         }
!       }
!     }
!   }
!   
!   public static class TagSet extends StarTag{
!     TagExpression[] components;
!     public TagSet(SexpList l) throws SexpParseException{
!       int size = l.size();
!       components = new TagExpression[size - 2];
!       for (int i =0;i<size-2;i++)
!         components[i] = TagExpression.parse(l.elementAt(i+2));
!     }
!     public TagExpression intersect(TagExpression starFree) {
!       if (starFree instanceof StarTag)
!         return null;
!       else {
!         for (int i = 0;i<components.length;i++) {
!           if (components[i].intersect(starFree) != null)  //this won't work unless intersection returns whole starfree
!             return starFree;
!         }
!         return null;
!       }
!     }
!   }
!   
!   public static class TagPrefix extends StarTag {
!     SexpString prefix;
!     public TagPrefix(SexpList l) throws SexpParseException{
!       if (l.size() != 3 || !(l.elementAt(2) instanceof SexpString))
!         throw new SexpParseException("Tag with *-prefix not encoded properly");
!       prefix = (SexpString)l.elementAt(2);
!     }  
!     public TagExpression intersect(TagExpression starFree) {
!       if (starFree instanceof StarTag)
!         return null;
!       else {
!         if (!(starFree instanceof TagByteString))
!           return null;
!         SexpString starFreeString = ((TagByteString)starFree).value;
!         if (starFreeString.startsWith(prefix))
!           return starFree;
!         else
!           return null;
!       }
!     }   
!   }
!   
!   public static class TagByteString extends TagExpression {
!     SexpString value;
!     public TagByteString(SexpString s) {
!       value = s;
!     }
!     public TagExpression intersect(TagExpression starFree) {
!       if (starFree instanceof StarTag)
!         return null;
!       else {
!         if (!(starFree instanceof TagByteString))
!           return null;
!         if (this.value.equals(((TagByteString)starFree).value))
!           return starFree;
!         else 
!           return null;
!       }
!     }
!   }
  }
--- 1,188 ----
! // reworked by jonh
! 
! package sdsi;
  
  import sdsi.sexp.*;
  import java.io.*;
  
! /**
!  * A Tag object represents an s-expression that begins (tag ...).
!  * TagExpressions are the things inside that Tag object.
!  * So a Tag object is a wrapper for the whole expression.<p>
!  *
!  * This class and its companion classes
!  * TagExpression, TagTest, TE*, RangeComparator, and RC* are all rewritten
!  * by jonh@cs.dartmouth.edu based on my formal semantics for tags
!  * and tag intersection in Chapter {@tex \ref{tag_semantics}} of my
!  * thesis.
!  */
! public class Tag
! 	extends SDSIObject {
! 
! 	TagExpression texp;
! 
! 	/**
! 	 * S-expression label for this data structure.
! 	 */
! 	public static final String LABEL = "tag";
! 
! 	private Tag() {
! 		this(new TEStar());
! 	}
! 	protected static Tag tagStar;
! 
! 	/**
! 	 * Returns (tag *), the tag representing the set of all auths <em>A</em>.
! 	 */
! 	public static Tag getTagStar() {
! 		if (tagStar==null) {
! 			tagStar = new Tag();
! 		}
! 		return tagStar;
! 	}
! 
! 	/**
! 	 * Parse a S-expression into a Tag object.
! 	 */
! 	public Tag(SexpList l)
! 		throws SexpParseException {
! 		super(l);
! 		if (!(l.size()==2)) {
! 			throw new SexpParseException("Incorrectly formatted tag.");
! 		}
! 		if (!l.getType().equals(LABEL)) {
! 			throw new SexpParseException("This thing isn't a tag, it's a "
! 				+l.getType());
! 		}
! 
! 		// There's a funny special case -- (tag *) stands for the set
! 		// of all permissions. For consistency, it should be written
! 		// (tag ()) (an ordered list with no restrictions), but this is
! 		// the official syntax.
! 		// The special form (*) should also be written (), for the same
! 		// reason.
! 		SexpList pTagStar;
! 		if (l.elementAt(1) instanceof SexpString
! 			&& ((SexpString) l.elementAt(1)).stringContent().equals("*")) {
! 			// recognize irritating special case (tag *).
! 			// [but note this constructor preserves the original sexp, so
! 			// if the call was actually (tag (*)), this object will return
! 			// that as its getSrep().]
! 			texp = new TEStar();
! 		} else {
! 			texp = TEParse.parse(l.elementAt(1));
! 		}
! 	}
! 
! 	/**
! 	 * Wrap a tag expression in a Tag wrapper.
! 	 */
! 	Tag(TagExpression texp) {
!     	this.texp = texp;
! 		Sexp tagArgument;
! 
! 		if (texp instanceof TEStar) {
! 			// irritating special case of (tag *), which is
! 			// equivalent to (tag (*)), but represented differently.
! 			tagArgument = new SexpString("*");
! 		} else {
! 			tagArgument = texp.getSexp();
! 		}
!     	srep = new SexpList(
! 				new Sexp[] {
! 					new SexpString(LABEL),
! 					tagArgument
! 				}
! 			   );
! 	}
! 
! 	/**
! 	 * Get the special tag representing no authorization (an empty set,
! 	 * or {@tex $A_{\textit{null}}$).
! 	 */
! 	public static Tag getNullTag() {
! 		return new Tag(TENull.getNull());
! 	}
! 
! 	/**
! 	 * Returns the first 15ish characters of the tag representation
! 	 * as a String.
! 	 */
! 	public String toShortString() {
! 		String s = srep.toReadableString(0,200,0);
! 		return s.substring(5,(s.length() < 21) ? s.length()-1 : 20);
! 	}
! 
! 	/**
! 	 * Returns a tag that represents the set formed from the
! 	 * intersection of the sets represented by this tag and the
! 	 * otherTag. (Got that?)
! 	 * If there is ``no intersection'' (as the SPKI document calls it),
! 	 * the resulting tag will return true when asked isNull().
! 	 */
! 	public Tag intersect(Tag otherTag) {
! 		TagExpression texpIntersection = texp.intersect(otherTag.texp);
! 		return new Tag(texpIntersection);
! 	}
! 
! 	/**
! 	 * Return a tag that represents the union of the auths represented
! 	 * by <code>this</code> tag and <code>otherTag</code>. The new
! 	 * tag is simply the {@tex $A_{\textit{set}}$} of the original two
! 	 * tags.
! 	 *
! 	 * @todo This method has not even been remotely thought through
! 	 * carefully. There's probably some optimal way to build unions in
! 	 * the tag grammar.
! 	 */
! 	public Tag union(Tag otherTag) {
! 		TESet texpUnion = new TESet(new TagExpression[] {
! 			texp,
! 			otherTag.texp });
! 		return new Tag(texpUnion);
! 	}
! 
! 	/**
! 	 * Return true if this tag represents the null set of auths
! 	 * {@tex $A_{\textit{null}}$.
! 	 */
! 	public boolean isNull() {
! 		return (texp instanceof TENull);
! 	}
! 
! 	/**
! 	 * Returns true if otherTag represents a subset of the set
! 	 * represented by this tag. The test is performed by intersecting
! 	 * the two and seeing if you get back otherTag.
! 	 * <p>
! 	 * Comments:<ol>
! 	 * <li>The test is sound, but I'm not sure that it is complete.
! 	 * Might there be times when the thing you get back is logically
! 	 * equivalent to this tag, but not syntactically equivalent?
! 	 * 
! 	 * <li>The original SDSI code had a
! 	 *		<code>boolean intersects()</code>
! 	 * method that returned true if this Tag and <code>otherTag</code>
! 	 * intersect to something other than the empty set (TENull). You'd
! 	 * think this would be a good way to test membership of a request
! 	 * in a restriction set, but what if the request is a bigger set
! 	 * than the restriction set? That's a weird way to structure
! 	 * requests, but in some circumstances it may be meaningful. So we
! 	 * really want to test whether otherTag is a subset of this tag,
! 	 * hence this method.
! 	 * 
! 	 * <li>if otherTag.isNull(), this test will always succeed. (And
! 	 * rightfully so.)
! 	 * </ol>
! 	 */
! 	public boolean hasSubset(Tag otherTag) {
! 		// original sdsi-style test was:
! 		// return (!(texpIntersection instanceof TENull));
! 
! 		Tag intersection = intersect(otherTag);
! 
! 		// the .equals() method is that of SDSIObject, which calls .equals
! 		// on the s-expressions, so the test is for syntactic equality.
! 		return intersection.equals(otherTag);
! 	}
  }
Only in sdsi-new: TagExpression.java
Only in sdsi-new: TagTest.java
Only in sdsi-new: ThresholdSubject.java
diff -r -c3 sdsi/Tuple.java sdsi-new/Tuple.java
*** sdsi/Tuple.java	Wed Jun  3 10:36:38 1998
--- sdsi-new/Tuple.java	Thu May 25 21:05:58 2000
***************
*** 1,5 ****
--- 1,13 ----
  package sdsi;
  
+ /**
+  * Changed Morcos' class to use a more meaningful intersection test
+  * than just ``has a non-null intersection.'' See dissertation
+  * Section {@tex \ref{tag_meaning_intersection}}.
+  *
+  * @author changed by jonh@cs.dartmouth.edu
+  * @classSummaryOnly true
+  */
  public class Tuple {
    
    boolean namingPermission;
***************
*** 18,24 ****
      this.propagate = c.delegate;
      this.subject = subject;
      this.issuer = issuer;
!     if (c.t.intersect(request))
        this.t = request;
      else
        this.t = null;
--- 26,32 ----
      this.propagate = c.delegate;
      this.subject = subject;
      this.issuer = issuer;
!     if (c.t.hasSubset(request))
        this.t = request;
      else
        this.t = null;
***************
*** 42,48 ****
    
    public void add(Tuple p) throws VerificationException {
      v.update(p.v);
!     if (!p.t.intersect(this.t)) 
        throw new VerificationException("Certificate tag does not match request");
      /*Note at this point p will only have one name where as this may have more than one*/
      /*Named subsequences may change this*/
--- 50,56 ----
    
    public void add(Tuple p) throws VerificationException {
      v.update(p.v);
!     if (!p.t.hasSubset(this.t)) 
        throw new VerificationException("Certificate tag does not match request");
      /*Note at this point p will only have one name where as this may have more than one*/
      /*Named subsequences may change this*/
***************
*** 96,99 ****
      
  }
      
!     
\ No newline at end of file
--- 104,107 ----
      
  }
      
!     
diff -r -c3 sdsi/control/SDSIMainFrame.java sdsi-new/control/SDSIMainFrame.java
*** sdsi/control/SDSIMainFrame.java	Wed Jun  3 10:34:10 1998
--- sdsi-new/control/SDSIMainFrame.java	Mon Jan 10 11:29:18 2000
***************
*** 76,82 ****
  		panelObjList.setLayout(new BorderLayout(0,0));
  		Label objListLabel = new Label("Current Objects");
  		panelObjList.add("North", objListLabel);
! 		objectList = new List(10,false);
  		panelObjList.add("Center", objectList);
  
  		panelObjects = new Panel();
--- 76,85 ----
  		panelObjList.setLayout(new BorderLayout(0,0));
  		Label objListLabel = new Label("Current Objects");
  		panelObjList.add("North", objListLabel);
! 		objectList = new java.awt.List(10,false);
! 			// jonh: vile jdk1.2 introduces a new java.util.List interface,
! 			// requiring the source code to explicitly disambiguate between
! 			// the two when importing both packages.
  		panelObjList.add("Center", objectList);
  
  		panelObjects = new Panel();
***************
*** 298,304 ****
  	Panel panelDisplay;
  	TextArea display;
  	Panel panelObjList;
! 	List objectList;
  
  	Panel controls;
  	CardLayout cards;
--- 301,307 ----
  	Panel panelDisplay;
  	TextArea display;
  	Panel panelObjList;
! 	java.awt.List objectList;
  
  	Panel controls;
  	CardLayout cards;
***************
*** 659,666 ****
  		  KeyPair kp = kpg.generateKeyPair();
  		  PublicKey pubKey = kp.getPublic();
  		  PrivateKey privKey = kp.getPrivate();
! 		  SDSIRSAPrivateKey sdsiPrivKey = new SDSIRSAPrivateKey((RSAPrivateKey)privKey);
! 		  SDSIRSAPublicKey sdsiPubKey = new SDSIRSAPublicKey((RSAPublicKey)pubKey);
  		  current = sdsiPrivKey;
  		  display.setText(current.toReadableString(display.getColumns()));
  		  saveSexpMenuItem_Action(null,"Private Key");
--- 662,671 ----
  		  KeyPair kp = kpg.generateKeyPair();
  		  PublicKey pubKey = kp.getPublic();
  		  PrivateKey privKey = kp.getPrivate();
! 			// jonh: Cryptix 3.0 renames these classes from RSAPrivateKey,
! 			// since that name got taken over by jdk1.2
! 		  SDSIRSAPrivateKey sdsiPrivKey = new SDSIRSAPrivateKey((CryptixRSAPrivateKey)privKey);
! 		  SDSIRSAPublicKey sdsiPubKey = new SDSIRSAPublicKey((CryptixRSAPublicKey)pubKey);
  		  current = sdsiPrivKey;
  		  display.setText(current.toReadableString(display.getColumns()));
  		  saveSexpMenuItem_Action(null,"Private Key");
***************
*** 727,741 ****
--- 732,749 ----
  	{
  		String f1 = file1.getText();
  		String f2 = file2.getText();
+ 		  System.out.println("debug A");
  		if (f1.equals("") || f2.equals("")) {
  		  new ErrorDialog(this,"File Error","Please specify both a Public Key and a Private Key").setVisible(true);
  		  return;
  		}
  		try {
+ 		  System.out.println("debug B");
  		  PushbackInputStream p = new PushbackInputStream(new FileInputStream(f1));
  		  SDSIObject o = processStream(p,false);
  		  SDSIPublicKey pub_key;
  		  SDSIPrivateKey priv_key;
+ 		  System.out.println("debug C");
  		  if (o != null && o instanceof SDSIPublicKey )
  		    pub_key = (SDSIPublicKey) o;
  		  else {
***************
*** 743,761 ****
--- 751,773 ----
  		    //take out the object used to be here
  		    return;
  		  }
+ 		  System.out.println("debug D");
  		  p = new PushbackInputStream(new FileInputStream(f2));
  		  o = processStream(p,false);
  		  if (o == null) {
  		    new ErrorDialog(this,"SDSIObject Error","Private key file must contain a private key").setVisible(true);
  		    return;
  		  }
+ 		  System.out.println("debug E");
  		  if (o instanceof SDSIPrivateKey) {
+ 		  System.out.println("debug E.1");
  		    priv_key = (SDSIPrivateKey) o;
  		    Signature sign = Signature.getInstance("MD5/RSA");
  		    Signature verify = Signature.getInstance("MD5/RSA");
          sign.initSign(priv_key);
          verify.initVerify(pub_key);
          byte[] test = new String("Babbaloo Babbaloo Hey How About You?").getBytes();
+ 		  System.out.println("debug F");
          sign.update(test);
          verify.update(test);
          if (verify.verify(sign.sign())) {
***************
*** 767,776 ****
--- 779,790 ----
            new ErrorDialog(this,"Identity Error","Public Key and Private Key do not match").setVisible(true);
  		  }
  		  else {
+ 		  System.out.println("debug E.2");
  		    new ErrorDialog(this,"SDSIObject Error","Private key file must contain a private key").setVisible(true);
  		    return;
  		  }
  		  status.setText("Identity set");
+ 		  System.out.println("debug G");
  		}
      catch (IOException e) {
        new ErrorDialog(this,"I/O Error",e.getMessage()).setVisible(true);
***************
*** 779,786 ****
        new ErrorDialog(this,"Missing algorithm",e.getMessage()).setVisible(true);
      }
      catch (Exception e){
!       new ErrorDialog(this,"Fatal Error",e.getMessage());
      }
  	}
  
  	void identityMenuItem_Action(ActionEvent event)
--- 793,801 ----
        new ErrorDialog(this,"Missing algorithm",e.getMessage()).setVisible(true);
      }
      catch (Exception e){
!       new ErrorDialog(this,"Fatal Error",e.getMessage()).setVisible(true);
      }
+ 		  System.out.println("debug H");
  	}
  
  	void identityMenuItem_Action(ActionEvent event)
Only in sdsi-new/control: makefile
Only in sdsi-new: makefile
Only in sdsi-new: package.html
diff -r -c3 sdsi/sexp/Sexp.java sdsi-new/sexp/Sexp.java
*** sdsi/sexp/Sexp.java	Wed Jun  3 10:34:36 1998
--- sdsi-new/sexp/Sexp.java	Wed Apr  5 06:53:58 2000
***************
*** 1,6 ****
--- 1,7 ----
  package sdsi.sexp;
  
  import java.io.*;
+ import Tools.ByteBuffer;
  
  /** Abstract class to represent S-expressions.  There are two subclasses
      to represent byte-string or list S-expressions.
***************
*** 207,228 ****
    /** Calculates the length of the canonical representation of this S-expression.
        @return the length of the canonical representation.*/
    public abstract int getCanonLen();
!   /** Generates the canonical representation of this S-expression.
!       @return a byte array containing exactly the canonical representation.*/
!   public abstract byte[] getCanonRep();
   /** Returns a string representation of this S-expression.
       Possibly just the a String which represents the canonical-form.
       @return a string representation of this S-expression.
       */
    public String toString() {
      String s = null;
!     try {
!       s = new String(this.getCanonRep(),"8859_1");
!     }
!     catch (UnsupportedEncodingException e){
!       System.out.println("Unsupported Encoding, huh?");
!     }
!     return s;
    }
    /** Returns a readable string representation of this S-expression.
        Given format parameters, returns a nicely formatted readable representation
--- 208,251 ----
    /** Calculates the length of the canonical representation of this S-expression.
        @return the length of the canonical representation.*/
    public abstract int getCanonLen();
! 	/**
! 	 * Generates the canonical representation of this S-expression.
! 	 * 
! 	 * @return an int equal to the length of the canonical representation.
! 	 * 
! 	 * @author jonh@cs.dartmouth.edu changed to call ByteBuffer version.
! 	 */
! 	public byte[] getCanonRep() {
! 		ByteBuffer bb = new ByteBuffer();
! 		getCanonRep(bb);
! 		return bb.toByteArray();
! 	}
! 
! 	/**
! 	 * concatenates the canonical representation of this S-expression onto
! 	 * ByteBuffer bb. This is more efficient when building up the canonrep
! 	 * of a big tree than a tree of calls to getCanonRep with intervening
! 	 * copies into new byte[]s.
! 	 * 
! 	 * @author jonh 
! 	 */
!   public abstract void getCanonRep(ByteBuffer bb);
! 
   /** Returns a string representation of this S-expression.
       Possibly just the a String which represents the canonical-form.
       @return a string representation of this S-expression.
+ 	 @author jonh changed this to return a readable representation.
       */
    public String toString() {
      String s = null;
! //    try {
! //      s = new String(this.getCanonRep(),"8859_1");
! //    }
! //    catch (UnsupportedEncodingException e){
! //      System.out.println("Unsupported Encoding, huh?");
! //    }
! //    return s;
! 		return toReadableString(0, 72, 0);
    }
    /** Returns a readable string representation of this S-expression.
        Given format parameters, returns a nicely formatted readable representation
***************
*** 233,239 ****
        @param last the number of spaces that should be left at the end of every line (for possible closing parens).
        @return a nicely formatted string representation of this S-expression.
    */
!   public abstract String toReadableString(int offset, int width, int last);
    abstract int getReadableLen();
   /** Returns a string representation of the canonical form of this S-expression.
       @return a string representation of the canoical form of this S-expression.
--- 256,274 ----
        @param last the number of spaces that should be left at the end of every line (for possible closing parens).
        @return a nicely formatted string representation of this S-expression.
    */
! 	/**
! 	 * @author jonh modified this to be a call to the recursively-efficient
! 	 * version.
! 	 */
! 	public String toReadableString(int offset, int width, int last) {
! 		StringBuffer sb = new StringBuffer();
! 		toReadableString(sb, offset, width, last);
! 		return sb.toString();
! 	}
! 
! 	public abstract void toReadableString(StringBuffer sb,
! 		int offset, int width, int last);
! 
    abstract int getReadableLen();
   /** Returns a string representation of the canonical form of this S-expression.
       @return a string representation of the canoical form of this S-expression.
***************
*** 325,328 ****
--- 360,371 ----
        throw new SexpException("There has been an input/output error reading a base64 rep in Sexp.parse");
      } 
    }
+ 
+ 	static String buildOffsetStr(int offset) {
+ 		// Build an offset string with which to break up long StringBuffer
+ 		StringBuffer offsetPart = new StringBuffer("\n");
+ 		for (int j=0;j<offset;j++)
+ 			offsetPart.append(" ");
+ 		return offsetPart.toString();
+ 	}
  }
diff -r -c3 sdsi/sexp/SexpList.java sdsi-new/sexp/SexpList.java
*** sdsi/sexp/SexpList.java	Wed Jun  3 10:34:40 1998
--- sdsi-new/sexp/SexpList.java	Mon Apr  3 14:22:02 2000
***************
*** 2,7 ****
--- 2,9 ----
  
  import java.util.*;
  import java.io.*;
+ import Tools.ByteBuffer;
+ 
  /**
     This class is used to represent S-Expressions which are not simple byte-strings.
     That is they are lists of other S-Expressions.
***************
*** 21,26 ****
--- 23,77 ----
      for (int i=0;i<expressions.length;i++)
        elements.addElement(expressions[i]);
    }
+ 
+ 	/**
+ 	 * Create an empty SexpList
+ 	 */
+ 	public SexpList() {
+ 		elements = new Vector();
+ 	}
+ 
+ 	/**
+ 	 * A constructor to extend one list by another Sexp
+ 	 * @author jonh@cs.dartmouth.edu
+ 	 */
+ 	public SexpList(SexpList base, Sexp extra) {
+ 		elements = new Vector(base.elements);
+ 		elements.add(extra);
+ 	}
+ 
+ 	/**
+ 	 * Use this helper method to incrementally build up a SexpList.
+ 	 * With the () constructor, this makes building SexpLists easy:
+ 	 * <pre>
+ 	 * SexpList l = new SexpList().append(x).append(y).append(z);
+ 	 * </pre>
+ 	 * @author jonh@cs.dartmouth.edu
+ 	 */
+ 	public SexpList append(Sexp extra) {
+ 		return new SexpList(this, extra);
+ 	}
+ 
+ 	/**
+ 	 * Use this helper method to append a new SexpString to the end
+ 	 * of a SexpList.
+ 	 * This method makes building SexpLists made of strings <em>really</em>
+ 	 * easy.
+ 	 * <pre>
+ 	 * SexpList l = new SexpList().append("x").append("y").append("z");
+ 	 * </pre>
+ 	 * It wasn't hard to do this anyway by using the parse constructors
+ 	 * (and a helper method that turned your string into a stupid
+ 	 * PushbackInputStream), but this is nice when the strings aren't
+ 	 * necessarily legal Sexp tokens -- since we use
+ 	 * <code>new SexpString(...)</code>, the string will be encoded safely
+ 	 * in any case.
+ 	 * @author jonh@cs.dartmouth.edu
+ 	 */
+ 	public SexpList append(String str) {
+ 		return new SexpList(this, new SexpString(str));
+ 	}
+ 
  /**
     Create a new SexpList by parsing an S-Expression out of the input stream.
     Assumes that we have already parsed the first parenthesis of a list S-Expression.
***************
*** 72,92 ****
      return len;
    }
    
!   public byte[] getCanonRep() {
!     Sexp s;
!     int s_len;
!     int cur_pos = 1;
!     byte[] canon = new byte[this.getCanonLen()];
!     canon[0] = (byte) '(';
!     for (Enumeration e = elements.elements(); e.hasMoreElements();) {
!       s = (Sexp)e.nextElement();
!       s_len = s.getCanonLen();
!       System.arraycopy(s.getCanonRep(),0,canon,cur_pos,s_len);
!       cur_pos += s_len;
!     }
!     canon[cur_pos] = (byte) ')';
!     return canon;
!   }
    int getReadableLen() {//assumes on one line
      int len = 1;
      Sexp[] elements = this.arrayOfElements();
--- 123,157 ----
      return len;
    }
    
! //  public byte[] getCanonRep() {
! //    Sexp s;
! //    int s_len;
! //    int cur_pos = 1;
! //    byte[] canon = new byte[this.getCanonLen()];
! //    canon[0] = (byte) '(';
! //    for (Enumeration e = elements.elements(); e.hasMoreElements();) {
! //      s = (Sexp)e.nextElement();
! //      s_len = s.getCanonLen();
! //      System.arraycopy(s.getCanonRep(),0,canon,cur_pos,s_len);
! //      cur_pos += s_len;
! //    }
! //    canon[cur_pos] = (byte) ')';
! //    return canon;
! //  }
! 
! 	/**
! 	 * @author jonh@cs.dartmouth.edu
! 	 */
! 	public void getCanonRep(ByteBuffer bb) {
! 		Sexp s;
! 		bb.append((byte) '(');
! 		for (Enumeration e = elements.elements(); e.hasMoreElements();) {
! 			s = (Sexp) e.nextElement();
! 			s.getCanonRep(bb);
! 		}
! 		bb.append((byte) ')');
! 	}
! 
    int getReadableLen() {//assumes on one line
      int len = 1;
      Sexp[] elements = this.arrayOfElements();
***************
*** 96,138 ****
      }
      return len;
    }
!   public String toReadableString(int offset, int width, int last) {
!     StringBuffer s = new StringBuffer();
!     s.append("(");
!     Sexp[] elements = this.arrayOfElements();
!     if (elements.length == 0)
!       return "()";
!     boolean newLines = false;
!     if (this.getReadableLen() > width-offset-last) {
!       newLines = true;
!       offset += 2;
!       if (offset >= width)
!         offset = 0;
!     }
!     for (int i=0;i<elements.length-1;i++) {
!       if (newLines && i>0) {
!         s.append("\n");
!         for (int j=0;j<offset;j++)
!           s.append(" ");
!       }
!       s.append(elements[i].toReadableString(offset,width,0) + " ");
!     }
!     if (newLines) {
!       s.append("\n");
!       for (int j=0;j<offset;j++)
!         s.append(" ");
!     }
!     s.append(elements[elements.length-1].toReadableString(offset,width,last+1));
!     s.append(")");
!     return s.toString();
!   }
! /*
!   //need to eliminate this function
!   public void display() { //need to find a good way to do this!!
!     byte[] disp = this.getCanonRep();
!     System.out.write(disp,0,disp.length);
!   } 
! */  
    /** Returns the Sexp located at the given index.  This is used when we know 
        that we want to get to the element at a particular location in the list
        @param index the index of the Sexp to return
--- 161,235 ----
      }
      return len;
    }
! 
! 	/**
! 	 * @author jonh: rewrote to append to an existing StringBuffer.
! 	 */
! 	public void toReadableString(StringBuffer sb,
! 		int offset, int width, int last) {
! 
! 		Sexp[] elements = this.arrayOfElements();
! 		if (elements.length == 0) {
! 			sb.append("()");
! 			return;
! 		}
! 
! 		sb.append("(");
! 		boolean newLines = false;
! 		String offsetStr = null;
! 
! 		if (this.getReadableLen() > width-offset-last) {
! 			offset += 2;
! 			if (offset >= width) {
! 				offset = 0;
! 			}
! 			offsetStr = buildOffsetStr(offset);
! 		}
! 		for (int i=0; i<elements.length-1; i++) {
! 			if (offsetStr!=null && i>0) {
! 				sb.append(offsetStr);
! 			}
! 			elements[i].toReadableString(sb, offset, width, 0);
! 			sb.append(' ');
! 		}
! 		if (offsetStr!=null) {
! 			sb.append(offsetStr);
! 		}
! 		elements[elements.length-1].toReadableString(sb, offset, width, last+1);
! 		sb.append(')');
! 	}
! 
! //  public String toReadableString(int offset, int width, int last) {
! //    StringBuffer s = new StringBuffer();
! //    s.append("(");
! //    Sexp[] elements = this.arrayOfElements();
! //    if (elements.length == 0)
! //      return "()";
! //    boolean newLines = false;
! //    if (this.getReadableLen() > width-offset-last) {
! //      newLines = true;
! //      offset += 2;
! //      if (offset >= width)
! //        offset = 0;
! //    }
! //    for (int i=0;i<elements.length-1;i++) {
! //      if (newLines && i>0) {
! //        s.append("\n");
! //        for (int j=0;j<offset;j++)
! //          s.append(" ");
! //      }
! //      s.append(elements[i].toReadableString(offset,width,0) + " ");
! //    }
! //    if (newLines) {
! //      s.append("\n");
! //      for (int j=0;j<offset;j++)
! //        s.append(" ");
! //    }
! //    s.append(elements[elements.length-1].toReadableString(offset,width,last+1));
! //    s.append(")");
! //    return s.toString();
! //  }
! 
    /** Returns the Sexp located at the given index.  This is used when we know 
        that we want to get to the element at a particular location in the list
        @param index the index of the Sexp to return
diff -r -c3 sdsi/sexp/SexpString.java sdsi-new/sexp/SexpString.java
*** sdsi/sexp/SexpString.java	Wed Jun  3 10:34:46 1998
--- sdsi-new/sexp/SexpString.java	Mon Apr  3 14:22:18 2000
***************
*** 3,8 ****
--- 3,10 ----
  import java.io.*;
  import java.util.*;
  import java.security.*;  //so we can use MessageDigest.isEqual()
+ import Tools.ByteBuffer;
+ 
  /**
     This class represents simple S-Expressions.  These are S-Expession which are just byte-strings.
     @author Alex Morcos
***************
*** 97,155 ****
        return (this.content.canBeQuotedString() && this.display.canBeQuotedString());
    }
    */
!   public String toReadableString(int offset, int width, int last) {
!     if (width <= offset + last + 1) {
!       width = offset + last + 2;
!     }
!     if (display == null) {
!       StringBuffer s = this.content.toReadableStringBuffer();
!       if (s.length() > width - offset - last) {
!         StringBuffer offsetPart = new StringBuffer("\n");
!         for (int j=0;j<offset;j++)
!           offsetPart.append(" ");
!         for(int i=1;true;i++) {
!           int next = (width + 1) * i - (offset+1);
!           if (s.length() > next)
!             s.insert(next,offsetPart.toString());
!           else {
!             if (s.length() > (next - last)) {
!               s.append(offsetPart.toString().substring(0,offset));
!               break;
!             }
!             else
!               break;
!           }
!         }
!       }
!       return s.toString();
!     }
!     else {
!       StringBuffer s = this.display.toReadableStringBuffer();
!       s.insert(0,'[');
!       s.append(']');
!       StringBuffer offsetPart = new StringBuffer("\n");
!       for (int j=0;j<offset;j++)
!         offsetPart.append(" ");
!       if (s.length() > width - offset) {
!         for(int i=0;true;i++) {
!           int next = width * i - offset;
!           if (s.length() > next)
!             s.insert(next,offsetPart.toString());
!         }
!       }
!       s.append(offsetPart);
!       StringBuffer c = this.content.toReadableStringBuffer();
!       if (c.length() > width - offset) {
!         for(int i=0;true;i++) {
!           int next = width * i - offset;
!           if (c.length() > next)
!             c.insert(next,offsetPart.toString());
!         }
!       }
!       s.append(c);
!       return s.toString();
!     }
!   }
   int getReadableLen() {
      if (display != null)
        return display.getReadableLen() + 2 + content.getReadableLen();
--- 99,169 ----
        return (this.content.canBeQuotedString() && this.display.canBeQuotedString());
    }
    */
! 	
! 	/**
! 	 * @author jonh modified this to write into a single StringBuffer.
! 	 * Otherwise, StringBuffers are being created and destroyed all through
! 	 * the recursive tree of calls that makes a top-level readable string.
! 	 */
! 	public void toReadableString(StringBuffer sb,
! 		int offset, int width, int last) {
! 		if (width <= offset + last + 1) {
! 			width = offset + last + 2;
! 		}
! 		if (display != null) {
! 			// jonh says: this toReadableString() may generate
! 			// different output than Morcos' original code when a
! 			// display hint is present, but I don't feel too bad about
! 			// that because I don't think that part of his code was
! 			// ever tested. The original code had no way to get out of
! 			// a for loop.
! 			appendSimpleToReadable(display, true, sb, offset, width, last);
! 		}
! 		appendSimpleToReadable(content, false, sb, offset, width, last);
! 	}
! 
! 
! 	// jonh: TODO: It seems like this indenting strategy could break token or
! 	// quotable strings midline, which seems pretty broken, doesn't it?
! 	void appendSimpleToReadable(SimpleString simple, boolean isDisplay,
! 		StringBuffer sb,
! 		int offset, int width, int last) {
! 
! 		int sbOffset = sb.length();
! 		if (isDisplay) {
! 			sb.append('[');
! 		}
! 		this.content.toReadableStringBuffer(sb);
! 		if (isDisplay) {
! 			sb.append(']');
! 		}
! 		int contentLength = sb.length()-sbOffset;
! 
! 		if (contentLength > width - offset - last) {
! 			String offsetStr = buildOffsetStr(offset);
! 
! 			for (int i=1; true; i++) {
! 				int next = (width + 1) * i - (offset+1);
! 				if (contentLength > next) {
! 					sb.insert(sbOffset+next, offsetStr);
! 					contentLength = sb.length()-sbOffset;
! 				} else {
! 					if ((!isDisplay)
! 						&& (contentLength > (next - last))) {
! 						// room for string on last line,
! 						// but not <code>last</code> ))'s
! 						// Apparently we should start a newline
! 						// with offset-1 spaces on it. Yuk. --jonh
! 						sb.append(offsetStr.substring(0,offset));
! 						break;
! 					} else {
! 						break;
! 					}
! 				}
! 			}
! 		}
! 	}
! 
   int getReadableLen() {
      if (display != null)
        return display.getReadableLen() + 2 + content.getReadableLen();
***************
*** 170,188 ****
      else
        return content.getCanonLen();
    }
!   public byte[] getCanonRep() {
!     if (display != null) {
!       int disp_len = display.getCanonLen();
!       byte[] canon = new byte[this.getCanonLen()];
!       canon[0] = (byte) '[';
!       System.arraycopy(display.getCanonRep(),0,canon,1,disp_len);
!       canon[disp_len + 1] = (byte) ']';
!       System.arraycopy(content.getCanonRep(),0,canon,disp_len+2,content.getCanonLen());
!       return canon;
!     }
!     else 
!       return content.getCanonRep();
!   }
    /**
    Compares the string representation of two SexpStrings lexicographically.  Requires 
    that their display types are equal for them to be compared.  If the display types
--- 184,215 ----
      else
        return content.getCanonLen();
    }
! //  public byte[] getCanonRep() {
! //    if (display != null) {
! //      int disp_len = display.getCanonLen();
! //      byte[] canon = new byte[this.getCanonLen()];
! //      canon[0] = (byte) '[';
! //      System.arraycopy(display.getCanonRep(),0,canon,1,disp_len);
! //      canon[disp_len + 1] = (byte) ']';
! //      System.arraycopy(content.getCanonRep(),0,canon,disp_len+2,content.getCanonLen());
! //      return canon;
! //    }
! //    else 
! //      return content.getCanonRep();
! //  }
! 
! 	/**
! 	 * @author jonh@cs.dartmouth.edu
! 	 */
! 	public void getCanonRep(ByteBuffer bb) {
! 		if (display!=null) {
! 			bb.append((byte) '[');
! 			display.getCanonRep(bb);
! 			bb.append((byte) ']');
! 		}
! 		content.getCanonRep(bb);
! 	}
! 
    /**
    Compares the string representation of two SexpStrings lexicographically.  Requires 
    that their display types are equal for them to be compared.  If the display types
diff -r -c3 sdsi/sexp/SimpleString.java sdsi-new/sexp/SimpleString.java
*** sdsi/sexp/SimpleString.java	Wed Jun  3 10:34:52 1998
--- sdsi-new/sexp/SimpleString.java	Mon Apr  3 12:21:50 2000
***************
*** 2,7 ****
--- 2,8 ----
  
  import java.io.*;
  import java.security.*;
+ import Tools.ByteBuffer;
  
  class SimpleString implements Serializable{  
    byte length_bytes[];
***************
*** 314,344 ****
        String number;
        switch(cur_byte) {
          case 'b':
!           data[bCount++]='\b';
            break;
          case 't':
!           data[bCount++]='\t';
            break;
          case 'v':
!           data[bCount++]='\t'; //no vertical tab!!
            break;
          case 'f':
!           data[bCount++]='\f';
            break;  
          case 'n':
!           data[bCount++]='\n';
            break;
          case 'r':
!           data[bCount++]='\r';
            break;
          case '\'':
!           data[bCount++]='\'';
            break;
          case '\"':
!           data[bCount++]='\"';
            break;
          case '\\':
!           data[bCount++]='\\';
            break;  
          case 'x':
            byte[] hexRep = new byte[2];
--- 315,345 ----
        String number;
        switch(cur_byte) {
          case 'b':
!           data[bCount++] = (byte) '\b';
            break;
          case 't':
!           data[bCount++] = (byte) '\t';
            break;
          case 'v':
!           data[bCount++] = (byte) '\t'; //no vertical tab!!
            break;
          case 'f':
!           data[bCount++] = (byte) '\f';
            break;  
          case 'n':
!           data[bCount++] = (byte) '\n';
            break;
          case 'r':
!           data[bCount++] = (byte) '\r';
            break;
          case '\'':
!           data[bCount++] = (byte) '\'';
            break;
          case '\"':
!           data[bCount++] = (byte) '\"';
            break;
          case '\\':
!           data[bCount++] = (byte) '\\';
            break;  
          case 'x':
            byte[] hexRep = new byte[2];
***************
*** 444,532 ****
      }
      return true;
    }
!   StringBuffer toTokenString() {
!     String s = null;
!     try {
!       s = new String(data,"8859_1"); 
!     }
!     catch (UnsupportedEncodingException e){
!       //do something this can't happen
!     }
!     return new StringBuffer(s);
!   }
!   StringBuffer toQuotedString() {
!     StringBuffer s = this.toTokenString();
!     s.insert(0,'\"');
!     s.append('\"');
!     return s;
!   }
!   StringBuffer toHexString() {
!     StringBuffer s = new StringBuffer();
!     s.append("#");
!     for (int i=0;i<data.length;i++) {
!       s.append(Sexp.hexDigit[data[i]>>>4 & 0x0F]);
!       s.append(Sexp.hexDigit[data[i] & 0x0F]);
!     }
!     s.append("#");
!     return s;
!   }
!   StringBuffer toBase64String() {
!     StringBuffer s= new StringBuffer();
!     s.append("|");
!     int carry = 0;
!     for (int i=0;i<data.length;i++) {
!       switch (i%3) {
!       case 0:
!         s.append(Sexp.base64Digit[data[i]>>>2 & 0x3F]);
!         carry = data[i]<<4 & 0x30;
!         break;
!       case 1:
!         s.append(Sexp.base64Digit[carry + (data[i]>>>4 & 0x0F)]);
!         carry = data[i]<<2 & 0x3C;
!         break;
!       case 2:
!         s.append(Sexp.base64Digit[carry + (data[i]>>>6 & 0x03)]);
!         s.append(Sexp.base64Digit[data[i] & 0x3F]);
!         carry = 0;
!         break;
!       }
!     }
!     if (data.length%3 == 1) {
!       s.append(Sexp.base64Digit[carry & 0x3F]);
!       s.append('=');
!       s.append('=');
!     }
!     if (data.length%3 == 2) {
!       s.append(Sexp.base64Digit[carry & 0x3F]);
!       s.append('=');
!     }
!     s.append('|');
!     return s;
!   }      
!   //this can be done better by only scanning input once
!   //maybe somehow combine this with getReadableLen
!   //first time either one is called store how it can
!   //be represented  thats good!!
!   StringBuffer toReadableStringBuffer() {
!     if (this.canBeTokenString())
!       return this.toTokenString();
!     else if (this.canBeQuotedString())
!       return this.toQuotedString();
!     else if (this.data.length < 8)
!       return this.toHexString();
!     else
!       return this.toBase64String();
!   }
!   int getReadableLen() {
!     if (this.canBeTokenString())
!       return data.length;
!     else if (this.canBeQuotedString())
!       return data.length + 2;
!     else if (this.data.length < 8)
!       return 2*data.length;
!     else
!       return 4*((data.length + 2)/3)+2;
!   }
    public String toVerbatimString() {
      String s = null;
      try {
--- 445,608 ----
      }
      return true;
    }
! 
! 	StringBuffer toTokenString() {
! 		StringBuffer sb = new StringBuffer();
! 		toTokenString(sb);
! 		return sb;
! 	}
! 	StringBuffer toQuotedString() {
! 		StringBuffer sb = new StringBuffer();
! 		toQuotedString(sb);
! 		return sb;
! 	}
! 	StringBuffer toHexString() {
! 		StringBuffer sb = new StringBuffer();
! 		toHexString(sb);
! 		return sb;
! 	}
! 	StringBuffer toBase64String() {
! 		StringBuffer sb = new StringBuffer();
! 		toBase64String(sb);
! 		return sb;
! 	}
! 
! 	void toTokenString(StringBuffer sb) {
! 		String s = null;
! 		try {
! 			s = new String(data,"8859_1"); 
! 		} catch (UnsupportedEncodingException e){
! 			throw new RuntimeException(e.toString());
! 		}
! 		sb.append(s);
! 	}
! 
! 	void toQuotedString(StringBuffer sb) {
! 		sb.append('\"');
! 		toTokenString(sb);
! 		sb.append('\"');
! 	}
! 
! 	void toHexString(StringBuffer sb) {
! 		sb.append("#");
! 		for (int i=0;i<data.length;i++) {
! 			sb.append(Sexp.hexDigit[data[i]>>>4 & 0x0F]);
! 			sb.append(Sexp.hexDigit[data[i] & 0x0F]);
! 		}
! 		sb.append("#");
! 	}
! 
! 	void toBase64String(StringBuffer sb) {
! 		sb.append("|");
! 		int carry = 0;
! 		for (int i=0;i<data.length;i++) {
! 			switch (i%3) {
! 			case 0:
! 				sb.append(Sexp.base64Digit[data[i]>>>2 & 0x3F]);
! 				carry = data[i]<<4 & 0x30;
! 				break;
! 			case 1:
! 				sb.append(Sexp.base64Digit[carry + (data[i]>>>4 & 0x0F)]);
! 				carry = data[i]<<2 & 0x3C;
! 				break;
! 			case 2:
! 				sb.append(Sexp.base64Digit[carry + (data[i]>>>6 & 0x03)]);
! 				sb.append(Sexp.base64Digit[data[i] & 0x3F]);
! 				carry = 0;
! 				break;
! 			}
! 		}
! 		if (data.length%3 == 1) {
! 			sb.append(Sexp.base64Digit[carry & 0x3F]);
! 			sb.append('=');
! 			sb.append('=');
! 		} else if (data.length%3 == 2) {
! 			sb.append(Sexp.base64Digit[carry & 0x3F]);
! 			sb.append('=');
! 		}
! 		sb.append('|');
! 	}
! 
! 	/**
! 	 * Only walk the string once to figure out how to best display it.
! 	 * From Morcos' suggestion in his original version of this code:
!   	 *	//this can be done better by only scanning input once
!   	 *	//maybe somehow combine this with getReadableLen
!   	 *	//first time either one is called store how it can
!   	 *	//be represented  thats good!!
! 	 * 
! 	 * @author jonh
! 	 */
! 	int getBestReadableType() {
! 		if (bestReadableType==UNKNOWN) {
! 			if (this.canBeTokenString()) {
! 				bestReadableType = TOKEN;
! 			} else if (this.canBeQuotedString()) {
! 				bestReadableType = QUOTED;
! 			} else if (this.data.length < 8) {
! 				bestReadableType = HEX;
! 			} else {
! 				bestReadableType = BASE64;
! 			}
! 		}
! 		return bestReadableType;
! 	}
! 
! 	/**
! 	 * put readable representation into an existing StringBuffer.
! 	 * 
! 	 * @author jonh@cs.dartmouth.edu
! 	 */
! 	void toReadableStringBuffer(StringBuffer sb) {
! 		switch (getBestReadableType()) {
! 			case TOKEN:
! 				this.toTokenString(sb);
! 				break;
! 			case QUOTED:
! 				this.toQuotedString(sb);
! 				break;
! 			case HEX:
! 				this.toHexString(sb);
! 				break;
! 			case BASE64:
! 				this.toBase64String(sb);
! 				break;
! 			default:
! 				throw new RuntimeException(
! 					"Famous last words: this cannot happen.");
! 		}
! 	}
! 
! 	static final int UNKNOWN	= 0;
! 	static final int TOKEN	= 1;
! 	static final int QUOTED	= 2;
! 	static final int HEX		= 3;
! 	static final int BASE64	= 4;
! 	transient int bestReadableType = UNKNOWN;
! 
! 	StringBuffer toReadableStringBuffer() {
! 		StringBuffer sb = new StringBuffer();
! 		toReadableStringBuffer(sb);
! 		return sb;
! 	}
! 
! 	/* @author jonh modified to use cached bestReadableType hint */
! 	int getReadableLen() {
! 		switch (getBestReadableType()) {
! 			case TOKEN:
! 				return data.length;
! 			case QUOTED:
! 				return data.length + 2;
! 			case HEX:
!       			return 2*data.length;
! 			case BASE64:
!       			return 4*((data.length + 2)/3)+2;
! 			default:
! 				throw new RuntimeException(
! 					"Famous last words: this cannot happen.");
! 		}
! 	}
! 
    public String toVerbatimString() {
      String s = null;
      try {
***************
*** 557,562 ****
--- 633,648 ----
      System.arraycopy(data,0,canon,len_len+1,data.length);
      return canon;
    }
+ 
+ 	/**
+ 	 * @author jonh@cs.dartmouth.edu
+ 	 */
+ 	public void getCanonRep(ByteBuffer bb) {
+ 		bb.append(length_bytes);
+ 		bb.append((byte) ':');
+ 		bb.append(data);
+ 	}
+ 
    public boolean equals(SimpleString other) {
      return MessageDigest.isEqual(this.data,other.data);
    }
Only in sdsi-new/sexp: makefile
Only in sdsi-new/sexp: package.html
