First Commit after cleanup

Socket Bridge in java now works with UDP
Now connecting to remote ccnd nodes ( unless there is a firewall on the
way) currently connecting to borges on port 9695
Cleaned up the code and added authors to all files since new people are
joining the project.
Separated java from javascript code.
diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..edbfeb9
--- /dev/null
+++ b/.DS_Store
Binary files differ
diff --git a/java/JavaSocketBridge.java b/java/JavaSocketBridge.java
new file mode 100644
index 0000000..877f1b9
--- /dev/null
+++ b/java/JavaSocketBridge.java
@@ -0,0 +1,161 @@
+// JavaSocketBridge.java

+// by Stephen Ware

+// April 25, 2009

+//

+// Part of the JavaSocketBridge project.

+// This applet provides an interface for using true sockets in JavaScript.

+//

+// Note: You will need to have the Java Plugin archive in your classpath to compile this.

+//       For me, that's C:\Program Files\Java\jre6\lib\plugin.jar

+// Note: You will need to jar this class and Listener.class into a signed jar file if

+//       you want your sockets to access domains other than the one this is running on.

+// Note: Apparently, when you grant permissions to Java applets in Java 6, you only grant

+//       them to the main applet thread.  That's the reason for all the confusing stuff

+//       in the connect methods... so that connections always happen on the main thread.

+

+import java.applet.*;

+import javax.swing.*;

+import netscape.javascript.*;

+

+import java.net.*;

+import java.security.AccessController;

+import java.security.PrivilegedAction;

+import java.io.*;

+

+public class JavaSocketBridge extends JApplet {

+

+	private final static int PACKETSIZE = 3000 ;

+	// Instance variables

+	JSObject browser = null;		// The browser

+

+

+	// Initialize

+	public void init(){

+		browser = JSObject.getWindow(this);

+	}

+

+	public String connectAndStart(final String ip, final int por, final String interest){

+		return AccessController.doPrivileged(

+				new PrivilegedAction<String>() {

+					public String run() {

+

+						DatagramSocket socket = null ;

+						byte[] output = null;

+						try

+						{

+							// Convert the arguments first, to ensure that they are valid

+							InetAddress host = InetAddress.getByName( ip ) ;

+							int port = por ;

+

+							// Construct the socket

+							socket = new DatagramSocket() ;

+

+							

+							byte [] data = hex2Byte(interest);

+							DatagramPacket packet = new DatagramPacket( data, data.length, host, port ) ;

+

+							// Send it

+							socket.send( packet ) ;

+

+							// Set a receive timeout, 2000 milliseconds

+							socket.setSoTimeout( 2000 ) ;

+

+							// Prepare the packet for receive

+							packet.setData( new byte[PACKETSIZE] ) ;

+

+							// Wait for a response from the server

+							socket.receive( packet ) ;

+

+							// Print the response

+							output = packet.getData() ;

+

+						}

+						catch( Exception e )

+						{

+							error(e.toString());

+							System.out.println( e ) ;

+						}

+						finally

+						{

+							if( socket != null )

+								socket.close() ;

+						}

+

+						if(output!=null)

+							return byte2hex(output);

+						else 

+							return "";

+					}

+				}

+				);

+

+	}

+	public static byte[] hex2Byte(String str)

+	{

+		byte[] bytes = new byte[str.length() / 2];

+		for (int i = 0; i < bytes.length; i++)

+		{

+			bytes[i] = (byte) Integer

+					.parseInt(str.substring(2 * i, 2 * i + 2), 16);

+		}

+

+		return bytes;

+	}

+	public static String byte2hex(byte[] b)

+	{

+		// String Buffer can be used instead

+		String hs = "";

+		String stmp = "";

+

+		for (int n = 0; n < b.length; n++)

+		{

+			stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));

+

+			if (stmp.length() == 1)

+			{

+				hs = hs + "0" + stmp;

+			}

+			else

+			{

+				hs = hs + stmp;

+			}

+

+			if (n < b.length - 1)

+			{

+				hs = hs + "";

+			}

+		}

+

+		return hs;

+	}

+

+

+	// Main

+	// Note: This method loops over and over to handle requests becuase only

+	//       this thread gets the elevated security policy.  Java == stupid.

+	public void start(){

+		try {

+			browser.call("java_socket_bridge_ready", null);

+		} catch (JSException e) {

+			// TODO Auto-generated catch block

+			e.printStackTrace();

+		}

+

+	}

+

+

+	// Report an error

+	public void error(String message){

+		message = "Java Socket Bridge ERROR: " + message;

+		Object[] arguments = new Object[1];

+		arguments[0] = message;

+		try {

+			browser.call("on_socket_error", arguments);

+		} catch (JSException e) {

+			// TODO Auto-generated catch block

+			e.printStackTrace();

+		}

+	}

+

+

+}
\ No newline at end of file
diff --git a/js/.DS_Store b/js/.DS_Store
new file mode 100644
index 0000000..5008ddf
--- /dev/null
+++ b/js/.DS_Store
Binary files differ
diff --git a/js/CCNProtocolDTags.js b/js/CCNProtocolDTags.js
new file mode 100644
index 0000000..36ea03d
--- /dev/null
+++ b/js/CCNProtocolDTags.js
@@ -0,0 +1,155 @@
+/*
+ * @author: ucla-cs
+ * THis class contains all CCNx tags
+ */
+
+
+var CCNProtocolDTags = {
+
+	/**
+	 * Note if you add one of these, add it to the reverse string map as well.
+	 * Emphasize getting the work done at compile time over trying to make something
+	 * flexible and developer error-proof.
+	 */
+
+	 Any : 13,
+	 Name : 14,
+	 Component : 15,
+	 Certificate : 16,
+	 Collection : 17,
+	 CompleteName : 18,
+	 Content : 19,
+	 SignedInfo : 20,
+	 ContentDigest : 21,
+	 ContentHash : 22,
+	 Count : 24,
+	 Header : 25,
+	 Interest : 26,	/* 20090915 */
+	 Key : 27,
+	 KeyLocator : 28,
+	 KeyName : 29,
+	 Length : 30,
+	 Link : 31,
+	 LinkAuthenticator : 32,
+	 NameComponentCount : 33,	/* DeprecatedInInterest */
+	 RootDigest : 36,
+	 Signature : 37,
+	 Start : 38,
+	 Timestamp : 39,
+	 Type : 40,
+	 Nonce : 41,
+	 Scope : 42,
+	 Exclude : 43,
+	 Bloom : 44,
+	 BloomSeed : 45,
+	 AnswerOriginKind : 47,
+	 InterestLifetime : 48,
+	 Witness : 53,
+	 SignatureBits : 54,
+	 DigestAlgorithm : 55,
+	 BlockSize : 56,
+	 FreshnessSeconds : 58,
+	 FinalBlockID : 59,
+	 PublisherPublicKeyDigest : 60,
+	 PublisherCertificateDigest : 61,
+	 PublisherIssuerKeyDigest : 62,
+	 PublisherIssuerCertificateDigest : 63,
+	 ContentObject : 64,	/* 20090915 */
+	 WrappedKey : 65,
+	 WrappingKeyIdentifier : 66,
+	 WrapAlgorithm : 67,
+	 KeyAlgorithm : 68,
+	 Label : 69,
+	 EncryptedKey : 70,
+	 EncryptedNonceKey : 71,
+	 WrappingKeyName : 72,
+	 Action : 73,
+	 FaceID : 74,
+	 IPProto : 75,
+	 Host : 76,
+	 Port : 77,
+	 MulticastInterface : 78,
+	 ForwardingFlags : 79,
+	 FaceInstance : 80,
+	 ForwardingEntry : 81,
+	 MulticastTTL : 82,
+	 MinSuffixComponents : 83,
+	 MaxSuffixComponents : 84,
+	 ChildSelector : 85,
+	 RepositoryInfo : 86,
+	 Version : 87,
+	 RepositoryVersion : 88,
+	 GlobalPrefix : 89,
+	 LocalName : 90,
+	 Policy : 91,
+	 Namespace : 92,
+	 GlobalPrefixName : 93,
+	 PolicyVersion : 94,
+	 KeyValueSet : 95,
+	 KeyValuePair : 96,
+	 IntegerValue : 97,
+	 DecimalValue : 98,
+	 StringValue : 99,
+	 BinaryValue : 100,
+	 NameValue : 101,
+	 Entry : 102,
+	 ACL : 103,
+	 ParameterizedName : 104,
+	 Prefix : 105,
+	 Suffix : 106,
+	 Root : 107,
+	 ProfileName : 108,
+	 Parameters : 109,
+	 InfoString : 110,
+	// 111 unallocated
+	 StatusResponse : 112,
+	 StatusCode : 113,
+	 StatusText : 114,
+
+	// Sync protocol
+	 SyncNode : 115,
+	 SyncNodeKind : 116,
+	 SyncNodeElement : 117,
+	 SyncVersion : 118,
+	 SyncNodeElements : 119,
+	 SyncContentHash : 120,
+	 SyncLeafCount : 121,
+	 SyncTreeDepth : 122,
+	 SyncByteCount : 123,
+	 ConfigSlice : 124,
+	 ConfigSliceList : 125,
+	 ConfigSliceOp : 126,
+
+	// Remember to keep in sync with schema/tagnames.csvsdict
+	 CCNProtocolDataUnit : 17702112,
+	 CCNPROTOCOL_DATA_UNIT : "CCNProtocolDataUnit"
+};
+
+var CCNProtocolDTagsStrings = [
+	null, null, null, null, null, null, null, null, null, null, null,
+	null, null,
+	"Any", "Name", "Component", "Certificate", "Collection", "CompleteName",
+	"Content", "SignedInfo", "ContentDigest", "ContentHash", null, "Count", "Header",
+	"Interest", "Key", "KeyLocator", "KeyName", "Length", "Link", "LinkAuthenticator",
+	"NameComponentCount", null, null, "RootDigest", "Signature", "Start", "Timestamp", "Type",
+	"Nonce", "Scope", "Exclude", "Bloom", "BloomSeed", null, "AnswerOriginKind",
+	"InterestLifetime", null, null, null, null, "Witness", "SignatureBits", "DigestAlgorithm", "BlockSize",
+	null, "FreshnessSeconds", "FinalBlockID", "PublisherPublicKeyDigest", "PublisherCertificateDigest",
+	"PublisherIssuerKeyDigest", "PublisherIssuerCertificateDigest", "ContentObject",
+	"WrappedKey", "WrappingKeyIdentifier", "WrapAlgorithm", "KeyAlgorithm", "Label",
+	"EncryptedKey", "EncryptedNonceKey", "WrappingKeyName", "Action", "FaceID", "IPProto",
+	"Host", "Port", "MulticastInterface", "ForwardingFlags", "FaceInstance",
+	"ForwardingEntry", "MulticastTTL", "MinSuffixComponents", "MaxSuffixComponents", "ChildSelector",
+	"RepositoryInfo", "Version", "RepositoryVersion", "GlobalPrefix", "LocalName",
+	"Policy", "Namespace", "GlobalPrefixName", "PolicyVersion", "KeyValueSet", "KeyValuePair",
+	"IntegerValue", "DecimalValue", "StringValue", "BinaryValue", "NameValue", "Entry",
+	"ACL", "ParameterizedName", "Prefix", "Suffix", "Root", "ProfileName", "Parameters",
+	"InfoString", null,
+    "StatusResponse", "StatusCode", "StatusText", "SyncNode", "SyncNodeKind", "SyncNodeElement",
+    "SyncVersion", "SyncNodeElements", "SyncContentHash", "SyncLeafCount", "SyncTreeDepth", "SyncByteCount",
+    "ConfigSlice", "ConfigSliceList", "ConfigSliceOp" ];
+
+
+//TESTING
+//console.log(exports.CCNProtocolDTagsStrings[17]);
+
diff --git a/js/CCNTime.js b/js/CCNTime.js
new file mode 100644
index 0000000..5aafca1
--- /dev/null
+++ b/js/CCNTime.js
@@ -0,0 +1,99 @@
+/*
+ * @author: ucla-cs
+ * This class represents CCNTime Objects
+ */
+
+var CCNTime = function CCNTime(
+                               //long 
+msec) {
+
+
+
+
+	this.NANOS_MAX = 999877929;
+	
+	this.date = new Date(msec);
+};
+
+
+	/**
+	 * Create a CCNTime
+	 * @param timestamp source timestamp to initialize from, some precision will be lost
+	 */
+
+	/**
+	 * Create a CCNTime
+	 * @param time source Date to initialize from, some precision will be lost
+	 * as CCNTime does not round to unitary milliseconds
+	 */
+CCNTime.prototype.setDate = function(
+	//Date 
+		date) {
+
+	this.date = date;
+};
+	
+	/**
+	 * Create a CCNTime from its binary encoding
+	 * @param binaryTime12 the binary representation of a CCNTime
+	 */
+CCNTime.prototype.setDateBinary = function(
+	//byte [] 
+		binaryTime12) {
+
+
+	if ((null == binaryTime12) || (binaryTime12.length == 0)) {
+		throw new IllegalArgumentException("Invalid binary time!");
+	}
+	
+
+	value = 0;
+	for(i = 0; i < binaryTime12.length; i++) {
+		value = value << 8;
+		// Java will assume the byte is signed, so extend it and trim it.
+		b = (binaryTime12[i]) & 0xFF;
+		value |= b;
+	}
+	
+	this.date = new Date(value);
+
+};
+
+//byte[]
+CCNTime.prototype.toBinaryTime = function() {
+	
+	
+
+	return unsignedLongToByteArray(this.date.getTime());
+
+}
+
+unsignedLongToByteArray= function( value) {
+	if( 0 == value )
+		return [0];
+
+	if( 0 <= value && value <= 0x00FF ) {
+		//byte [] 
+		bb = new Array[1];
+		bb[0] = (value & 0x00FF);
+		return bb;
+	}
+
+	
+	//byte [] 
+	out = null;
+	//int
+	offset = -1;
+	for(var i = 7; i >=0; --i) {
+		//byte
+		b = ((value >> (i * 8)) & 0xFF);
+		if( out == null && b != 0 ) {
+			out = new Array(i+1);//byte[i+1];
+			offset = i;
+		}
+		if( out != null )
+			out[ offset - i ] = b;
+	}
+	return out;
+}
+	
diff --git a/js/ContentName.js b/js/ContentName.js
new file mode 100644
index 0000000..bec8482
--- /dev/null
+++ b/js/ContentName.js
@@ -0,0 +1,69 @@
+/*
+ * @author: ucla-cs
+ * This class represents ContentName
+ */
+ 
+
+var ContentName = function ContentName(_Components){
+
+
+	this.SCHEME = "ccnx:";
+
+	this.ORIGINAL_SCHEME = "ccn:";
+
+	this.SEPARATOR = "/";
+	this.ROOT = null;
+	
+	if( typeof _Components == 'string') {
+		this.Components = _Components;
+		
+
+	}
+	else if(typeof _Components === 'object' && _Components instanceof Array ){
+		
+		this.Components = _Components;
+
+	}
+	else{
+		
+		console.log("TODO: This should be an array");
+		this.Components==_Components;
+	}
+};
+
+
+
+
+ContentName.prototype.decode = function(/*XMLDecoder*/ decoder)  {
+		decoder.readStartElement(this.getElementLabel());
+
+		
+		this.Components = new Array(); //new ArrayList<byte []>();
+
+		while (decoder.peekStartElement(CCNProtocolDTags.Component)) {
+			this.add(decoder.readBinaryElement(CCNProtocolDTags.Component));
+		}
+		
+		decoder.readEndElement();
+};
+
+ContentName.prototype.encode = function(/*XMLEncoder*/ encoder)  {
+		
+		//TODO Check if parameters are valid
+
+		encoder.writeStartElement(this.getElementLabel());
+		var count = this.Components.length;
+		for (var i=0; i < count; i++) {
+			encoder.writeElement(CCNProtocolDTags.Component, this.Components[i]);
+		}
+		encoder.writeEndElement();
+};
+
+ContentName.prototype.getElementLabel = function(){
+	return CCNProtocolDTags.Name;
+};
+
+ContentName.prototype.add = function(param){
+	return this.Components.push(param);
+};
+
diff --git a/js/ContentObject.js b/js/ContentObject.js
new file mode 100644
index 0000000..d05f7ba
--- /dev/null
+++ b/js/ContentObject.js
@@ -0,0 +1,58 @@
+/*
+ * @author: ucla-cs
+ * This class represents ContentObject Objects
+ */
+var ContentObject = function ContentObject(_Name,_SignedInfo,_Content,_Signature){
+	
+	
+	if (typeof _Name === 'string'){
+		var n = new Name(_Name);
+	}
+	else{
+		//TODO Check the class of _Name
+		this.Name = _Name;
+	}
+	this.SignedInfo = _SignedInfo;
+	this.Content=_Content;
+	this.Signature = _Signature;
+
+};
+
+
+ContentObject.prototype.decode = function(/*XMLDecoder*/ decoder) {
+
+		decoder.readStartElement(this.getElementLabel());
+
+		this.Signature = new Signature();
+		this.Signature.decode(decoder);
+
+		this.Name = new ContentName();
+		this.Name.decode(decoder);
+
+		this.SignedInfo = new SignedInfo();
+		this.SignedInfo.decode(decoder);
+
+		this.Content = decoder.readBinaryElement(CCNProtocolDTags.Content);
+
+		decoder.readEndElement();
+
+};
+
+ContentObject.prototype.encode = function(/*XMLEncoder*/ encoder)  {
+
+	//TODO verify Name, SignedInfo and Signature is present
+
+
+	encoder.writeStartElement(this.getElementLabel());
+
+	if(null!=this.Signature) this.Signature.encode(encoder);
+	if(null!=this.Name) this.Name.encode(encoder);
+	if(null!=this.SignedInfo) this.SignedInfo.encode(encoder);
+
+	encoder.writeElement(CCNProtocolDTags.Content, this.Content);
+
+	encoder.writeEndElement();
+
+};
+
+ContentObject.prototype.getElementLabel= function(){return CCNProtocolDTags.ContentObject;};
diff --git a/js/DateFormat.js b/js/DateFormat.js
new file mode 100644
index 0000000..1e63760
--- /dev/null
+++ b/js/DateFormat.js
@@ -0,0 +1,125 @@
+/*
+ * Date Format 1.2.3
+ * (c) 2007-2009 Steven Levithan <stevenlevithan.com>
+ * MIT license
+ *
+ * Includes enhancements by Scott Trenda <scott.trenda.net>
+ * and Kris Kowal <cixar.com/~kris.kowal/>
+ *
+ * Accepts a date, a mask, or a date and a mask.
+ * Returns a formatted version of the given date.
+ * The date defaults to the current date/time.
+ * The mask defaults to dateFormat.masks.default.
+ */
+
+var DateFormat = function () {
+	var	token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,
+		timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,
+		timezoneClip = /[^-+\dA-Z]/g,
+		pad = function (val, len) {
+			val = String(val);
+			len = len || 2;
+			while (val.length < len) val = "0" + val;
+			return val;
+		};
+
+	// Regexes and supporting functions are cached through closure
+	return function (date, mask, utc) {
+		var dF = dateFormat;
+
+		// You can't provide utc if you skip other args (use the "UTC:" mask prefix)
+		if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) {
+			mask = date;
+			date = undefined;
+		}
+
+		// Passing date through Date applies Date.parse, if necessary
+		date = date ? new Date(date) : new Date;
+		if (isNaN(date)) throw SyntaxError("invalid date");
+
+		mask = String(dF.masks[mask] || mask || dF.masks["default"]);
+
+		// Allow setting the utc argument via the mask
+		if (mask.slice(0, 4) == "UTC:") {
+			mask = mask.slice(4);
+			utc = true;
+		}
+
+		var	_ = utc ? "getUTC" : "get",
+			d = date[_ + "Date"](),
+			D = date[_ + "Day"](),
+			m = date[_ + "Month"](),
+			y = date[_ + "FullYear"](),
+			H = date[_ + "Hours"](),
+			M = date[_ + "Minutes"](),
+			s = date[_ + "Seconds"](),
+			L = date[_ + "Milliseconds"](),
+			o = utc ? 0 : date.getTimezoneOffset(),
+			flags = {
+				d:    d,
+				dd:   pad(d),
+				ddd:  dF.i18n.dayNames[D],
+				dddd: dF.i18n.dayNames[D + 7],
+				m:    m + 1,
+				mm:   pad(m + 1),
+				mmm:  dF.i18n.monthNames[m],
+				mmmm: dF.i18n.monthNames[m + 12],
+				yy:   String(y).slice(2),
+				yyyy: y,
+				h:    H % 12 || 12,
+				hh:   pad(H % 12 || 12),
+				H:    H,
+				HH:   pad(H),
+				M:    M,
+				MM:   pad(M),
+				s:    s,
+				ss:   pad(s),
+				l:    pad(L, 3),
+				L:    pad(L > 99 ? Math.round(L / 10) : L),
+				t:    H < 12 ? "a"  : "p",
+				tt:   H < 12 ? "am" : "pm",
+				T:    H < 12 ? "A"  : "P",
+				TT:   H < 12 ? "AM" : "PM",
+				Z:    utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""),
+				o:    (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4),
+				S:    ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10]
+			};
+
+		return mask.replace(token, function ($0) {
+			return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
+		});
+	};
+}();
+
+// Some common format strings
+DateFormat.masks = {
+	"default":      "ddd mmm dd yyyy HH:MM:ss",
+	shortDate:      "m/d/yy",
+	mediumDate:     "mmm d, yyyy",
+	longDate:       "mmmm d, yyyy",
+	fullDate:       "dddd, mmmm d, yyyy",
+	shortTime:      "h:MM TT",
+	mediumTime:     "h:MM:ss TT",
+	longTime:       "h:MM:ss TT Z",
+	isoDate:        "yyyy-mm-dd",
+	isoTime:        "HH:MM:ss",
+	isoDateTime:    "yyyy-mm-dd'T'HH:MM:ss",
+	isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"
+};
+
+// Internationalization strings
+DateFormat.i18n = {
+	dayNames: [
+		"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+		"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
+	],
+	monthNames: [
+		"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
+		"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
+	]
+};
+
+// For convenience...
+Date.prototype.format = function (mask, utc) {
+	return dateFormat(this, mask, utc);
+};
diff --git a/js/Exclude.js b/js/Exclude.js
new file mode 100644
index 0000000..50f8ea7
--- /dev/null
+++ b/js/Exclude.js
@@ -0,0 +1,53 @@
+/*
+ * @author: ucla-cs
+ * This class represents Exclude objects
+ */
+
+var Exclude = function Exclude(_Values){ 
+	
+	this.OPTIMUM_FILTER_SIZE = 100;
+	
+
+	this.Values = _Values; //array of elements
+	
+}
+
+Exclude.prototype.decode = function(/*XMLDecoder*/ decoder) {
+
+
+		
+		decoder.readStartElement(this.getElementLabel());
+
+		//TODO APPLY FILTERS/EXCLUDE
+		
+		//TODO 
+		/*var component;
+		var any = false;
+		while ((component = decoder.peekStartElement(CCNProtocolDTags.Component)) || 
+				(any = decoder.peekStartElement(CCNProtocolDTags.Any)) ||
+					decoder.peekStartElement(CCNProtocolDTags.Bloom)) {
+			var ee = component?new ExcludeComponent(): any ? new ExcludeAny() : new BloomFilter();
+			ee.decode(decoder);
+			_values.add(ee);
+		}*/
+
+		decoder.readEndElement();
+
+};
+
+Exclude.prototype.encode=function(/*XMLEncoder*/ encoder)  {
+		if (!validate()) {
+			throw new ContentEncodingException("Cannot encode " + this.getClass().getName() + ": field values missing.");
+		}
+
+		if (empty())
+			return;
+
+		encoder.writeStartElement(getElementLabel());
+
+		encoder.writeEndElement();
+		
+	};
+
+Exclude.prototype.getElementLabel = function() { return CCNProtocolDTags.Exclude; };
+
diff --git a/js/ExcludeAny.js b/js/ExcludeAny.js
new file mode 100644
index 0000000..25a1a23
--- /dev/null
+++ b/js/ExcludeAny.js
@@ -0,0 +1,21 @@
+/*
+ * @author: ucla-cs
+ * This class represents ExcludeAny objects
+ */
+
+var ExcludeAny = function ExcludeAny() {
+
+};
+
+ExcludeAny.prototype.decode = function(decoder) {
+		decoder.readStartElement(this.getElementLabel());
+		decoder.readEndElement();
+};
+
+
+ExcludeAny.prototype.encode = function( encoder) {
+		encoder.writeStartElement(this.getElementLabel());
+		encoder.writeEndElement();
+};
+
+ExcludeAny.prototype.getElementLabel=function() { return CCNProtocolDTags.Any; };
diff --git a/js/ExcludeComponent.js b/js/ExcludeComponent.js
new file mode 100644
index 0000000..ed2bbeb
--- /dev/null
+++ b/js/ExcludeComponent.js
@@ -0,0 +1,22 @@
+/*
+ * @author: ucla-cs
+ * This class represents Exclude Component OBjects
+ */
+
+var ExcludeComponent = function ExcludeComponent(_Body) {
+
+	//TODO Check BODY is an Array of componenets.
+	
+	this.Body = _Body
+};
+
+ExcludeComponent.prototype.decode = function( decoder)  {
+		body = decoder.readBinaryElement(this.getElementLabel());
+};
+
+ExcludeComponent.prototype.encode = function(encoder) {
+		encoder.writeElement(this.getElementLabel(), body);
+};
+
+ExcludeComponent.prototype.getElementLabel = function() { return CCNProtocolDTags.Component; };
+
diff --git a/js/Interest.js b/js/Interest.js
new file mode 100644
index 0000000..c2df753
--- /dev/null
+++ b/js/Interest.js
@@ -0,0 +1,125 @@
+/*
+ * @author: ucla-cs
+ * This class represents Interest Objects
+ */
+
+var Interest = function Interest(_Name,_MinSuffixComponents,_MaxSuffixComponents,_PublisherPublicKeyDigest, _Exclude, _ChildSelector,_AnswerOriginKind,_Scope,_InterestLifetime,_Nonce){
+		
+	this.Name = _Name;
+	this.MaxSuffixComponents = _MaxSuffixComponents;
+	this.MinSuffixComponents = _MinSuffixComponents;
+	
+	this.PublisherKeyDigest = _PublisherPublicKeyDigest;
+	this.Exclude = _Exclude;
+	this.ChildSelector = _ChildSelector;
+	this.AnswerOriginKind = _AnswerOriginKind;
+	this.Scope = _Scope;
+	this.InterestLifetime = null;		// For now we don't have the ability to set an interest lifetime
+	this.Nonce = _Nonce;
+	
+
+	this.RECURSIVE_POSTFIX = "*";
+
+	this.CHILD_SELECTOR_LEFT = 0;
+	this.CHILD_SELECTOR_RIGHT = 1;
+	this.ANSWER_CONTENT_STORE = 1;
+	this.ANSWER_GENERATED = 2;
+	this.ANSWER_STALE = 4;		// Stale answer OK
+	this.MARK_STALE = 16;		// Must have Scope 0.  Michael calls this a "hack"
+
+	this.DEFAULT_ANSWER_ORIGIN_KIND = this.ANSWER_CONTENT_STORE | this.ANSWER_GENERATED;
+
+};
+
+Interest.prototype.decode = function(/*XMLDecoder*/ decoder) {
+
+		decoder.readStartElement(CCNProtocolDTags.Interest);
+
+		this.Name = new ContentName();
+		this.Name.decode(decoder);
+
+		if (decoder.peekStartElement(CCNProtocolDTags.MinSuffixComponents)) {
+			this.MinSuffixComponents = decoder.readIntegerElement(CCNProtocolDTags.MinSuffixComponents);
+		}
+
+		if (decoder.peekStartElement(CCNProtocolDTags.MaxSuffixComponents)) {
+			this.MaxSuffixComponents = decoder.readIntegerElement(CCNProtocolDTags.MaxSuffixComponents);
+		}
+			
+		//TODO decode PublisherID
+		/*if (PublisherID.peek(decoder)) {
+			this.Publisher = new PublisherID();
+			this.Publisher.decode(decoder);
+		}*/
+
+		if (decoder.peekStartElement(CCNProtocolDTags.Exclude)) {
+			this.Exclude = new Exclude();
+			this.Exclude.decode(decoder);
+		}
+		
+		if (decoder.peekStartElement(CCNProtocolDTags.ChildSelector)) {
+			this.ChildSelector = decoder.readIntegerElement(CCNProtocolDTags.ChildSelector);
+		}
+		
+		if (decoder.peekStartElement(CCNProtocolDTags.AnswerOriginKind)) {
+			// call setter to handle defaulting
+			this.AnswerOriginKind = decoder.readIntegerElement(CCNProtocolDTags.AnswerOriginKind);
+		}
+		
+		if (decoder.peekStartElement(CCNProtocolDTags.Scope)) {
+			this.Scope = decoder.readIntegerElement(CCNProtocolDTags.Scope);
+		}
+
+		if (decoder.peekStartElement(CCNProtocolDTags.InterestLifetime)) {
+			this.InterestLifetime = decoder.readBinaryElement(CCNProtocolDTags.InterestLifetime);
+		}
+		
+		if (decoder.peekStartElement(CCNProtocolDTags.Nonce)) {
+			this.Nonce = decoder.readBinaryElement(CCNProtocolDTags.Nonce);
+		}
+		
+		decoder.readEndElement();
+};
+
+Interest.prototype.encode = function(/*XMLEncoder*/ encoder){
+		/*if (!validate()) {
+			throw new ContentEncodingException("Cannot encode " + this.getClass().getName() + ": field values missing.");
+		}*/
+		
+		encoder.writeStartElement(CCNProtocolDTags.Interest);
+		
+		this.Name.encode(encoder);
+	
+		if (null != this.MinSuffixComponents) 
+			encoder.writeElement(CCNProtocolDTags.MinSuffixComponents, this.MinSuffixComponents);	
+
+		if (null != this.MaxSuffixComponents) 
+			encoder.writeElement(CCNProtocolDTags.MaxSuffixComponents, this.MaxSuffixComponents);
+
+		//TODO Encode PublisherID
+		
+		/*if (null != this.PublisherID)
+			publisherID().encode(encoder);*/
+		
+		//TODO Encode Exclude
+		
+		//if (null != this.Exclude)
+			//exclude().encode(encoder);
+		
+		if (null != this.ChildSelector) 
+			encoder.writeElement(CCNProtocolDTags.ChildSelector, this.ChildSelector);
+
+		//TODO Encode OriginKind
+		if (this.DEFAULT_ANSWER_ORIGIN_KIND != this.AnswerOriginKind && this.AnswerOriginKind!=null) 
+			//encoder.writeElement(CCNProtocolDTags.AnswerOriginKind, this.AnswerOriginKind);
+		
+		if (null != this.Scope) 
+			encoder.writeElement(CCNProtocolDTags.Scope, this.Scope);
+		
+		if (null != this.Nonce)
+			encoder.writeElement(CCNProtocolDTags.Nonce, this.Nonce);
+		
+		encoder.writeEndElement();
+
+};
+
diff --git a/js/JavaSocketBridge.jar b/js/JavaSocketBridge.jar
new file mode 100644
index 0000000..0f2deae
--- /dev/null
+++ b/js/JavaSocketBridge.jar
Binary files differ
diff --git a/js/KeyLocator.js b/js/KeyLocator.js
new file mode 100644
index 0000000..ff5edaa
--- /dev/null
+++ b/js/KeyLocator.js
@@ -0,0 +1,116 @@
+/*
+ * @author: ucla-cs
+ * This class represents KeyLocator Objects
+ */
+
+var KeyLocatorType = {
+	  NAME:1,
+	  KEY:2,
+	  CERTIFICATE:3
+};
+
+var KeyLocator = function KeyLocator(_Input,_Type){ 
+
+
+    this.Type=_Type;
+    
+    if (_Type==KeyLocatorType.NAME){
+    	this.KeyName = _Input;
+    }
+    else if(_Type==KeyLocatorType.KEY){
+    	this.PublicKey = _Input;
+    }
+    else if(_Type==KeyLocatorType.CERTIFICATE){
+    	this.Certificate = _Input;
+    }
+    
+};
+
+KeyLocator.prototype.decode = function(decoder) {
+
+		decoder.readStartElement(this.getElementLabel());
+
+		if (decoder.peekStartElement(CCNProtocolDTags.Key)) {
+			try {
+				encodedKey = decoder.readBinaryElement(CCNProtocolDTags.Key);
+				// This is a DER-encoded SubjectPublicKeyInfo.
+				
+				//TODO FIX THIS, This should create a Key Object instead of keeping bytes
+
+				this.Key =   encodedKey;//CryptoUtil.getPublicKey(encodedKey);
+				
+				this.PublicKey = encodedKey;
+				
+				
+			} catch (e) {
+				throw new Exception("Cannot parse key: ", e);
+			} 
+
+			if (null == this.Key) {
+				throw new Exception("Cannot parse key: ");
+			}
+
+		} else if ( decoder.peekStartElement(CCNProtocolDTags.Certificate)) {
+			try {
+				encodedCert = decoder.readBinaryElement(CCNProtocolDTags.Certificate);
+				
+				/*
+				 * Certificates not yet working
+				 */
+				
+				//CertificateFactory factory = CertificateFactory.getInstance("X.509");
+				//this.Certificate = (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(encodedCert));
+				
+			} catch ( e) {
+				throw new Exception("Cannot decode certificate: " +  e);
+			}
+			if (null == this.Certificate) {
+				throw new Exception("Cannot parse certificate! ");
+			}
+		} else {
+			this.KeyName = new KeyName();
+			this.KeyName.decode(decoder);
+		}
+		decoder.readEndElement();
+	}
+	
+
+	KeyLocator.prototype.encode = function( encoder) {
+			
+		//TODO Check if Name is missing
+		/*if (!validate()) {
+			throw new ContentEncodingException("Cannot encode " + this.getClass().getName() + ": field values missing.");
+		}*/
+
+		
+		//TODO FIX THIS TOO
+		encoder.writeStartElement(this.getElementLabel());
+		
+		if (this._Type == KeyLocatorType.KEY) {
+			
+			encoder.writeElement(CCNProtocolDTags.Key, this.PublicKey);
+			
+		} else if (this.Type == KeyLocatorType.CERTIFICATE) {
+			
+			try {
+				encoder.writeElement(CCNProtocolDTags.Certificate, this.Certificate.getEncoded());
+			} catch ( e) {
+				throw new Exception("CertificateEncodingException attempting to write key locator: " + e);
+			}
+			
+		} else if (this.Type == KeyLocatorType.NAME) {
+			console.log('ACTUALLY HERE');
+			this.KeyName.encode(encoder);
+		}
+		encoder.writeEndElement();
+		
+};
+	
+KeyLocator.prototype.getElementLabel = function() {
+	return CCNProtocolDTags.KeyLocator; 
+};
+
+KeyLocator.prototype.validate = function() {
+	return (  (null != this.keyName) || (null != this.PublicKey) || (null != this.Certificate)   );
+};
+	
\ No newline at end of file
diff --git a/js/KeyName.js b/js/KeyName.js
new file mode 100644
index 0000000..036a550
--- /dev/null
+++ b/js/KeyName.js
@@ -0,0 +1,51 @@
+/*
+ * @author: ucla-cs
+ * This class represents KeyName Objects
+ */
+
+var KeyName = function KeyName() {
+	
+
+	this.ContentName = this.ContentName;//ContentName
+	this.PublisherID =this.PublisherID;//PublisherID
+
+};
+
+
+KeyName.prototype.decode=function( decoder){
+	
+
+	decoder.readStartElement(this.getElementLabel());
+
+	this.ContentName = new ContentName();
+	this.ContentName.decode(decoder);
+	
+	if ( peek(decoder) ) {
+		this.PublisherID = new PublisherID();
+		this.PublisherID.decode(decoder);
+	}
+	
+	decoder.readEndElement();
+};
+
+KeyName.prototype.encode = function( encoder) {
+	if (!this.validate()) {
+		throw new Exception("Cannot encode : field values missing.");
+	}
+	
+	encoder.writeStartElement(this.getElementLabel());
+	
+	this.ContentName.encode(encoder);
+	if (null != this.PublisherID)
+		this.PublisherID.encode(encoder);
+
+	encoder.writeEndElement();   		
+};
+	
+KeyName.prototype.getElementLabel = function() { return CCNProtocolDTags.KeyName; };
+
+KeyName.prototype.validate = function() {
+		// DKS -- do we do recursive validation?
+		// null signedInfo ok
+		return (null != this.ContentName);
+};
diff --git a/js/PublisherID.js b/js/PublisherID.js
new file mode 100644
index 0000000..1e24cc7
--- /dev/null
+++ b/js/PublisherID.js
@@ -0,0 +1,97 @@
+/*
+ * @author: ucla-cs
+ * This class represents Publisher and PublisherType Objects
+ */
+
+
+var PublisherType = function PublisherType(_tag){
+    	this.KEY =(CCNProtocolDTags.PublisherPublicKeyDigest);
+    	this.CERTIFICATE= (CCNProtocolDTags.PublisherCertificateDigest);
+    	this.ISSUER_KEY=	(CCNProtocolDTags.PublisherIssuerKeyDigest);
+    	this.ISSUER_CERTIFICATE	=(CCNProtocolDTags.PublisherIssuerCertificateDigest);
+
+    	this.Tag = _tag;
+}; 
+
+var isTypeTagVal = function(tagVal) {
+		if ((tagVal == CCNProtocolDTags.PublisherPublicKeyDigest) ||
+			(tagVal == CCNProtocolDTags.PublisherCertificateDigest) ||
+			(tagVal == CCNProtocolDTags.PublisherIssuerKeyDigest) ||
+			(tagVal == CCNProtocolDTags.PublisherIssuerCertificateDigest)) {
+			return true;
+		}
+		return false;
+};
+
+
+
+
+var PublisherID = function PublisherID() {
+
+	this.PUBLISHER_ID_DIGEST_ALGORITHM = "SHA-256";
+	this.PUBLISHER_ID_LEN = 256/8;
+    
+	//TODO, implement publisherID creation and key creation
+
+    //TODO implement generatePublicKeyDigest
+    this.PublisherID =null;//= generatePublicKeyDigest(key);//ByteArray
+    
+    //TODO implement generate key
+    //CryptoUtil.generateKeyID(PUBLISHER_ID_DIGEST_ALGORITHM, key);
+    this.PublisherType = null;//isIssuer ? PublisherType.ISSUER_KEY : PublisherType.KEY;//publisher Type
+    
+};
+
+
+PublisherID.prototype.decode = function(decoder) {
+		
+		// We have a choice here of one of 4 binary element types.
+		var nextTag = decoder.peekStartElementAsLong();
+		
+		if (null == nextTag) {
+			throw new Exception("Cannot parse publisher ID.");
+		} 
+		
+		this.PublisherType = new PublisherType(nextTag); 
+		
+		if (!isTypeTagVal(nextTag)) {
+			throw new Exception("Invalid publisher ID, got unexpected type: " + nextTag);
+		}
+		this.PublisherID = decoder.readBinaryElement(nextTag);
+		if (null == this.PublisherID) {
+			throw new ContentDecodingException("Cannot parse publisher ID of type : " + nextTag + ".");
+		}
+};
+
+PublisherID.prototype.encode = function(encoder) {
+	if (!this.validate()) {
+		throw new Exception("Cannot encode " + this.getClass().getName() + ": field values missing.");
+	}
+
+	encoder.writeElement(this.getElementLabel(), this.PublisherID);
+};
+	
+var peek = function(
+	//XMLDecoder 
+		decoder) {
+
+		//Long
+		nextTag = decoder.peekStartElementAsLong();
+		
+		if (null == nextTag) {
+			// on end element
+			return false;
+		}
+		return (isTypeTagVal(nextTag));
+	};
+
+PublisherID.prototype.getElementLabel = function() { 
+	return this.PublisherType.Tag;
+};
+
+PublisherID.prototype.validate = function(){
+	return ((null != id() && (null != type())));
+};
+
+
+
diff --git a/js/PublisherPublicKeyDigest.js b/js/PublisherPublicKeyDigest.js
new file mode 100644
index 0000000..92dec39
--- /dev/null
+++ b/js/PublisherPublicKeyDigest.js
@@ -0,0 +1,40 @@
+/*
+ * @author: ucla-cs
+ * This class represents PublisherPublicKeyDigest Objects
+ */
+var PublisherPublicKeyDigest = function PublisherPublicKeyDigest(_pkd){ 
+	
+ 	 if( typeof _pkd == "ByteArray") this.PublisherPublicKeyDigest = _pkd; // Byte Array
+ 	 else if( typeof _pkd == "PublicKey") ;//TODO...
+    
+};
+
+PublisherPublicKeyDigest.prototype.decode = function( decoder) {		
+
+		this.PublisherPublicKeyDigest = decoder.readBinaryElement(this.getElementLabel());
+		if (null == this.PublisherPublicKeyDigest) {
+			throw new Exception("Cannot parse publisher key digest.");
+		}
+		
+		//TODO check if the length of the PublisherPublicKeyDigest is correct ( Security reason)
+
+		/*if (this.PublisherPublicKeyDigest.length != PublisherID.PUBLISHER_ID_LEN) {
+			console.log('SHOULD NOT GO HERE !!!!!!!!!!!!!!!!!!');
+			this.PublisherPublicKeyDigest = new PublisherPublicKeyDigest(this.PublisherPublicKeyDigest).PublisherKeyDigest;
+		}*/
+	};
+
+PublisherPublicKeyDigest.prototype.encode= function( encoder) {
+		//TODO Check that the ByteArray for the key is present
+		/*if (!this.validate()) {
+			throw new Exception("Cannot encode : field values missing.");
+		}*/
+	
+		if (this.PublisherKeyDigest!=null)this.encoder.writeElement(this.getElementLabel(), this.PublisherKeyDigest);
+};
+	
+PublisherPublicKeyDigest.prototype.getElementLabel = function() { return CCNProtocolDTags.PublisherPublicKeyDigest; };
+
+PublisherPublicKeyDigest.prototype.validate =function() {
+		return (null != this.PublisherKeyDigest);
+};
diff --git a/js/Signature.js b/js/Signature.js
new file mode 100644
index 0000000..763d9fe
--- /dev/null
+++ b/js/Signature.js
@@ -0,0 +1,57 @@
+/*
+ * @author: ucla-cs
+ * This class represents Signature Objects
+ */
+
+
+var Signature = function Signature(_Witness,_Signature,_DigestAlgorithm) {
+	
+    this.Witness = _Witness;//byte [] _witness;
+	this.Signature = _Signature;//byte [] _signature;
+	this.DigestAlgorithm = _DigestAlgorithm//String _digestAlgorithm;
+};
+
+
+Signature.prototype.decode =function( decoder) {
+		decoder.readStartElement(this.getElementLabel());
+		if (decoder.peekStartElement(CCNProtocolDTags.DigestAlgorithm)) {
+			this.DigestAlgorithm = decoder.readUTF8Element(CCNProtocolDTags.DigestAlgorithm); 
+		}
+		if (decoder.peekStartElement(CCNProtocolDTags.Witness)) {
+			this.Witness = decoder.readBinaryElement(CCNProtocolDTags.Witness); 
+		}
+		this.Signature = decoder.readBinaryElement(CCNProtocolDTags.SignatureBits);	
+		decoder.readEndElement();
+	
+};
+
+
+Signature.prototype.encode= function( encoder){
+    	
+	if (!this.validate()) {
+		throw new Exception("Cannot encode: field values missing.");
+	}
+	
+	encoder.writeStartElement(this.getElementLabel());
+	
+	if ((null != this.DigestAlgorithm) && (!this.DigestAlgorithm.equals(CCNDigestHelper.DEFAULT_DIGEST_ALGORITHM))) {
+		encoder.writeElement(CCNProtocolDTags.DigestAlgorithm, OIDLookup.getDigestOID(this.DigestAlgorithm));
+	}
+	
+	if (null != this.Witness) {
+		// needs to handle null witness
+		encoder.writeElement(CCNProtocolDTags.Witness, this.Witness);
+	}
+
+	encoder.writeElement(CCNProtocolDTags.SignatureBits, this.Signature);
+
+	encoder.writeEndElement();   		
+};
+
+Signature.prototype.getElementLabel = function() { return CCNProtocolDTags.Signature; };
+
+
+Signature.prototype.validate = function() {
+		return null != this.Signature;
+};
+
diff --git a/js/SignedInfo.js b/js/SignedInfo.js
new file mode 100644
index 0000000..3d03f17
--- /dev/null
+++ b/js/SignedInfo.js
@@ -0,0 +1,121 @@
+/*
+ * @author: ucla-cs
+ * This class represents SignedInfo Object
+ * This keeps information about the ContentObject Signature
+ */
+
+var ContentType = {DATA:0, ENCR:1, GONE:2, KEY:3, LINK:4, NACK:5};
+
+var ContentTypeValue = {0:0x0C04C0, 1:0x10D091,2:0x18E344,3:0x28463F,4:0x2C834A,5:0x34008A};
+var ContentTypeValueReverse = {0x0C04C0:0, 0x10D091:1,0x18E344:2,0x28463F:3,0x2C834A:4,0x34008A:5};
+
+
+var SignedInfo = function SignedInfo(_publisher,_timestamp,_type,_locator,_freshnessSeconds,_finalBlockID){
+
+	//TODO, Check types
+    
+    this.Publisher = _publisher; //PublisherPublicKeyDigest
+    this.Timestamp=_timestamp; // CCN Time
+    this.Type=_type; // ContentType
+    this.Locator =_locator;//KeyLocator
+    this.FreshnessSeconds =_freshnessSeconds; // Integer
+    this.FinalBlockID=_finalBlockID; //byte array
+
+};
+
+
+SignedInfo.prototype.decode = function( decoder){
+
+		decoder.readStartElement( this.getElementLabel() );
+		
+		if (decoder.peekStartElement(CCNProtocolDTags.PublisherPublicKeyDigest)) {
+			this.Publisher = new PublisherPublicKeyDigest();
+			this.Publisher.decode(decoder);
+		}
+
+		if (decoder.peekStartElement(CCNProtocolDTags.Timestamp)) {
+			this.Timestamp = decoder.readDateTime(CCNProtocolDTags.Timestamp);
+		}
+
+		if (decoder.peekStartElement(CCNProtocolDTags.Type)) {
+			binType = decoder.readBinaryElement(CCNProtocolDTags.Type);//byte [] 
+		
+		
+			//TODO Implement Type of Key Reading
+			
+			//this.Type = valueToType(binType);
+			
+			
+			//TODO Implement Type of Key Reading
+			
+			/*
+			if (null == this.Type) {
+				throw new Exception("Cannot parse signedInfo type: bytes.");
+			}
+			
+		} else {
+			this.Type = ContentType.DATA; // default*/
+		}
+		
+		if (decoder.peekStartElement(CCNProtocolDTags.FreshnessSeconds)) {
+			this.FreshnessSeconds = decoder.readIntegerElement(CCNProtocolDTags.FreshnessSeconds);
+		}
+		
+		if (decoder.peekStartElement(CCNProtocolDTags.FinalBlockID)) {
+			this.FinalBlockID = decoder.readBinaryElement(CCNProtocolDTags.FinalBlockID);
+		}
+		
+		if (decoder.peekStartElement(CCNProtocolDTags.KeyLocator)) {
+			this.Locator = new KeyLocator();
+			this.Locator.decode(decoder);
+		}
+				
+		decoder.readEndElement();
+};
+
+SignedInfo.prototype.encode = function( encoder)  {
+		if (!this.validate()) {
+			throw new Exception("Cannot encode : field values missing.");
+		}
+		encoder.writeStartElement(this.getElementLabel());
+		
+		if (null!=this.Publisher) {
+			this.Publisher.encode(encoder);
+		}
+
+		if (null!=this.Timestamp) {
+			encoder.writeDateTime(CCNProtocolDTags.Timestamp, this.Timestamp);
+		}
+		
+		if (null!=this.Type && this.Type !=0) {
+			
+			encoder.writeElement(CCNProtocolDTags.Type, this.Type);
+		}
+		
+		if (null!=this.FreshnessSeconds) {
+			encoder.writeElement(CCNProtocolDTags.FreshnessSeconds, this.FreshnessSeconds);
+		}
+
+		if (null!=this.FinalBlockID) {
+			encoder.writeElement(CCNProtocolDTags.FinalBlockID, this.FinalBlockID);
+		}
+
+		if (null!=this.Locator) {
+			this.Locator.encode(encoder);
+		}
+
+		encoder.writeEndElement();   		
+};
+	
+SignedInfo.prototype.getElementLabel = function() { 
+	return CCNProtocolDTags.SignedInfo;
+};
+
+SignedInfo.prototype.validate = function() {
+		// We don't do partial matches any more, even though encoder/decoder
+		// is still pretty generous.
+		if (null ==this.Publisher || null==this.Timestamp ||null== this.Locator)
+			return false;
+		return true;
+};
+
diff --git a/js/encoding/BinaryXMLCodec.js b/js/encoding/BinaryXMLCodec.js
new file mode 100644
index 0000000..b1befdd
--- /dev/null
+++ b/js/encoding/BinaryXMLCodec.js
@@ -0,0 +1,271 @@
+/*
+ * This class is used to encode and decode binary elements ( blog, type/value pairs)
+ * 
+ * @author: ucla-cs
+ */
+var XML_EXT = 0x00; 
+	
+var XML_TAG = 0x01; 
+	
+var XML_DTAG = 0x02; 
+	
+var XML_ATTR = 0x03; 
+ 
+var XML_DATTR = 0x04; 
+	
+var XML_BLOB = 0x05; 
+	
+var XML_UDATA = 0x06; 
+	
+var XML_CLOSE = 0x0;
+
+var XML_SUBTYPE_PROCESSING_INSTRUCTIONS = 16; 
+	
+
+var XML_TT_BITS = 3;
+var XML_TT_MASK = ((1 << XML_TT_BITS) - 1);
+var XML_TT_VAL_BITS = XML_TT_BITS + 1;
+var XML_TT_VAL_MASK = ((1 << (XML_TT_VAL_BITS)) - 1);
+var XML_REG_VAL_BITS = 7;
+var XML_REG_VAL_MASK = ((1 << XML_REG_VAL_BITS) - 1);
+var XML_TT_NO_MORE = (1 << XML_REG_VAL_BITS); // 0x80
+var BYTE_MASK = 0xFF;
+var LONG_BYTES = 8;
+var LONG_BITS = 64;
+	
+var bits_11 = 0x0000007FF;
+var bits_18 = 0x00003FFFF;
+var bits_32 = 0x0FFFFFFFF;
+
+
+var TypeAndVal = function TypeAndVal(_type,_val) {
+	this.type = _type;
+	this.val = _val;
+	
+};
+
+var BinaryXMLCodec = function BinaryXMLCodec(){
+	this.CODEC_NAME = "Binary";
+};
+    
+
+
+BinaryXMLCodec.prototype.encodeTypeAndValOffset = function(
+	//int
+	type,
+	//long
+	val,
+	//byte []
+	buf,
+	//int
+	offset) {
+	
+	if ((type > XML_UDATA) || (type < 0) || (val < 0)) {
+		throw new Exception("Tag and value must be positive, and tag valid.");
+	}
+	
+	// Encode backwards. Calculate how many bytes we need:
+	var/*int*/ numEncodingBytes = numEncodingBytes(val);
+	
+	if ((offset + numEncodingBytes) > buf.length) {
+		throw new Exception("Buffer space of " + (buf.length-offset) + 
+											" bytes insufficient to hold " + 
+											numEncodingBytes + " of encoded type and value.");
+	}
+	
+
+	buf[offset + numEncodingBytes - 1] = 
+		(BYTE_MASK &
+					(((XML_TT_MASK & type) | 
+					 ((XML_TT_VAL_MASK & val) << XML_TT_BITS))) |
+					 XML_TT_NO_MORE); 
+	val = val >>> XML_TT_VAL_BITS;;
+
+	var /*int*/ i = offset + numEncodingBytes - 2;
+	while ((0 != val) && (i >= offset)) {
+		buf[i] = (BYTE_MASK &
+						    (val & XML_REG_VAL_MASK)); 
+		val = val >>> XML_REG_VAL_BITS;
+		--i;
+	}
+	
+	return numEncodingBytes;
+};
+
+
+BinaryXMLCodec.prototype.encodeTypeAndVal = function(
+		//int
+		type, 
+		//long 
+		val, 
+		//byte [] 
+		buf, 
+		//int 
+		offset) {
+	
+	if ((type > XML_UDATA) || (type < 0) || (val < 0)) {
+		throw new Exception("Tag and value must be positive, and tag valid.");
+	}
+	
+	// Encode backwards. Calculate how many bytes we need:
+	//int
+	var numEncodingBytes = numEncodingBytes(val);
+	
+	if ((offset + numEncodingBytes) > buf.length) {
+		throw new Exception("Buffer space of " + (buf.length-offset) + 
+											" bytes insufficient to hold " + 
+											numEncodingBytes + " of encoded type and value.");
+	}
+	
+	// Bottom 4 bits of val go in last byte with tag.
+	buf[offset + numEncodingBytes - 1] = 
+		//(byte)
+			(BYTE_MASK &
+					(((XML_TT_MASK & type) | 
+					 ((XML_TT_VAL_MASK & val) << XML_TT_BITS))) |
+					 XML_TT_NO_MORE); // set top bit for last byte
+	val = val >>> XML_TT_VAL_BITS;;
+	
+	// Rest of val goes into preceding bytes, 7 bits per byte, top bit
+	// is "more" flag.
+	var i = offset + numEncodingBytes - 2;
+	while ((0 != val) && (i >= offset)) {
+		buf[i] = //(byte)
+				(BYTE_MASK &
+						    (val & XML_REG_VAL_MASK)); // leave top bit unset
+		val = val >>> XML_REG_VAL_BITS;
+		--i;
+	}
+	if (val != 0) {
+		throw new Exception( "This should not happen: miscalculated encoding");
+		//Log.warning(Log.FAC_ENCODING, "This should not happen: miscalculated encoding length, have " + val + " left.");
+	}
+	
+	return numEncodingBytes;
+}
+
+
+	
+BinaryXMLCodec.prototype.decodeTypeAndVal = function(
+		/*InputStream*/
+		istream) {
+	
+	/*int*/next;
+	/*int*/type = -1;
+	/*long*/val = 0;
+	/*boolean*/more = true;
+
+	do {
+		next = istream.read();
+		
+		if (next < 0) {
+			return null; 
+		}
+
+		if ((0 == next) && (0 == val)) {
+			return null;
+		}
+		
+		more = (0 == (next & XML_TT_NO_MORE));
+		
+		if  (more) {
+			val = val << XML_REG_VAL_BITS;
+			val |= (next & XML_REG_VAL_MASK);
+		} else {
+
+			type = next & XML_TT_MASK;
+			val = val << XML_TT_VAL_BITS;
+			val |= ((next >>> XML_TT_BITS) & XML_TT_VAL_MASK);
+		}
+		
+	} while (more);
+	
+	return new TypeAndVal(type, val);
+};
+
+BinaryXMLCodec.prototype.encodeUString = function(
+		//OutputStream 
+		ostream, 
+		//String 
+		ustring, 
+		//byte 
+		type,
+		offset) {
+	
+	// We elide the encoding of a 0-length UString
+	if ((null == ustring) || (ustring.length == 0)) {
+		//if (Log.isLoggable(Log.FAC_ENCODING, Level.FINER))
+			//Log.finer(Log.FAC_ENCODING, "Eliding 0-length UString.");
+		return;
+	}
+	
+	//byte [] data utils
+	/*custom*/
+	//byte[]
+	strBytes = new Array(ustring.Length);
+	var i = 0;
+	for( ;i<ustring.lengh;i++) //in InStr.ToCharArray())
+	{
+		strBytes[i] = ustring[i];
+	}
+	//strBytes = DataUtils.getBytesFromUTF8String(ustring);
+	
+	this.encodeTypeAndVal(type, 
+						(((type == XML_TAG) || (type == XML_ATTR)) ?
+								(strBytes.length-1) :
+								strBytes.length), ostream);
+	//
+	//console.log(strBytes.toString());
+	
+	ostream.write(strBytes.toString(),offset);
+	
+	// 
+};
+
+BinaryXMLCodec.prototype.encodeBlob = function(
+		//OutputStream 
+		ostream, 
+		//byte [] 
+		blob, 
+		//int 
+		offset, 
+		//int 
+		length) {
+	// We elide the encoding of a 0-length blob
+	if ((null == blob) || (length == 0)) {
+
+		return;
+	}
+	
+	encodeTypeAndVal(XML_BLOB, length, ostream,offset);
+	if (null != blob) {
+		ostream.write(blob, this.offset, length);
+		this.offset += length;
+	}
+};
+
+
+var ENCODING_LIMIT_1_BYTE = ((1 << (XML_TT_VAL_BITS)) - 1);
+var ENCODING_LIMIT_2_BYTES = ((1 << (XML_TT_VAL_BITS + XML_REG_VAL_BITS)) - 1);
+var ENCODING_LIMIT_3_BYTES = ((1 << (XML_TT_VAL_BITS + 2 * XML_REG_VAL_BITS)) - 1);
+
+var numEncodingBytes = function(
+		//long
+		x) {
+	if (x <= ENCODING_LIMIT_1_BYTE) return (1);
+	if (x <= ENCODING_LIMIT_2_BYTES) return (2);
+	if (x <= ENCODING_LIMIT_3_BYTES) return (3);
+	
+	var numbytes = 1;
+	
+	// Last byte gives you XML_TT_VAL_BITS
+	// Remainder each give you XML_REG_VAL_BITS
+	x = x >>> XML_TT_VAL_BITS;
+	while (x != 0) {
+        numbytes++;
+		x = x >>> XML_REG_VAL_BITS;
+	}
+	return (numbytes);
+}
+
+//TODO
\ No newline at end of file
diff --git a/js/encoding/BinaryXMLDecoder.js b/js/encoding/BinaryXMLDecoder.js
new file mode 100644
index 0000000..f70cca4
--- /dev/null
+++ b/js/encoding/BinaryXMLDecoder.js
@@ -0,0 +1,654 @@
+/*
+ * This class is used to encode and decode binary elements ( blog, type/value pairs)
+ * 
+ * @author: ucla-cs
+ */
+
+var XML_EXT = 0x00; 
+	
+var XML_TAG = 0x01; 
+	
+var XML_DTAG = 0x02; 
+	
+var XML_ATTR = 0x03; 
+ 
+var XML_DATTR = 0x04; 
+	
+var XML_BLOB = 0x05; 
+	
+var XML_UDATA = 0x06; 
+	
+var XML_CLOSE = 0x0;
+
+var XML_SUBTYPE_PROCESSING_INSTRUCTIONS = 16; 
+	
+
+var XML_TT_BITS = 3;
+var XML_TT_MASK = ((1 << XML_TT_BITS) - 1);
+var XML_TT_VAL_BITS = XML_TT_BITS + 1;
+var XML_TT_VAL_MASK = ((1 << (XML_TT_VAL_BITS)) - 1);
+var XML_REG_VAL_BITS = 7;
+var XML_REG_VAL_MASK = ((1 << XML_REG_VAL_BITS) - 1);
+var XML_TT_NO_MORE = (1 << XML_REG_VAL_BITS); // 0x80
+var BYTE_MASK = 0xFF;
+var LONG_BYTES = 8;
+var LONG_BITS = 64;
+	
+var bits_11 = 0x0000007FF;
+var bits_18 = 0x00003FFFF;
+var bits_32 = 0x0FFFFFFFF;
+
+
+
+//returns a string
+tagToString = function(/*long*/ tagVal) {
+	if ((tagVal >= 0) && (tagVal < CCNProtocolDTagsStrings.length)) {
+		return CCNProtocolDTagsStrings[tagVal];
+	} else if (tagVal == CCNProtocolDTags.CCNProtocolDataUnit) {
+		return CCNProtocolDTags.CCNPROTOCOL_DATA_UNIT;
+	}
+	return null;
+};
+
+//returns a Long
+stringToTag =  function(/*String*/ tagName) {
+	// the slow way, but right now we don't care.... want a static lookup for the forward direction
+	for (var i=0; i < CCNProtocolDTagsStrings.length; ++i) {
+		if ((null != CCNProtocolDTagsStrings[i]) && (CCNProtocolDTagsStrings[i] == tagName)) {
+			return i;
+		}
+	}
+	if (CCNProtocolDTags.CCNPROTOCOL_DATA_UNIT == tagName) {
+		return CCNProtocolDTags.CCNProtocolDataUnit;
+	}
+	return null;
+};
+
+//console.log(stringToTag(64));
+var BinaryXMLDecoder = function BinaryXMLDecoder(istream){
+	var MARK_LEN=512;
+	var DEBUG_MAX_LEN =  32768;
+	
+	this.istream = istream;
+	//console.log('istream is '+ this.istream);
+	this.offset = 0;
+};
+
+
+BinaryXMLDecoder.prototype.readStartElement =function(
+	//String
+	startTag,				    
+	//TreeMap<String, String>
+	attributes) {
+
+	try {
+		//this.TypeAndVal 
+		tv = this.decodeTypeAndVal(this.istream);
+
+		if (null == tv) {
+			throw new Exception("Expected start element: " + startTag + " got something not a tag.");
+		}
+		
+		//String 
+		decodedTag = null;
+		
+		if (tv.type() == XML_TAG) {
+			
+			decodedTag = this.decodeUString(this.Istream, tv.val()+1);
+			
+		} else if (tv.type() == XML_DTAG) {
+			decodedTag = tagToString(tv.val());	
+		}
+		
+		if ((null ==  decodedTag) || decodedTag != startTag) {
+			throw new Exception("Expected start element: " + startTag + " got: " + decodedTag + "(" + tv.val() + ")");
+		}
+		
+		if (null != attributes) {
+			readAttributes(attributes); 
+		}
+		
+	} catch (e) {
+		throw new Exception("readStartElement", e);
+	}
+};
+
+BinaryXMLDecoder.prototype.readAttributes = function(
+	//TreeMap<String,String> 
+	attributes){
+	
+	if (null == attributes) {
+		return;
+	}
+
+	try {
+
+		//this.TypeAndVal 
+		nextTV = this.peekTypeAndVal(this.istream);
+
+		while ((null != nextTV) && ((XML_ATTR == nextTV.type()) ||
+				(XML_DATTR == nextTV.type()))) {
+
+			//this.TypeAndVal 
+			thisTV = this.decodeTypeAndVal(this.Istream);
+
+			var attributeName = null;
+			if (XML_ATTR == thisTV.type()) {
+				
+				attributeName = this.decodeUString(this.istream, thisTV.val()+1);
+
+			} else if (XML_DATTR == thisTV.type()) {
+				// DKS TODO are attributes same or different dictionary?
+				attributeName = tagToString(thisTV.val());
+				if (null == attributeName) {
+					throw new ContentDecodingException("Unknown DATTR value" + thisTV.val());
+				}
+			}
+			
+			var attributeValue = this.decodeUString(this.istream);
+
+			attributes.put(attributeName, attributeValue);
+
+			nextTV = this.peekTypeAndVal(this.istream);
+		}
+
+	} catch ( e) {
+
+		throw new ContentDecodingException("readStartElement", e);
+	}
+};
+
+
+BinaryXMLDecoder.prototype.initializeDecoding = function() {
+		//if (!this.istream.markSupported()) {
+			//throw new IllegalArgumentException(this.getClass().getName() + ": input stream must support marking!");
+		//}
+}
+
+BinaryXMLDecoder.prototype.readStartDocument = function(){
+		// Currently no start document in binary encoding.
+	}
+
+BinaryXMLDecoder.prototype.readEndDocument = function() {
+		// Currently no end document in binary encoding.
+	};
+
+BinaryXMLDecoder.prototype.readStartElement = function(
+		//String 
+		startTag,
+		//TreeMap<String, String> 
+		attributes) {
+	
+		
+		//NOT SURE
+		//if(typeof startTag == 'number')
+			//startTag = tagToString(startTag);
+		
+		//try {
+			//TypeAndVal 
+			tv = this.decodeTypeAndVal(this.istream);
+			
+			if (null == tv) {
+				throw new Exception("Expected start element: " + startTag + " got something not a tag.");
+			}
+			
+			//String 
+			decodedTag = null;
+			//console.log(tv);
+			//console.log(typeof tv);
+			
+			//console.log(XML_TAG);
+			if (tv.type() == XML_TAG) {
+				//console.log('got here');
+				//Log.info(Log.FAC_ENCODING, "Unexpected: got tag in readStartElement; looking for tag " + startTag + " got length: " + (int)tv.val()+1);
+				// Tag value represents length-1 as tags can never be empty.
+				var valval ;
+				if(typeof tv.val() == 'string'){
+					valval = (parseInt(tv.val())) + 1;
+				}
+				else
+					valval = (tv.val())+ 1;
+				
+				//console.log('valval is ' +valval);
+				
+				decodedTag = this.decodeUString(this.istream,  valval);
+				
+			} else if (tv.type() == XML_DTAG) {
+				//console.log('gothere');
+				//console.log(tv.val());
+				//decodedTag = tagToString(tv.val());
+				//console.log()
+				decodedTag = tv.val();
+			}
+			
+			//console.log(decodedTag);
+			//console.log('startTag is '+startTag);
+			
+			
+			if ((null ==  decodedTag) || decodedTag != startTag ) {
+				console.log('expecting '+ startag + ' but got '+ decodedTag);
+				throw new Exception("Expected start element: " + startTag + " got: " + decodedTag + "(" + tv.val() + ")");
+			}
+			
+			// DKS: does not read attributes out of stream if caller doesn't
+			// ask for them. Should possibly peek and skip over them regardless.
+			// TODO: fix this
+			if (null != attributes) {
+				readAttributes(attributes); 
+			}
+			
+		//} catch ( e) {
+			//console.log(e);
+			//throw new Exception("readStartElement", e);
+		//}
+	}
+	
+
+BinaryXMLDecoder.prototype.readAttributes = function(
+	//TreeMap<String,String> 
+	attributes) {
+	
+	if (null == attributes) {
+		return;
+	}
+
+	try {
+		// Now need to get attributes.
+		//TypeAndVal 
+		nextTV = this.peekTypeAndVal(this.istream);
+
+		while ((null != nextTV) && ((XML_ATTR == nextTV.type()) ||
+				(XML_DATTR == nextTV.type()))) {
+
+			// Decode this attribute. First, really read the type and value.
+			//this.TypeAndVal 
+			thisTV = this.decodeTypeAndVal(this.istream);
+
+			//String 
+			attributeName = null;
+			if (XML_ATTR == thisTV.type()) {
+				// Tag value represents length-1 as attribute names cannot be empty.
+				var valval ;
+				if(typeof tv.val() == 'string'){
+					valval = (parseInt(tv.val())) + 1;
+				}
+				else
+					valval = (tv.val())+ 1;
+				
+				attributeName = this.decodeUString(this.istream,valval);
+
+			} else if (XML_DATTR == thisTV.type()) {
+				// DKS TODO are attributes same or different dictionary?
+				attributeName = tagToString(thisTV.val());
+				if (null == attributeName) {
+					throw new Exception("Unknown DATTR value" + thisTV.val());
+				}
+			}
+			// Attribute values are always UDATA
+			//String
+			attributeValue = this.decodeUString(this.istream);
+
+			//
+			attributes.push([attributeName, attributeValue]);
+
+			nextTV = this.peekTypeAndVal(this.istream);
+		}
+
+	} catch ( e) {
+		Log.logStackTrace(Log.FAC_ENCODING, Level.WARNING, e);
+		throw new Exception("readStartElement", e);
+	}
+};
+
+//returns a string
+BinaryXMLDecoder.prototype.peekStartElementAsString = function() {
+	//this.istream.mark(MARK_LEN);
+
+	//String 
+	decodedTag = null;
+	var previousOffset = this.offset;
+	try {
+		// Have to distinguish genuine errors from wrong tags. Could either use
+		// a special exception subtype, or redo the work here.
+		//this.TypeAndVal 
+		tv = this.decodeTypeAndVal(this.istream);
+
+		if (null != tv) {
+
+			if (tv.type() == XML_TAG) {
+				/*if (tv.val()+1 > DEBUG_MAX_LEN) {
+					throw new ContentDecodingException("Decoding error: length " + tv.val()+1 + " longer than expected maximum length!");
+				}*/
+
+				// Tag value represents length-1 as tags can never be empty.
+				var valval ;
+				if(typeof tv.val() == 'string'){
+					valval = (parseInt(tv.val())) + 1;
+				}
+				else
+					valval = (tv.val())+ 1;
+				
+				decodedTag = this.decodeUString(this.istream, valval);
+				
+				//Log.info(Log.FAC_ENCODING, "Unexpected: got text tag in peekStartElement; length: " + valval + " decoded tag = " + decodedTag);
+
+			} else if (tv.type() == XML_DTAG) {
+				decodedTag = tagToString(tv.val());					
+			}
+
+		} // else, not a type and val, probably an end element. rewind and return false.
+
+	} catch ( e) {
+
+	} finally {
+		try {
+			this.offset = previousOffset;
+		} catch ( e) {
+			Log.logStackTrace(Log.FAC_ENCODING, Level.WARNING, e);
+			throw new ContentDecodingException("Cannot reset stream! " + e.getMessage(), e);
+		}
+	}
+	return decodedTag;
+};
+
+BinaryXMLDecoder.prototype.peekStartElement = function(
+		//String 
+		startTag) {
+	//String 
+	if(typeof startTag == 'string'){
+		decodedTag = this.peekStartElementAsString();
+		
+		if ((null !=  decodedTag) && decodedTag == startTag) {
+			return true;
+		}
+		return false;
+	}
+	else if(typeof startTag == 'number'){
+		decodedTag = this.peekStartElementAsLong();
+		if ((null !=  decodedTag) && decodedTag == startTag) {
+			return true;
+		}
+		return false;
+	}
+	else{
+		throw new Exception("SHOULD BE STRING OR NUMBER");
+	}
+}
+//returns Long
+BinaryXMLDecoder.prototype.peekStartElementAsLong = function() {
+		//this.istream.mark(MARK_LEN);
+
+		//Long
+		decodedTag = null;
+		
+		var previousOffset = this.offset;
+		
+		try {
+			// Have to distinguish genuine errors from wrong tags. Could either use
+			// a special exception subtype, or redo the work here.
+			//this.TypeAndVal
+			tv = this.decodeTypeAndVal(this.istream);
+
+			if (null != tv) {
+
+				if (tv.type() == XML_TAG) {
+					if (tv.val()+1 > DEBUG_MAX_LEN) {
+						throw new ContentDecodingException("Decoding error: length " + tv.val()+1 + " longer than expected maximum length!");
+					}
+
+					var valval ;
+					if(typeof tv.val() == 'string'){
+						valval = (parseInt(tv.val())) + 1;
+					}
+					else
+						valval = (tv.val())+ 1;
+					
+					// Tag value represents length-1 as tags can never be empty.
+					//String 
+					strTag = this.decodeUString(this.istream, valval);
+					
+					decodedTag = stringToTag(strTag);
+					
+					//Log.info(Log.FAC_ENCODING, "Unexpected: got text tag in peekStartElement; length: " + valval + " decoded tag = " + decodedTag);
+					
+				} else if (tv.type() == XML_DTAG) {
+					decodedTag = tv.val();					
+				}
+
+			} // else, not a type and val, probably an end element. rewind and return false.
+
+		} catch ( e) {
+			
+		} finally {
+			try {
+				//this.istream.reset();
+				this.offset = previousOffset;
+			} catch ( e) {
+				Log.logStackTrace(Log.FAC_ENCODING, Level.WARNING, e);
+				throw new Exception("Cannot reset stream! " + e.getMessage(), e);
+			}
+		}
+		return decodedTag;
+	};
+
+
+// returns a byte[]
+BinaryXMLDecoder.prototype.readBinaryElement = function(
+		//long 
+		startTag,
+		//TreeMap<String, String> 
+		attributes){
+	//byte [] 
+	blob = null;
+	
+		this.readStartElement(startTag, attributes);
+		blob = this.readBlob();
+	
+
+	return blob;
+
+};
+	
+	
+BinaryXMLDecoder.prototype.readEndElement = function(){
+		try {
+			var next = this.istream[this.offset]; 
+			this.offset++;
+			//read();
+			if (next != XML_CLOSE) {
+				throw new ContentDecodingException("Expected end element, got: " + next);
+			}
+		} catch ( e) {
+			throw new ContentDecodingException(e);
+		}
+	};
+
+
+//String	
+BinaryXMLDecoder.prototype.readUString = function(){
+			//String 
+			ustring = this.decodeUString(this.istream);	
+			this.readEndElement();
+			return ustring;
+
+	};
+	
+
+//returns a byte[]
+BinaryXMLDecoder.prototype.readBlob = function() {
+			//byte []
+			
+			blob = this.decodeBlob(this.istream);	
+			this.readEndElement();
+			return blob;
+
+	};
+
+
+//CCNTime
+BinaryXMLDecoder.prototype.readDateTime = function(
+	//long 
+	startTag)  {
+	//byte [] 
+	
+	byteTimestamp = this.readBinaryElement(startTag);
+	//CCNTime 
+	timestamp = new CCNTime();
+	timestamp.setDateBinary(byteTimestamp);
+	
+	if (null == timestamp) {
+		throw new ContentDecodingException("Cannot parse timestamp: " + DataUtils.printHexBytes(byteTimestamp));
+	}		
+	return timestamp;
+};
+
+BinaryXMLDecoder.prototype.decodeTypeAndVal = function(
+		/*InputStream*/
+		istream) {
+	
+	/*int*/next;
+	/*int*/type = -1;
+	/*long*/val = 0;
+	/*boolean*/more = true;
+
+	
+	//var savedOffset = this.offset;
+	var count = 0;
+	
+	do {
+		
+		var next = this.istream[this.offset ];
+		
+		
+		if (next < 0) {
+			return null; 
+		}
+
+		if ((0 == next) && (0 == val)) {
+			return null;
+		}
+		
+		more = (0 == (next & XML_TT_NO_MORE));
+		
+		if  (more) {
+			val = val << XML_REG_VAL_BITS;
+			val |= (next & XML_REG_VAL_MASK);
+		} else {
+
+			type = next & XML_TT_MASK;
+			val = val << XML_TT_VAL_BITS;
+			val |= ((next >>> XML_TT_BITS) & XML_TT_VAL_MASK);
+		}
+		
+		this.offset++;
+		
+	} while (more);
+	
+	return new TypeAndVal(type, val);
+};
+
+
+
+//TypeAndVal
+BinaryXMLDecoder.peekTypeAndVal = function(
+		//InputStream 
+		istream) {
+	//TypeAndVal 
+	tv = null;
+	
+	//istream.mark(LONG_BYTES*2);		
+	
+	var previousOffset = this.offset;
+	
+	try {
+		tv = this.decodeTypeAndVal(this.istream);
+	} finally {
+		//istream.reset();
+		this.offset = previousOffset;
+	}
+	
+	return tv;
+};
+
+
+//byte[]
+BinaryXMLDecoder.prototype.decodeBlob = function(
+		//InputStream 
+		istream, 
+		//int 
+		blobLength) {
+	
+	
+	if(null == blobLength){
+		//TypeAndVal
+		tv = this.decodeTypeAndVal(this.istream);
+
+		var valval ;
+		if(typeof tv.val() == 'string'){
+			valval = (parseInt(tv.val()));
+		}
+		else
+			valval = (tv.val());
+		
+		//console.log('valval here is ' + valval);
+		return  this.decodeBlob(this.istream, valval);
+	}
+	
+	//
+	//byte [] 
+
+	bytes = this.istream.slice(this.offset, this.offset+ blobLength);
+	this.offset += blobLength;
+	
+	//int 
+	return bytes;
+	
+	count = 0;
+
+};
+
+
+
+//String
+BinaryXMLDecoder.prototype.decodeUString = function(
+		//InputStream 
+		istream, 
+		//int 
+		byteLength) {
+	
+	if(null == byteLength){
+		tv = this.decodeTypeAndVal(this.istream);
+		var valval ;
+		if(typeof tv.val() == 'string'){
+			valval = (parseInt(tv.val()));
+		}
+		else
+			valval = (tv.val());
+		
+		byteLength= this.decodeUString(this.istream, valval);
+	}
+
+	stringBytes = this.decodeBlob(this.istream, byteLength);
+	
+	tempBuffer = this.istream.slice(this.offset, this.offset+byteLength);
+	this.offset+= byteLength;
+	console.log('read the String' + tempBuffer.toString('ascii'));
+	return tempBuffer.toString('ascii');//DataUtils.getUTF8StringFromBytes(stringBytes);
+};
+
+
+//OBject containg a pair of type and value
+var TypeAndVal = function TypeAndVal(_type,_val) {
+	this.t = _type;
+	this.v = _val;
+	
+};
+
+TypeAndVal.prototype.type = function(){
+	return this.t;
+};
+
+TypeAndVal.prototype.val = function(){
+	return this.v;
+};
+//TODO
\ No newline at end of file
diff --git a/js/encoding/BinaryXMLEncoder.js b/js/encoding/BinaryXMLEncoder.js
new file mode 100644
index 0000000..f05a869
--- /dev/null
+++ b/js/encoding/BinaryXMLEncoder.js
@@ -0,0 +1,340 @@
+/*
+ * This class is used to encode and decode binary elements ( blog, type/value pairs)
+ * 
+ * @author: ucla-cs
+ */
+
+var XML_EXT = 0x00; 
+	
+var XML_TAG = 0x01; 
+	
+var XML_DTAG = 0x02; 
+	
+var XML_ATTR = 0x03; 
+ 
+var XML_DATTR = 0x04; 
+	
+var XML_BLOB = 0x05; 
+	
+var XML_UDATA = 0x06; 
+	
+var XML_CLOSE = 0x0;
+
+var XML_SUBTYPE_PROCESSING_INSTRUCTIONS = 16; 
+	
+
+var XML_TT_BITS = 3;
+var XML_TT_MASK = ((1 << XML_TT_BITS) - 1);
+var XML_TT_VAL_BITS = XML_TT_BITS + 1;
+var XML_TT_VAL_MASK = ((1 << (XML_TT_VAL_BITS)) - 1);
+var XML_REG_VAL_BITS = 7;
+var XML_REG_VAL_MASK = ((1 << XML_REG_VAL_BITS) - 1);
+var XML_TT_NO_MORE = (1 << XML_REG_VAL_BITS); // 0x80
+var BYTE_MASK = 0xFF;
+var LONG_BYTES = 8;
+var LONG_BITS = 64;
+	
+var bits_11 = 0x0000007FF;
+var bits_18 = 0x00003FFFF;
+var bits_32 = 0x0FFFFFFFF;
+
+
+var BinaryXMLEncoder = function BinaryXMLEncoder(){
+
+	this.ostream = new Array(10000);
+	
+	
+	this.offset =0;
+	
+	this.CODEC_NAME = "Binary";
+	
+};
+
+BinaryXMLEncoder.prototype.writeUString = function(/*String*/ utf8Content){
+	this.encodeUString(this.ostream, utf8Content);
+};
+
+BinaryXMLEncoder.prototype.writeBlob = function(/*byte []*/ binaryContent
+		//, /*int*/ offset, /*int*/ length
+		)  {
+	console.log(binaryContent);
+	this.encodeBlob(this.ostream, binaryContent, this.offset, binaryContent.length);
+};
+
+BinaryXMLEncoder.prototype.writeStartElement = function(/*String*/ tag, /*TreeMap<String,String>*/ attributes){
+
+	/*Long*/ dictionaryVal = tag;//stringToTag(tag);
+	
+	if (null == dictionaryVal) {
+
+		this.encodeUString(this.ostream, tag, XML_TAG);
+		
+	} else {
+		this.encodeTypeAndVal(XML_DTAG, dictionaryVal, this.ostream);
+	}
+	
+	if (null != attributes) {
+		this.writeAttributes(attributes); 
+	}
+};
+
+
+BinaryXMLEncoder.prototype.writeEndElement = function(){
+
+	this.ostream[this.offset] = XML_CLOSE;
+	this.offset+= 1;
+}
+
+BinaryXMLEncoder.prototype.writeAttributes = function(/*TreeMap<String,String>*/ attributes) {
+	
+	if (null == attributes) {
+		return;
+	}
+
+	// the keySet of a TreeMap is sorted.
+
+	for(var i=0; i<attributes.length;i++){
+		var strAttr = attributes[i].k;
+		var strValue = attributes[i].v;
+
+		var dictionaryAttr = stringToTag(strAttr);
+		if (null == dictionaryAttr) {
+			// not in dictionary, encode as attr
+			// compressed format wants length of tag represented as length-1
+			// to save that extra bit, as tag cannot be 0 length.
+			// encodeUString knows to do that.
+			this.encodeUString(this.ostream, strAttr, XML_ATTR);
+		} else {
+			this.encodeTypeAndVal(XML_DATTR, dictionaryAttr, this.ostream);
+		}
+		// Write value
+		this.encodeUString(this.ostream, strValue);
+		
+	}
+
+	
+}
+
+//returns a string
+stringToTag = function(/*long*/ tagVal) {
+	if ((tagVal >= 0) && (tagVal < CCNProtocolDTagsStrings.length)) {
+		return CCNProtocolDTagsStrings[tagVal];
+	} else if (tagVal == CCNProtocolDTags.CCNProtocolDataUnit) {
+		return CCNProtocolDTags.CCNPROTOCOL_DATA_UNIT;
+	}
+	return null;
+};
+
+//returns a Long
+tagToString =  function(/*String*/ tagName) {
+	// the slow way, but right now we don't care.... want a static lookup for the forward direction
+	for (var i=0; i < CCNProtocolDTagsStrings.length; ++i) {
+		if ((null != CCNProtocolDTagsStrings[i]) && (CCNProtocolDTagsStrings[i] == tagName)) {
+			return i;
+		}
+	}
+	if (CCNProtocolDTags.CCNPROTOCOL_DATA_UNIT == tagName) {
+		return CCNProtocolDTags.CCNProtocolDataUnit;
+	}
+	return null;
+};
+
+
+BinaryXMLEncoder.prototype.writeElement = function(
+		//long 
+		tag, 
+		//byte[] 
+		binaryContent,
+		//TreeMap<String, String> 
+		attributes) {
+	this.writeStartElement(tag, attributes);
+	// Will omit if 0-length
+	
+	this.writeBlob(binaryContent);
+	this.writeEndElement();
+}
+
+//TODO
+
+var TypeAndVal = function TypeAndVal(_type,_val) {
+	this.type = _type;
+	this.val = _val;
+	
+};
+
+BinaryXMLEncoder.prototype.encodeTypeAndVal = function(
+		//int
+		type, 
+		//long 
+		val, 
+		//byte [] 
+		buf) {
+	
+	console.log('Encoding type '+ type+ ' and value '+ val);
+	
+	if ((type > XML_UDATA) || (type < 0) || (val < 0)) {
+		throw new Exception("Tag and value must be positive, and tag valid.");
+	}
+	
+	// Encode backwards. Calculate how many bytes we need:
+	var numEncodingBytes = this.numEncodingBytes(val);
+	
+	if ((this.offset + numEncodingBytes) > buf.length) {
+		throw new Exception("Buffer space of " + (buf.length-this.offset) + 
+											" bytes insufficient to hold " + 
+											numEncodingBytes + " of encoded type and value.");
+	}
+
+	// Bottom 4 bits of val go in last byte with tag.
+	buf[this.offset + numEncodingBytes - 1] = 
+		//(byte)
+			(BYTE_MASK &
+					(((XML_TT_MASK & type) | 
+					 ((XML_TT_VAL_MASK & val) << XML_TT_BITS))) |
+					 XML_TT_NO_MORE); // set top bit for last byte
+	val = val >>> XML_TT_VAL_BITS;;
+	
+	// Rest of val goes into preceding bytes, 7 bits per byte, top bit
+	// is "more" flag.
+	var i = this.offset + numEncodingBytes - 2;
+	while ((0 != val) && (i >= this.offset)) {
+		buf[i] = //(byte)
+				(BYTE_MASK &
+						    (val & XML_REG_VAL_MASK)); // leave top bit unset
+		val = val >>> XML_REG_VAL_BITS;
+		--i;
+	}
+	if (val != 0) {
+		throw new Exception( "This should not happen: miscalculated encoding");
+		//Log.warning(Log.FAC_ENCODING, "This should not happen: miscalculated encoding length, have " + val + " left.");
+	}
+	this.offset+= numEncodingBytes;
+	
+	return numEncodingBytes;
+};
+
+BinaryXMLEncoder.prototype.encodeUString = function(
+		//OutputStream 
+		ostream, 
+		//String 
+		ustring, 
+		//byte 
+		type) {
+	
+	if ((null == ustring) || (ustring.length == 0)) {
+		return;
+	}
+	
+	
+	//byte [] data utils
+	/*custom*/
+	//byte[]
+	strBytes = new Array(ustring.Length);
+	var i = 0;
+	for( ;i<ustring.lengh;i++) //in InStr.ToCharArray())
+	{
+		strBytes[i] = ustring[i];
+	}
+	//strBytes = DataUtils.getBytesFromUTF8String(ustring);
+	
+	this.encodeTypeAndVal(type, 
+						(((type == XML_TAG) || (type == XML_ATTR)) ?
+								(strBytes.length-1) :
+								strBytes.length), ostream);
+	
+
+	this.writeString(strBytes,this.offset);
+	
+	this.offset+= strBytes.length;
+
+};
+
+
+
+BinaryXMLEncoder.prototype.encodeBlob = function(
+		//OutputStream 
+		ostream, 
+		//byte [] 
+		blob, 
+		//int 
+		offset, 
+		//int 
+		length) {
+
+
+	if ((null == blob) || (length == 0)) {
+
+		return;
+	}
+	
+	
+	this.encodeTypeAndVal(XML_BLOB, length, ostream,offset);
+	
+	if (null != blob) {
+
+		this.writeString(blob,this.offset);
+		this.offset += length;
+	}
+};
+
+var ENCODING_LIMIT_1_BYTE = ((1 << (XML_TT_VAL_BITS)) - 1);
+var ENCODING_LIMIT_2_BYTES = ((1 << (XML_TT_VAL_BITS + XML_REG_VAL_BITS)) - 1);
+var ENCODING_LIMIT_3_BYTES = ((1 << (XML_TT_VAL_BITS + 2 * XML_REG_VAL_BITS)) - 1);
+
+BinaryXMLEncoder.prototype.numEncodingBytes = function(
+		//long
+		x) {
+	if (x <= ENCODING_LIMIT_1_BYTE) return (1);
+	if (x <= ENCODING_LIMIT_2_BYTES) return (2);
+	if (x <= ENCODING_LIMIT_3_BYTES) return (3);
+	
+	var numbytes = 1;
+	
+	// Last byte gives you XML_TT_VAL_BITS
+	// Remainder each give you XML_REG_VAL_BITS
+	x = x >>> XML_TT_VAL_BITS;
+	while (x != 0) {
+        numbytes++;
+		x = x >>> XML_REG_VAL_BITS;
+	}
+	return (numbytes);
+};
+
+BinaryXMLEncoder.prototype.writeDateTime = function(
+		//String 
+		tag, 
+		//CCNTime 
+		dateTime) {
+	this.writeElement(tag, dateTime.toBinaryTime());
+};
+
+BinaryXMLEncoder.prototype.writeString = function(
+		//String 
+		input,
+		//CCNTime 
+		offset) {
+	
+	
+	for (var i = 0; i < input.length; i++) {
+	    this.ostream[this.offset+i] = (input.charCodeAt(i));
+	}
+	
+};
+
+BinaryXMLEncoder.prototype.writeBlobArray = function(
+		//String 
+		Blob,
+		//CCNTime 
+		offset) {
+	
+	for (var i = 0; i < Blob.length; i++) {
+	    this.ostream[this.offset+i] = Blob[i];
+	}
+	
+};
+BinaryXMLEncoder.prototype.getReducedOstream = function() {
+	
+	return this.ostream.slice(0,this.offset);
+	
+};
+
diff --git a/js/encoding/DataUtils.js b/js/encoding/DataUtils.js
new file mode 100644
index 0000000..92a4257
--- /dev/null
+++ b/js/encoding/DataUtils.js
@@ -0,0 +1,137 @@
+
+/*
+ * This class contains utilities to help parse the data
+ * author: ucla-cs
+ */
+ 
+var DataUtils = function DataUtils(){
+	
+	
+};
+
+
+/*
+ * NOTE THIS IS CURRENTLY NOT BEHING USED
+ * 
+ */
+
+  var keyStr = "ABCDEFGHIJKLMNOP" +
+               "QRSTUVWXYZabcdef" +
+               "ghijklmnopqrstuv" +
+               "wxyz0123456789+/" +
+               "=";
+
+DataUtils.encode64=function encode64(input) {
+     input = escape(input);
+     var output = "";
+     var chr1, chr2, chr3 = "";
+     var enc1, enc2, enc3, enc4 = "";
+     var i = 0;
+
+     do {
+        chr1 = input.charCodeAt(i++);
+        chr2 = input.charCodeAt(i++);
+        chr3 = input.charCodeAt(i++);
+
+        enc1 = chr1 >> 2;
+        enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
+        enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
+        enc4 = chr3 & 63;
+
+        if (isNaN(chr2)) {
+           enc3 = enc4 = 64;
+        } else if (isNaN(chr3)) {
+           enc4 = 64;
+        }
+
+        output = output +
+           keyStr.charAt(enc1) +
+           keyStr.charAt(enc2) +
+           keyStr.charAt(enc3) +
+           keyStr.charAt(enc4);
+        chr1 = chr2 = chr3 = "";
+        enc1 = enc2 = enc3 = enc4 = "";
+     } while (i < input.length);
+
+     return output;
+  }
+
+DataUtils.decode64 = function decode64(input) {
+     var output = "";
+     var chr1, chr2, chr3 = "";
+     var enc1, enc2, enc3, enc4 = "";
+     var i = 0;
+
+     // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
+     var base64test = /[^A-Za-z0-9\+\/\=]/g;
+     if (base64test.exec(input)) {
+        alert("There were invalid base64 characters in the input text.\n" +
+              "Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\n" +
+              "Expect errors in decoding.");
+     }
+     input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
+
+     do {
+        enc1 = keyStr.indexOf(input.charAt(i++));
+        enc2 = keyStr.indexOf(input.charAt(i++));
+        enc3 = keyStr.indexOf(input.charAt(i++));
+        enc4 = keyStr.indexOf(input.charAt(i++));
+
+        chr1 = (enc1 << 2) | (enc2 >> 4);
+        chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
+        chr3 = ((enc3 & 3) << 6) | enc4;
+
+        output = output + String.fromCharCode(chr1);
+
+        if (enc3 != 64) {
+           output = output + String.fromCharCode(chr2);
+        }
+        if (enc4 != 64) {
+           output = output + String.fromCharCode(chr3);
+        }
+
+        chr1 = chr2 = chr3 = "";
+        enc1 = enc2 = enc3 = enc4 = "";
+
+     } while (i < input.length);
+
+     return unescape(output);
+  };
+  
+  
+
+
+
+//byte [] 
+DataUtils.prototype.unsignedLongToByteArray= function( value) {
+	if( 0 == value )
+		return [0];
+
+	if( 0 <= value && value <= 0x00FF ) {
+		//byte [] 
+		bb = new Array[1];
+		bb[0] = (value & 0x00FF);
+		return bb;
+	}
+
+	
+	//byte [] 
+	out = null;
+	//int
+	var offset = -1;
+	for(var i = 7; i >=0; --i) {
+		//byte
+		b = ((value >> (i * 8)) & 0xFF);
+		if( out == null && b != 0 ) {
+			out = new byte[i+1];
+			offset = i;
+		}
+		if( out != null )
+			out[ offset - i ] = b;
+	}
+	return out;
+}
+
+
+
+
diff --git a/js/encoding/TextXMLCodec.js b/js/encoding/TextXMLCodec.js
new file mode 100644
index 0000000..716aa6d
--- /dev/null
+++ b/js/encoding/TextXMLCodec.js
@@ -0,0 +1,59 @@
+//TODO INCOMPLETE
+/*
+ * @author: ucla-cs
+ * 
+ * Encodes CCN object into xml tags
+ */
+var DataUtils = require('./DataUtils').DataUtils;
+	
+ 	var /*DateFormat*/ canonicalWriteDateFormat = null;
+	var /* DateFormat*/ canonicalReadDateFormat = null;
+    var /*String*/ PAD_STRING = "000000000";
+	var /*int*/ NANO_LENGTH = 9;
+
+var TextXMLCodec =  function TextXMLCodec(){
+
+	this.CCN_NAMESPACE = "http://www.parc.com/ccn"; // String
+	this.CCN_PREFIX = "ccn";	// String
+	this.CODEC_NAME = "Text";// String
+	this.BINARY_ATTRIBUTE = "ccnbencoding";// String
+	this.BINARY_ATTRIBUTE_VALUE = "base64Binary";// String
+
+
+};
+
+//returns a string
+
+TextXMLCodec.protpotype.codecName = function() { return this.CODEC_NAME; }	;
+
+//returns a string
+TextXMLCodec.protottype.encodeBinaryElement = function(/*byte []*/ element) {
+		if ((null == element) || (0 == element.length)) 
+			return new String("");
+		return new String(DataUtils.base64Encode(element));
+	};
+	
+/* returns a string */
+TextXMLCodec.prototype.encodeBinaryElement = function(/*byte []*/ element, /*int*/ offset, /*int*/ length) {
+		if ((null == element) || (0 == element.length)) 
+			return new String("");
+		ByteBuffer bbuf = ByteBuffer.wrap(element, offset, length);
+		return new String(DataUtils.base64Encode(bbuf.array()));
+	};
+
+/*returns a byte array*/
+TextXMLCodec.prototype.decodeBinaryElement = function(/*String*/ element) {
+		if ((null == element) || (0 == element.length()))
+			return new byte[0];
+		return DataUtils.base64Decode(element.getBytes());
+	}; 
+
+	
+/*
+	Decode Data
+*/
+	
+
+/*
+	Encode Date
+*/ 
\ No newline at end of file
diff --git a/js/encoding/TextXMLDecoder.js b/js/encoding/TextXMLDecoder.js
new file mode 100644
index 0000000..6af8be3
--- /dev/null
+++ b/js/encoding/TextXMLDecoder.js
@@ -0,0 +1,232 @@
+//TODO INCOMPLETE
+
+/*
+ * @author: ucla-cs
+ * 
+ * Decodes CCN object into xml
+ */
+
+var TextXMLDecoder = function TextXMLDecoder(){
+
+	this.reader = null;
+	
+};
+
+
+exports.TextXMLDecoder = TextXMLDecoder;
+
+
+exports.prototype.initializeDecoding = function(){
+	try {
+		XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
+        factory.setNamespaceAware(true);
+		_reader = factory.newPullParser();
+		_reader.setInput(_istream, null);
+	} catch (XmlPullParserException e) {
+		throw new ContentDecodingException(e.getMessage(), e);
+	}		
+};
+
+exports.prototype.readStartDocument = function(){
+	try {
+		int event = _reader.getEventType();
+		_reader.next();
+		if (event != XmlPullParser.START_DOCUMENT) {
+			throw new ContentDecodingException("Expected start document, got: " + XmlPullParser.TYPES[event]);
+		}
+	} catch (XmlPullParserException e) {
+		throw new ContentDecodingException(e.getMessage(), e);
+	} catch (IOException e) {
+		throw new ContentDecodingException(e.getMessage(), e);
+	}
+};
+
+public void readEndDocument() throws ContentDecodingException {
+	int event;
+	try {
+		event = _reader.getEventType();
+	} catch (XmlPullParserException e) {
+		throw new ContentDecodingException(e.getMessage(), e);
+	}
+	if (event != XmlPullParser.END_DOCUMENT) {
+		throw new ContentDecodingException("Expected end document, got: " + XmlPullParser.TYPES[event]);
+	}
+};
+
+exports.prototype.readStartElement = function(/*String*/ startTag,
+							TreeMap<String, String> attributes) throws ContentDecodingException {
+
+	int event = readToNextTag(XmlPullParser.START_TAG);
+	if (event != XmlPullParser.START_TAG) {
+		throw new ContentDecodingException("Expected start element, got: " + XmlPullParser.TYPES[event]);
+	}
+	// Use getLocalPart to strip namespaces.
+	// Assumes we are working with a global default namespace of CCN.
+	if (!startTag.equals(_reader.getName())) {
+		// Coming back with namespace decoration doesn't match
+		throw new ContentDecodingException("Expected start element: " + startTag + " got: " + _reader.getName());
+	}	
+	if (null != attributes) {
+		// we might be expecting attributes
+		for (int i=0; i < _reader.getAttributeCount(); ++i) {
+			// may need fancier namespace handling.
+			attributes.put(_reader.getAttributeName(i), _reader.getAttributeValue(i));
+		}
+	}
+	try {
+		_reader.next();
+	} catch (XmlPullParserException e) {
+		throw new ContentDecodingException(e.getMessage());
+	} catch (IOException e) {
+		throw new ContentDecodingException(e.getMessage());
+	}
+}
+
+	public void readStartElement(long startTagLong,
+			TreeMap<String, String> attributes) throws ContentDecodingException {
+		
+		String startTag = tagToString(startTagLong);
+
+		int event = readToNextTag(XmlPullParser.START_TAG);
+		if (event != XmlPullParser.START_TAG) {
+			throw new ContentDecodingException("Expected start element, got: " + XmlPullParser.TYPES[event]);
+		}
+		// Use getLocalPart to strip namespaces.
+		// Assumes we are working with a global default namespace of CCN.
+		if (!startTag.equals(_reader.getName())) {
+			// Coming back with namespace decoration doesn't match
+			throw new ContentDecodingException("Expected start element: " + startTag + " got: " + _reader.getName());
+		}	
+		if (null != attributes) {
+			// we might be expecting attributes
+			for (int i=0; i < _reader.getAttributeCount(); ++i) {
+				// may need fancier namespace handling.
+				attributes.put(_reader.getAttributeName(i), _reader.getAttributeValue(i));
+			}
+		}
+		try {
+			_reader.next();
+		} catch (XmlPullParserException e) {
+			throw new ContentDecodingException(e.getMessage());
+		} catch (IOException e) {
+			throw new ContentDecodingException(e.getMessage());
+		}
+	}
+	public String peekStartElementAsString() throws ContentDecodingException {
+		int event = readToNextTag(XmlPullParser.START_TAG);
+		if (event != XmlPullParser.START_TAG) {
+			return null;
+		}
+		return _reader.getName();
+	}
+	
+	public Long peekStartElementAsLong() throws ContentDecodingException {
+		String strTag = peekStartElementAsString();
+		if (null == strTag) {
+			return null; // e.g. hit an end tag...
+		}
+		return stringToTag(strTag);
+	}
+	
+	/**
+	 * Helper method to decode text (UTF-8) and binary elements. Consumes the end element,
+	 * behavior which other decoders are forced to match.
+	 * @return the read data, as a String
+	 * @throws ContentDecodingException if there is a problem decoding the data
+	 */
+	public String readUString() throws ContentDecodingException {
+		StringBuffer buf = new StringBuffer();
+		try {
+			int event = _reader.getEventType();;
+			// Handles empty text element.
+			while (event == XmlPullParser.TEXT) {
+				buf.append(_reader.getText());
+				event = _reader.next();
+			}
+			if (event == XmlPullParser.START_TAG) {
+				throw new ContentDecodingException("readElementText expects start element to have been previously consumed, got: " + XmlPullParser.TYPES[event]);
+			} else if (event != XmlPullParser.END_TAG) {
+				throw new ContentDecodingException("Expected end of text element, got: " + XmlPullParser.TYPES[event]);
+			}
+			readEndElement();
+			return buf.toString();
+		} catch (XmlPullParserException e) {
+			throw new ContentDecodingException(e.getMessage(), e);
+		} catch (IOException e) {
+			throw new ContentDecodingException(e.getMessage(), e);
+		}
+	}
+
+	public void readEndElement() throws ContentDecodingException {
+		int event = readToNextTag(XmlPullParser.END_TAG);
+		if (event != XmlPullParser.END_TAG) {
+			throw new ContentDecodingException("Expected end element, got: " + XmlPullParser.TYPES[event]);
+		}
+		try {
+			_reader.next();
+		} catch (XmlPullParserException e) {
+			throw new ContentDecodingException(e.getMessage());
+		} catch (IOException e) {
+			throw new ContentDecodingException(e.getMessage());
+		}
+	}
+
+	/**
+	 * Read a BLOB. Consumes the end element, so force other versions
+	 * to match.
+	 */
+	public byte [] readBlob() throws ContentDecodingException {
+		try {
+			String strElementText = readUString();
+			// readEndElement(); // readElementText consumes end element
+			return TextXMLCodec.decodeBinaryElement(strElementText);
+		} catch (IOException e) {
+			throw new ContentDecodingException(e.getMessage(),e);
+		}
+	}
+	
+	public CCNTime readDateTime(String startTag) throws ContentDecodingException {
+		String strTimestamp = readUTF8Element(startTag);
+		CCNTime timestamp;
+		try {
+			timestamp = TextXMLCodec.parseDateTime(strTimestamp);
+		} catch (ParseException e) {
+			timestamp = null;
+		}
+		if (null == timestamp) {
+			throw new ContentDecodingException("Cannot parse timestamp: " + strTimestamp);
+		}		
+		return timestamp;
+	}
+
+	public CCNTime readDateTime(long startTag) throws ContentDecodingException {
+		String strTimestamp = readUTF8Element(startTag);
+		CCNTime timestamp;
+		try {
+			timestamp = TextXMLCodec.parseDateTime(strTimestamp);
+		} catch (ParseException e) {
+			timestamp = null;
+		}
+		if (null == timestamp) {
+			throw new ContentDecodingException("Cannot parse timestamp: " + strTimestamp);
+		}		
+		return timestamp;
+	}
+
+	private int readToNextTag(int type) throws ContentDecodingException {
+		int event;
+		try {
+			event = _reader.getEventType();
+			if (event == type)
+				return event;
+			if (event == XmlPullParser.TEXT || event == XmlPullParser.COMMENT)
+				event = _reader.next();
+		} catch (IOException e) {
+			throw new ContentDecodingException(e.getMessage(), e);
+		} catch (XmlPullParserException e) {
+			throw new ContentDecodingException(e.getMessage(), e);
+		}
+		return event;
+	}
+
+};
diff --git a/js/encoding/TextXMLEncoder.js b/js/encoding/TextXMLEncoder.js
new file mode 100644
index 0000000..495984b
--- /dev/null
+++ b/js/encoding/TextXMLEncoder.js
@@ -0,0 +1,109 @@
+//TODO INCOMPLETE
+/*
+ * @author: ucla-cs
+ * 
+ * Encodes CCN object into xml
+ */
+
+var Stream = require('stream').Stream;
+var TextXMLCodec = require('TextXMLCodec').TextXMLCodec;
+
+
+
+
+var TextXMLEncoder  = function TextXMLEncoder(){
+
+
+	this.ostream = new String();
+};
+
+exports.TextXMLEncoder = TextXMLEncoder;
+
+TextXMLEncoder.prototype.beginEncoding = function(/*OutputStream*/ ostream){
+		if (null == ostream)
+			throw new IllegalArgumentException("TextXMLEncoder: output stream cannot be null!");
+		
+		
+		/*Start by encoing the begining*/
+		//this.IStream = ostream;
+		this.ostream.write('<?xml version="1.0" encoding="UTF-8"?>');
+};
+
+TextXMLEncoder.prototype.endEncoding =function() {
+	this.IStream.end();
+}
+
+
+TextXMLEncoder.prorotype.writeStartElement(/*String*/ tag, /*TreeMap<String, String>*/ attributes) {
+		
+	
+		this.ostream.write('<'+tab);
+
+		if (null != attributes) {
+			
+			for(var i=0; i<attributes.length;i++){
+				this.ostream.write(' '+attributes[i].key +'='+attributes[i].value);
+			}
+		
+			// keySet of a TreeMap is ordered
+		}
+		this.ostream.write('>');
+};
+
+TextXMLEncoder.prototype.writeUString = function(/*String*/ utf8Content) {
+
+		this.ostream.write(utf8Content);
+
+};
+
+
+TextXMLEncoder.prototype.writeBlob =  function(/*byte []*/ binaryContent, /*int*/ offset, /*int*/ length) {
+
+		this.ostream.write(TextXMLCodec.encodeBinaryElement(binaryContent, offset, length));
+
+};
+
+TextXMLEncoder.prototype.writeElement = function(/*String*/ tag, /*byte[]*/ binaryContent,
+			/*TreeMap<String, String>*/ attributes)  {
+		
+		/*if (null == attributes) {
+		
+			attributes = new TreeMap<String,String>();
+		}*/
+		if (!attributes.containsKey(TextXMLCodec.BINARY_ATTRIBUTE)) {
+			attributes.put(TextXMLCodec.BINARY_ATTRIBUTE, TextXMLCodec.BINARY_ATTRIBUTE_VALUE);
+		}
+		super.writeElement(tag, binaryContent, attributes);
+}
+
+
+TextXMLEncoder.prototype.writeEndElement(tag) {
+
+		this.ostream.write('<'+tab+'>');
+
+	};
+
+	
+//returns number long
+stringToTag = function(/*String*/ tagName) {
+
+	if (null == tagName) {
+		return null;
+	}
+	Long tagVal = null;
+	if (null != _dictionaryStack) {
+		for (/*XMLDictionary*/ dictionary in _dictionaryStack) {
+			tagVal = dictionary.stringToTag(tagName);
+			if (null != tagVal) {
+				return tagVal;
+			}
+		}
+	}
+
+
+	if (XMLDictionaryStack.isUnknownTag(tagName)) {
+		return XMLDictionaryStack.decodeUnknownTag(tagName);
+	}
+	return null;
+};
+	
diff --git a/js/encoding/xml2object.js b/js/encoding/xml2object.js
new file mode 100644
index 0000000..c6711b6
--- /dev/null
+++ b/js/encoding/xml2object.js
@@ -0,0 +1,170 @@
+/**
+ * Simple xml 2 javascript object parser based on sax.js
+ * 
+ * https://github.com/emberfeather/node-xml2object
+ */
+var emitter = require('events').EventEmitter;
+var fs = require('fs');
+var sax = require('./sax');
+var util = require('util');
+
+var xml2object  = function(xmlFile, elements) {
+	elements = elements || [];
+	
+	this._hasStarted = false;
+
+	var self = this;
+	var currentObject;
+	var inObject = false;
+	var inObjectName;
+	var ancestors = [];
+
+	this.fileStream = fs.createReadStream(xmlFile);
+	this.saxStream = sax.createStream(true);
+
+	this.saxStream.on("opentag", function (args) {
+		if(!inObject) {
+			// If we are not in an object and not tracking the element
+			// then we don't need to do anything
+			if (elements.indexOf(args.name) < 0) {
+				return;
+			}
+
+			// Start tracking a new object
+			inObject = true;
+			inObjectName = args.name;
+
+			currentObject = {};
+		}
+
+		if (!(args.name in currentObject)) {
+			currentObject[args.name] = args.attributes;
+		} else if (!util.isArray(currentObject[args.name])) {
+			// Put the existing object in an array.
+			var newArray = [currentObject[args.name]];
+			
+			// Add the new object to the array.
+			newArray.push(args.attributes);
+			
+			// Point to the new array.
+			currentObject[args.name] = newArray;
+		} else {
+			// An array already exists, push the attributes on to it.
+			currentObject[args.name].push(args.attributes);
+		}
+
+		// Store the current (old) parent.
+		ancestors.push(currentObject);
+
+		// We are now working with this object, so it becomes the current parent.
+		if (currentObject[args.name] instanceof Array) {
+			// If it is an array, get the last element of the array.
+			currentObject = currentObject[args.name][currentObject[args.name].length - 1];
+		} else {
+			// Otherwise, use the object itself.
+			currentObject = currentObject[args.name];
+		}
+	});
+
+	this.saxStream.on("text", function (data) {
+		if(!inObject) {
+			return;
+		}
+
+		data = data.trim();
+
+		if (!data.length) {
+			return;
+		}
+
+		currentObject['$t'] = (currentObject['$t'] || "") + data;
+	});
+
+	this.saxStream.on("closetag", function (name) {
+		if(!inObject) {
+			return;
+		}
+
+		if(inObject && inObjectName === name) {
+			// Finished building the object
+			self.emit('object', name, currentObject);
+
+			inObject = false;
+			ancestors = [];
+
+			return;
+		}
+
+		if(ancestors.length) {
+			var ancestor = ancestors.pop();
+			var keys = Object.keys(currentObject);
+
+			if (keys.length == 1 && '$t' in currentObject) {
+				// Convert the text only objects into just the text
+				if (ancestor[name] instanceof Array) {
+					ancestor[name].push(ancestor[name].pop()['$t']);
+				} else {
+					ancestor[name] = currentObject['$t'];
+				}
+			} else if (!keys.length) {
+				// Remove empty keys
+				delete ancestor[name];
+			}
+
+			currentObject = ancestor;
+		} else {
+			currentObject = {};
+		}
+	});
+
+	// Rebroadcast the error and keep going
+	this.saxStream.on("error", function (e) {
+		this.emit('error', e);
+
+		// clear the error and resume
+		this._parser.error = null;
+		this._parser.resume();
+	});
+
+	// Rebroadcast the end of the file read
+	this.fileStream.on("end", function() {
+		self.emit("end");
+	});
+};
+
+util.inherits(xml2object, emitter);
+
+xml2object.prototype.start = function() {
+	// Can only start once
+	if(this._hasStarted) {
+		return;
+	}
+
+	this._hasStarted = true;
+
+	this.emit('start');
+
+	// Start the streaming!
+	this.fileStream.pipe(this.saxStream);
+};
+
+
+//TEST///////////////////////////////////////////////////////////////////////////////
+//var xml2object = require('xml2object');
+
+// Create a new xml parser with an array of xml elements to look for
+/*var parser = new xml2object('./src/encoding/ContentObject1.xml', [ 'ContentObject' ]);
+
+// Bind to the object event to work with the objects found in the XML file
+parser.on('object', function(name, obj) {
+    console.log('Found an object: %s', name);
+    console.log(obj);
+});
+
+// Bind to the file end event to tell when the file is done being streamed
+parser.on('end', function(name, obj) {
+    console.log('Finished parsing xml!');
+});
+
+// Start parsing the XML
+parser.start();*/
\ No newline at end of file
diff --git a/js/index.html b/js/index.html
new file mode 100644
index 0000000..04e402e
--- /dev/null
+++ b/js/index.html
@@ -0,0 +1,130 @@
+<?xml version = "1.0" encoding="utf-8" ?>

+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"

+"DTD/xhtml1-strict.dtd">

+<html xmlns = "http://www.w3.org/1999/xhtml">

+

+<head>

+	<title>NDN Request Example</title>

+	<script type="text/javascript" src="java_socket_bridge.js"></script>

+	

+	<script type="text/javascript" src="CCNProtocolDTags.js"></script>

+	

+	<script type="text/javascript" src="CCNTime.js"></script>

+	

+	<script type="text/javascript" src="ContentName.js"></script>

+	

+	<script type="text/javascript" src="ContentObject.js"></script>

+	

+	<script type="text/javascript" src="DateFormat.js"></script>

+	

+	<script type="text/javascript" src="Exclude.js"></script>

+

+	<script type="text/javascript" src="ExcludeAny.js"></script>

+

+	<script type="text/javascript" src="ExcludeComponent.js"></script>

+

+	<script type="text/javascript" src="Interest.js"></script>

+	

+	<script type="text/javascript" src="KeyLocator.js"></script>

+	

+	<script type="text/javascript" src="KeyName.js"></script>

+

+	<script type="text/javascript" src="PublisherID.js"></script>

+	

+	<script type="text/javascript" src="Signature.js"></script>

+	

+	<script type="text/javascript" src="SignedInfo.js"></script>

+	

+	<script type="text/javascript" src="PublisherPublicKeyDigest.js"></script>

+	

+

+	<script type="text/javascript" src="encoding/BinaryXMLEncoder.js"></script>

+	

+	<script type="text/javascript" src="encoding/BinaryXMLCodec.js"></script>

+	

+	<script type="text/javascript" src="encoding/BinaryXMLDecoder.js"></script>

+	

+	<script type="text/javascript" src="encoding/DataUtils.js"></script>

+	

+	<script type="text/javascript">

+		function run(){

+

+			var ContentName = document.getElementById('contentname').value;

+		

+			///////////////////////////////////////

+		    //createRoute('localhost', 9695);

+

+		    createRoute('131.179.141.15', 9695);

+		    //createRoute('borges.metwi.ucla.edu', 9695);

+		    

+			//content object

+			var co = queryPrefix( ContentName );

+			

+			///////////////////////////////////////

+			

+			var output ="";

+			

+			if(co==-1)

+				output+= "NO CONTENT FOUND"

+			else if (co==-2)

+				output+= "CONTENT NAME IS EMPTY"

+			else{

+				if(co.Name!=null && co.Name.Components!=null){

+					output+= "NAME: ";

+					

+					for(var i=0;i<co.Name.Components.length;i++){

+						output+= "/"+ toString(co.Name.Components[i]);

+					}

+					output+= "<br />";

+					output+= "<br />";

+				}

+	

+				if(co.Content !=null){

+					output += "CONTENT(ASCII): "+ toString(co.Content);

+					

+					output+= "<br />";

+					output+= "<br />";

+				}

+				if(co.Content !=null){

+					output += "CONTENT(hex): "+ toHex(co.Content);

+					

+					output+= "<br />";

+					output+= "<br />";

+				}

+				if(co.Signature !=null && co.Signature.Signature!=null){

+					

+					output += "SIGNATURE(hex): "+ toHex(co.Signature.Signature);

+					

+					output+= "<br />";

+					output+= "<br />";

+				}

+				if(co.SignedInfo!=null && co.SignedInfo.Locator!=null && co.SignedInfo.Locator.Key!=null){

+					

+					output += "PUBLISHER KEY: "+ toHex(co.SignedInfo.Locator.Key);

+					

+					output+= "<br />";

+					output+= "<br />";

+	

+				}

+			}

+			

+			document.getElementById('result').innerHTML = output;

+		}

+	

+		</script>

+	

+</head>

+<body >

+	<form>

+		Please Enter a Content Name:<br /><input id="contentname" type="text" name="CONTENTNAME" value="/PARC/abc" /> <br />

+	</form>

+	<button onclick="run()">Run!</button>

+	<div >

+		<applet id="JavaSocketBridge" archive="JavaSocketBridge.jar" code="JavaSocketBridge.class" width="0" height="0">

+		</applet>

+	</div>

+

+		<p id="result"></p>

+

+</body>

+</html>
\ No newline at end of file
diff --git a/js/java_socket_bridge.js b/js/java_socket_bridge.js
new file mode 100644
index 0000000..bf4c3ac
--- /dev/null
+++ b/js/java_socket_bridge.js
@@ -0,0 +1,151 @@
+/*

+ * @author: ucla-cs

+ * This class represents Interest Objects

+ */

+

+// Global variables

+var java_socket_bridge_ready_flag = false;

+

+var ndnport =null;

+var ndnurl=null;

+

+// Applet reports it is ready to use

+function java_socket_bridge_ready(){

+	java_socket_bridge_ready_flag = true;

+}

+

+//Sets the route to ccnx router

+function createRoute(url, port){

+	ndnport = port;

+	ndnurl=url;

+}

+

+// Connect to a given url and port

+//Error -1 No countent found

+//Error -2 Empty query

+function queryPrefix(message){

+	if(ndnport!=null && ndnurl!=null){

+		var newMessage ='';

+		

+		String.prototype.trim = function() {

+			return this.replace(/^\s+|\s+$/g, "");

+		};

+

+		message = message.trim();

+		

+

+		

+		if(message==null || message =="" || message=="/"){

+			return -2;

+		}

+		

+		//message = decodeURIComponent(message);

+		message = unescape(message);

+		

+		var array = message.split('/');

+

+		

+		if(message[0]=="/")

+			array=array.slice(1,array.length);

+			

+		if(message[message.length-1]=="/")

+			array=array.slice(0,array.length-1);

+		

+		

+		//console.log('ARRAY IS '+ array);

+		

+		enc = new BinaryXMLEncoder();

+ 

+		int = new Interest(new ContentName(array));

+

+		int.encode(enc);

+		

+		var hex = toHex(enc.getReducedOstream());

+		

+		

+		

+		//console.log('Connecting and start '+ ndnurl +':'+ndnport+'-'+message);

+		

+		

+		

+		var result = get_java_socket_bridge().connectAndStart(ndnurl,ndnport,hex);

+		

+		console.log('BINARY RESPONSE IS ' +result);

+		

+		

+		//result[0] and result[1] should be 0 and 4 if there is a content object found

+		if(result==null || result==undefined || result =="" || result[0] != '0'||result[1]!='4'){

+			return -1;

+		}

+		

+		else{

+			

+			var numbers = toNumbers(result);

+			

+			console.log('HEX RESPONSE IS \n'+numbers);

+			decoder = new BinaryXMLDecoder(numbers);

+			

+			

+			co = new ContentObject();

+        

+			co.decode(decoder);

+

+			//console.log(co);

+			

+			return co;

+			

+

+		}

+		

+		

+		

+	}

+	

+	else{

+

+		alert('ERROR URL OR PORT NOT SET');

+

+		return -3;

+

+	}	

+

+}

+

+//http://ejohn.org/blog/numbers-hex-and-colors/

+function toHex(arguments){

+  //console.log(arguments);

+  var ret = "";

+  for ( var i = 0; i < arguments.length; i++ )

+    ret += (arguments[i] < 16 ? "0" : "") + arguments[i].toString(16);

+  return ret.toUpperCase();

+}

+

+function toString(arguments){

+  //console.log(arguments);

+  var ret = "";

+  for ( var i = 0; i < arguments.length; i++ )

+    ret += String.fromCharCode(arguments[i]);

+  return ret;

+}

+

+function toNumbers( str ){

+  var ret = [];

+   str.replace(/(..)/g, function(str){

+    ret.push( parseInt( str, 16 ) );

+  });

+  return ret;

+}

+

+

+// Get something from the socket

+function on_socket_get(message){}

+

+// Report an error

+function on_socket_error(message){

+	alert('NO CONTENT FOUND\nERROR MESSAGE:' +message);

+}

+

+// Get the applet object

+function get_java_socket_bridge(){

+	return document.getElementById('JavaSocketBridge');

+}
\ No newline at end of file