Add interest timeout
diff --git a/js/tools/build/ndn-js-uncomp.js b/js/tools/build/ndn-js-uncomp.js
index d8ebcfa..fa00a92 100644
--- a/js/tools/build/ndn-js-uncomp.js
+++ b/js/tools/build/ndn-js-uncomp.js
@@ -1,4 +1,4 @@
-/* 
+/**
  * @author: Jeff Thompson
  * See COPYING for copyright and distribution information.
  * Provide the callback closure for the async communication methods in the NDN class.
@@ -18,6 +18,8 @@
 	// Use instance variables to return data to callback
 	this.ndn_data = null;  // this holds the ndn_closure
     this.ndn_data_dirty = false;
+    
+    this.timerID = -1;  // Store the interest timer; used to cancel the timer upon receiving interest
 };
 
 // Upcall result
@@ -62,13 +64,13 @@
 	ret += "\nContentObject: " + this.contentObject;
 	return ret;
 }
-/*
+/**
  * @author: Meki Cherkaoui, Jeff Thompson, Wentao Shang
  * See COPYING for copyright and distribution information.
  * This class represents the top-level object for communicating with an NDN host.
  */
 
-var LOG = 3;
+var LOG = 0;
 
 /**
  * settings is an associative array with the following defaults:
@@ -76,8 +78,8 @@
  *   host: 'localhost',
  *   port: 9696,
  *   getTransport: function() { return new WebSocketTransport(); }
- *   onopen: function() { console.log("NDN connection established."); }
- *   onclose: function() { console.log("NDN connection closed."); }
+ *   onopen: function() { if (LOG > 3) console.log("NDN connection established."); }
+ *   onclose: function() { if (LOG > 3) console.log("NDN connection closed."); }
  * }
  */
 var NDN = function NDN(settings) {
@@ -88,14 +90,16 @@
     this.transport = getTransport();
     this.readyStatus = NDN.UNOPEN;
     // Event handler
-    this.onopen = (settings.onopen || function() { console.log("NDN connection established."); });
-    this.onclose = (settings.onclose || function() { console.log("NDN connection closed."); });
+    this.onopen = (settings.onopen || function() { if (LOG > 3) console.log("NDN connection established."); });
+    this.onclose = (settings.onclose || function() { if (LOG > 3) console.log("NDN connection closed."); });
 };
 
 NDN.UNOPEN = 0;  // created but not opened yet
 NDN.OPENED = 1;  // connection to ccnd opened
 NDN.CLOSED = 2;  // connection to ccnd closed
 
+NDN.InterestTimeOut = 5000; // 5000 ms timeout for pending interest
+
 /* Java Socket Bridge and XPCOM transport */
 
 NDN.prototype.createRoute = function(host,port){
@@ -141,7 +145,7 @@
 NDN.prototype.registerPrefix = function(name, closure, flag) {
     return this.transport.registerPrefix(this, name, closure, flag);
 }
-/* 
+/** 
  * @author: Wentao Shang
  * See COPYING for copyright and distribution information.
  * Implement getAsync and putAsync used by NDN using nsISocketTransportService.
@@ -156,27 +160,6 @@
 	this.structureDecoder = new BinaryXMLStructureDecoder();
 };
 
-WebSocketTransport.prototype.expressInterest = function(ndn, interest, closure) {
-	if (this.ws != null) {
-		//TODO: check local content store first
-
-        var binaryInterest = encodeToBinaryInterest(interest);
-		var bytearray = new Uint8Array(binaryInterest.length);
-		bytearray.set(binaryInterest);
-		
-		var pitEntry = new PITEntry(interest.name.getName(), closure);
-		PITTable.push(pitEntry);
-		
-		this.ws.send(bytearray.buffer);
-		console.log('ws.send() returned.');
-	}
-	else{
-		console.log('WebSocket connection is not established.');
-		return null;
-	}
-};
-
-
 var ccndIdFetcher = '/%C1.M.S.localhost/%C1.M.SRV/ccnd/KEY';
 
 WebSocketTransport.prototype.connectWebSocket = function(ndn) {
@@ -184,7 +167,7 @@
 		delete this.ws;
 	
 	this.ws = new WebSocket('ws://' + ndn.host + ':' + ndn.port);
-	console.log('ws connection created.');
+	if (LOG > 0) console.log('ws connection created.');
 	
 	this.ws.binaryType = "arraybuffer";
 	
@@ -198,7 +181,7 @@
 		} else if (result instanceof ArrayBuffer) {
 	        var bytearray = new Uint8Array(result);
 	        
-			if (LOG>3) console.log('BINARY RESPONSE IS ' + bytearray);
+			if (LOG>3) console.log('BINARY RESPONSE IS ' + DataUtils.toHex(bytearray));
 			
 			try {
 				if (bytearray.length + self.buffer.byteOffset >= self.buffer.byteLength) {
@@ -231,13 +214,13 @@
 			var decoder = new BinaryXMLDecoder(self.buffer);
 			// Dispatch according to packet type
 			if (decoder.peekStartElement(CCNProtocolDTags.Interest)) {  // Interest packet
-				console.log('Interest packet received.');
+				if (LOG > 3) console.log('Interest packet received.');
 				
 				var interest = new Interest();
 				interest.from_ccnb(decoder);
 				if (LOG>3) console.log(interest);
 				var nameStr = escape(interest.name.getName());
-				console.log(nameStr);
+				if (LOG > 3) console.log(nameStr);
 				
 				var entry = getEntryForRegisteredPrefix(nameStr);
 				if (entry != null) {
@@ -246,38 +229,44 @@
 				}
 				
 			} else if (decoder.peekStartElement(CCNProtocolDTags.ContentObject)) {  // Content packet
-				console.log('ContentObject packet received.');
+				if (LOG > 3) console.log('ContentObject packet received.');
 				
 				var co = new ContentObject();
 				co.from_ccnb(decoder);
-				if (LOG>3) console.log(co);
+				if (LOG > 3) console.log(co);
 				nameStr = co.name.getName();
-				console.log(nameStr);
+				if (LOG > 3) console.log(nameStr);
 				
 				if (self.ccndid == null && nameStr.match(ccndIdFetcher) != null) {
 					// We are in starting phase, record publisherPublicKeyDigest in self.ccndid
 					if(!co.signedInfo || !co.signedInfo.publisher 
 						|| !co.signedInfo.publisher.publisherPublicKeyDigest) {
-						console.log("Cannot contact router");
+						console.log("Cannot contact router, close NDN now.");
 						
 						// Close NDN if we fail to connect to a ccn router
 						ndn.readyStatus = NDN.CLOSED;
 						ndn.onclose();
-						console.log("NDN.onclose event fired.");
+						//console.log("NDN.onclose event fired.");
 					} else {
-						console.log('Connected to ccnd.');
+						//console.log('Connected to ccnd.');
 						self.ccndid = co.signedInfo.publisher.publisherPublicKeyDigest;
 						if (LOG>3) console.log(self.ccndid);
 						
 						// Call NDN.onopen after success
 						ndn.readyStatus = NDN.OPENED;
 						ndn.onopen();
-						console.log("NDN.onopen event fired.");
+						//console.log("NDN.onopen event fired.");
 					}
 				} else {
 					var pitEntry = getEntryForExpressedInterest(nameStr);
 					if (pitEntry != null) {
 						//console.log(pitEntry);
+						
+						// Cancel interest timer
+						clearTimeout(pitEntry.closure.timerID);
+						//console.log("Clear interest timer");
+						//console.log(pitEntry.closure.timerID);
+						// Raise callback
 						pitEntry.closure.upcall(Closure.UPCALL_CONTENT, new UpcallInfo(ndn, null, 0, co));
 					}
 				}
@@ -296,12 +285,12 @@
 	}
 	
 	this.ws.onopen = function(ev) {
-		console.log(ev);
-		console.log('ws.onopen: WebSocket connection opened.');
-		console.log('ws.onopen: ReadyState: ' + this.readyState);
+		if (LOG > 3) console.log(ev);
+		if (LOG > 3) console.log('ws.onopen: WebSocket connection opened.');
+		if (LOG > 3) console.log('ws.onopen: ReadyState: ' + this.readyState);
 
 		// Fetch ccndid now
-		interest = new Interest(new Name(ccndIdFetcher));
+		var interest = new Interest(new Name(ccndIdFetcher));
 		interest.InterestLifetime = 4200;
 		//var hex = encodeToHexInterest(interest);
 		var hex = encodeToBinaryInterest(interest);
@@ -329,7 +318,7 @@
 		// Close NDN when WebSocket is closed
 		ndn.readyStatus = NDN.CLOSED;
 		ndn.onclose();
-		console.log("NDN.onclose event fired.");
+		//console.log("NDN.onclose event fired.");
 	}
 }
 
@@ -351,6 +340,38 @@
 	return null;
 }
 
+WebSocketTransport.prototype.expressInterest = function(ndn, interest, closure) {
+	if (this.ws != null) {
+		//TODO: check local content store first
+
+        var binaryInterest = encodeToBinaryInterest(interest);
+		var bytearray = new Uint8Array(binaryInterest.length);
+		bytearray.set(binaryInterest);
+		
+		var pitEntry = new PITEntry(interest.name.getName(), closure);
+		PITTable.push(pitEntry);
+		
+		this.ws.send(bytearray.buffer);
+		if (LOG > 3) console.log('ws.send() returned.');
+		
+		// Set interest timer
+		closure.timerID = setTimeout(function() {
+			console.log("Interest time out.");
+			
+			// Remove PIT entry from PITTable
+			index = PITTable.indexOf(pitEntry);
+			//console.log(PITTable);
+			PITTable.splice(index, 1);
+			//console.log(PITTable);
+			// Raise closure callback
+			closure.upcall(Closure.UPCALL_INTEREST_TIMED_OUT, new UpcallInfo(ndn, interest, 0, null));
+		}, NDN.InterestTimeOut);
+		//console.log(closure.timerID);
+	}
+	else
+		console.log('WebSocket connection is not established.');
+};
+
 
 // For publishing data
 var CSTable = new Array();
@@ -372,7 +393,7 @@
 	if (this.ws != null) {
 		if (this.ccndid == null) {
 			console.log('ccnd node ID unkonwn. Cannot register prefix.');
-			return;
+			return -1;
 		}
 		
 		var fe = new ForwardingEntry('selfreg', name, null, null, 3, 2147483647);
@@ -402,7 +423,7 @@
 		//    ---Wentao
     	var bytearray = new Uint8Array(binaryInterest.length);
 		bytearray.set(binaryInterest);
-		console.log('Send Interest registration packet.');
+		if (LOG > 3) console.log('Send Interest registration packet.');
     	
     	var csEntry = new CSEntry(name.getName(), closure);
 		CSTable.push(csEntry);
@@ -876,6 +897,32 @@
     return -1;
 }
 
+/*
+ * Find the last component in name that has a ContentDigest and return the digest value as Uint8Array, 
+ *   or null if not found.
+ * A ContentDigest component is Name.ContentDigestPrefix + 32 bytes + Name.ContentDigestSuffix.
+ */
+Name.prototype.getContentDigestValue = function() {
+    var digestComponentLength = Name.ContentDigestPrefix.length + 32 + Name.ContentDigestSuffix.length; 
+    for (var i = this.components.length - 1; i >= 0; --i) {
+        // Check for the correct length and equal ContentDigestPrefix and ContentDigestSuffix.
+        if (this.components[i].length == digestComponentLength &&
+            DataUtils.arraysEqual(this.components[i].subarray(0, Name.ContentDigestPrefix.length), 
+                                  Name.ContentDigestPrefix) &&
+            DataUtils.arraysEqual(this.components[i].subarray
+               (this.components[i].length - Name.ContentDigestSuffix.length, this.components[i].length),
+                                  Name.ContentDigestSuffix))
+           return this.components[i].subarray
+               (Name.ContentDigestPrefix.length, Name.ContentDigestPrefix.length + 32);
+    }
+    
+    return null;
+}
+
+// Meta GUID "%C1.M.G%C1" + ContentDigest with a 32 byte BLOB. 
+Name.ContentDigestPrefix = new Uint8Array([0xc1, 0x2e, 0x4d, 0x2e, 0x47, 0xc1, 0x01, 0xaa, 0x02, 0x85]);
+Name.ContentDigestSuffix = new Uint8Array([0x00]);
+
 /**
  * Return component as an escaped string according to "CCNx URI Scheme".
  * We can't use encodeURIComponent because that doesn't encode all the characters we want to.
@@ -1108,26 +1155,6 @@
 	this.digestAlgorithm = _digestAlgorithm//String _digestAlgorithm;
 };
 
-var generateSignature = function(contentName,content,signedinfo){
-	
-	var enc = new BinaryXMLEncoder();
-	contentName.to_ccnb(enc);
-	var hex1 = toHex(enc.getReducedOstream());
-
-	var enc = new BinaryXMLEncoder();
-	content.to_ccnb(enc);
-	var hex2 = toHex(enc.getReducedOstream());
-
-	var enc = new BinaryXMLEncoder();
-	signedinfo.to_ccnb(enc);
-	var hex3 = toHex(enc.getReducedOstream());
-
-	var hex = hex1+hex2+hex3;
-
-	//globalKeyManager.sig
-
-};
-
 Signature.prototype.from_ccnb =function( decoder) {
 		decoder.readStartElement(this.getElementLabel());
 		
@@ -4761,8 +4788,10 @@
 {

   //console.log('Raw string comming is '+input);

   var output = Array(input.length >> 2);

+  /* JavaScript automatically zeroizes a new array.

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

     output[i] = 0;

+   */

   for(var i = 0; i < input.length * 8; i += 8)

     output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32);

   return output;

@@ -4777,8 +4806,10 @@
 function byteArray2binb(input){

 	//console.log("Byte array coming is " + input);

 	var output = Array(input.length >> 2);

+      /* JavaScript automatically zeroizes a new array.

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

 	    output[i] = 0;

+       */

 	  for(var i = 0; i < input.length * 8; i += 8)

 	    output[i>>5] |= (input[i / 8] & 0xFF) << (24 - i % 32);

 	  return output;

@@ -4831,15 +4862,25 @@
   var HASH = new Array(1779033703, -1150833019, 1013904242, -1521486534,

                        1359893119, -1694144372, 528734635, 1541459225);

   var W = new Array(64);

-  var a, b, c, d, e, f, g, h;

-  var i, j, T1, T2;

 

   /* append padding */

   m[l >> 5] |= 0x80 << (24 - l % 32);

   m[((l + 64 >> 9) << 4) + 15] = l;

+ 

+  for(var offset = 0; offset < m.length; offset += 16)

+    processBlock_sha256(m, offset, HASH, W);

 

-  for(i = 0; i < m.length; i += 16)

-  {

+  return HASH;

+}

+

+/*

+ * Process a block of 16 4-byte words in m starting at offset and update HASH.  

+ * offset must be a multiple of 16 and less than m.length.  W is a scratchpad Array(64).

+ */

+function processBlock_sha256(m, offset, HASH, W) {

+    var a, b, c, d, e, f, g, h;

+    var j, T1, T2;

+    

     a = HASH[0];

     b = HASH[1];

     c = HASH[2];

@@ -4851,7 +4892,7 @@
 

     for(j = 0; j < 64; j++)

     {

-      if (j < 16) W[j] = m[j + i];

+      if (j < 16) W[j] = m[j + offset];

       else W[j] = safe_add(safe_add(safe_add(sha256_Gamma1256(W[j - 2]), W[j - 7]),

                                             sha256_Gamma0256(W[j - 15])), W[j - 16]);

 

@@ -4876,8 +4917,6 @@
     HASH[5] = safe_add(f, HASH[5]);

     HASH[6] = safe_add(g, HASH[6]);

     HASH[7] = safe_add(h, HASH[7]);

-  }

-  return HASH;

 }

 

 function safe_add (x, y)

@@ -4886,6 +4925,90 @@
   var msw = (x >> 16) + (y >> 16) + (lsw >> 16);

   return (msw << 16) | (lsw & 0xFFFF);

 }

+

+/*

+ * Create a Sha256, call update(data) multiple times, then call finalize().

+ */

+var Sha256 = function Sha256() {

+    this.W = new Array(64);

+    this.hash = new Array(1779033703, -1150833019, 1013904242, -1521486534,

+                          1359893119, -1694144372, 528734635, 1541459225);

+    this.nTotalBytes = 0;

+    this.buffer = new Uint8Array(16 * 4);

+    this.nBufferBytes = 0;

+}

+

+/*

+ * Update the hash with data, which is Uint8Array.

+ */

+Sha256.prototype.update = function(data) {

+    this.nTotalBytes += data.length;

+    

+    if (this.nBufferBytes > 0) {

+        // Fill up the buffer and process it first.

+        var bytesNeeded = this.buffer.length - this.nBufferBytes;

+        if (data.length < bytesNeeded) {

+            this.buffer.set(data, this.nBufferBytes);

+            this.nBufferBytes += data.length;

+            return;

+        }

+        else {

+            this.buffer.set(data.subarray(0, bytesNeeded), this.nBufferBytes);

+            processBlock_sha256(byteArray2binb(this.buffer), 0, this.hash, this.W);

+            this.nBufferBytes = 0;

+            // Consume the bytes from data.

+            data = data.subarray(bytesNeeded, data.length);

+            if (data.length == 0)

+                return;

+        }

+    }

+    

+    // 2^6 is 16 * 4.

+    var nBlocks = data.length >> 6;

+    if (nBlocks > 0) {

+        var nBytes = nBlocks * 16 * 4;

+        var m = byteArray2binb(data.subarray(0, nBytes));

+        for(var offset = 0; offset < m.length; offset += 16)

+            processBlock_sha256(m, offset, this.hash, this.W);

+

+        data = data.subarray(nBytes, data.length);

+    }

+    

+    if (data.length > 0) {

+        // Save the remainder in the buffer.

+        this.buffer.set(data);

+        this.nBufferBytes = data.length;

+    }

+}

+

+/*

+ * Finalize the hash and return the result as Uint8Array.

+ * Only call this once.  Return values on subsequent calls are undefined.

+ */

+Sha256.prototype.finalize = function() {

+    var m = byteArray2binb(this.buffer.subarray(0, this.nBufferBytes));

+    /* append padding */

+    var l = this.nBufferBytes * 8;

+    m[l >> 5] |= 0x80 << (24 - l % 32);

+    m[((l + 64 >> 9) << 4) + 15] = this.nTotalBytes * 8;

+

+    for(var offset = 0; offset < m.length; offset += 16)

+        processBlock_sha256(m, offset, this.hash, this.W);

+

+    return Sha256.binb2Uint8Array(this.hash);

+}

+

+/*

+ * Convert an array of big-endian words to Uint8Array.

+ */

+Sha256.binb2Uint8Array = function(input)

+{

+    var output = new Uint8Array(input.length * 4);

+    var iOutput = 0;

+    for (var i = 0; i < input.length * 32; i += 8)

+        output[iOutput++] = (input[i>>5] >>> (24 - i % 32)) & 0xFF;

+    return output;

+}

 var b64map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

 var b64pad="=";

 

diff --git a/js/tools/build/ndn-js.js b/js/tools/build/ndn-js.js
index 5e2599b..77ae081 100644
--- a/js/tools/build/ndn-js.js
+++ b/js/tools/build/ndn-js.js
@@ -1,18 +1,19 @@
-var Closure=function(){this.ndn_data=null;this.ndn_data_dirty=!1};Closure.RESULT_ERR=-1;Closure.RESULT_OK=0;Closure.RESULT_REEXPRESS=1;Closure.RESULT_INTEREST_CONSUMED=2;Closure.RESULT_VERIFY=3;Closure.RESULT_FETCHKEY=4;Closure.UPCALL_FINAL=0;Closure.UPCALL_INTEREST=1;Closure.UPCALL_CONSUMED_INTEREST=2;Closure.UPCALL_CONTENT=3;Closure.UPCALL_INTEREST_TIMED_OUT=4;Closure.UPCALL_CONTENT_UNVERIFIED=5;Closure.UPCALL_CONTENT_BAD=6;Closure.prototype.upcall=function(){return Closure.RESULT_OK};
+var Closure=function(){this.ndn_data=null;this.ndn_data_dirty=!1;this.timerID=-1};Closure.RESULT_ERR=-1;Closure.RESULT_OK=0;Closure.RESULT_REEXPRESS=1;Closure.RESULT_INTEREST_CONSUMED=2;Closure.RESULT_VERIFY=3;Closure.RESULT_FETCHKEY=4;Closure.UPCALL_FINAL=0;Closure.UPCALL_INTEREST=1;Closure.UPCALL_CONSUMED_INTEREST=2;Closure.UPCALL_CONTENT=3;Closure.UPCALL_INTEREST_TIMED_OUT=4;Closure.UPCALL_CONTENT_UNVERIFIED=5;Closure.UPCALL_CONTENT_BAD=6;Closure.prototype.upcall=function(){return Closure.RESULT_OK};
 var UpcallInfo=function(a,b,c,d){this.ndn=a;this.interest=b;this.matchedComps=c;this.contentObject=d};UpcallInfo.prototype.toString=function(){var a="ndn = "+this.ndn,a=a+("\nInterest = "+this.interest),a=a+("\nmatchedComps = "+this.matchedComps);return a+="\nContentObject: "+this.contentObject};
-var LOG=3,NDN=function NDN(b){b=b||{};this.host=b.host||"localhost";this.port=b.port||9696;this.transport=(b.getTransport||function(){return new WebSocketTransport})();this.readyStatus=NDN.UNOPEN;this.onopen=b.onopen||function(){console.log("NDN connection established.")};this.onclose=b.onclose||function(){console.log("NDN connection closed.")}};NDN.UNOPEN=0;NDN.OPENED=1;NDN.CLOSED=2;NDN.prototype.createRoute=function(a,b){this.host=a;this.port=b};
+var LOG=0,NDN=function NDN(b){b=b||{};this.host=b.host||"localhost";this.port=b.port||9696;this.transport=(b.getTransport||function(){return new WebSocketTransport})();this.readyStatus=NDN.UNOPEN;this.onopen=b.onopen||function(){3<LOG&&console.log("NDN connection established.")};this.onclose=b.onclose||function(){3<LOG&&console.log("NDN connection closed.")}};NDN.UNOPEN=0;NDN.OPENED=1;NDN.CLOSED=2;NDN.InterestTimeOut=5E3;NDN.prototype.createRoute=function(a,b){this.host=a;this.port=b};
 NDN.prototype.expressInterest=function(a,b,c){null==this.host||null==this.port?dump("ERROR host OR port NOT SET\n"):(a=new Interest(a),null!=c?(a.minSuffixComponents=c.minSuffixComponents,a.maxSuffixComponents=c.maxSuffixComponents,a.publisherPublicKeyDigest=c.publisherPublicKeyDigest,a.exclude=c.exclude,a.childSelector=c.childSelector,a.answerOriginKind=c.answerOriginKind,a.scope=c.scope,a.interestLifetime=c.interestLifetime):a.interestLifetime=4200,this.transport.expressInterest(this,a,b))};
-NDN.prototype.registerPrefix=function(a,b,c){return this.transport.registerPrefix(this,a,b,c)};var WebSocketTransport=function(){this.ccndid=this.ws=null;this.maxBufferSize=1E4;this.buffer=new Uint8Array(this.maxBufferSize);this.structureDecoder=new BinaryXMLStructureDecoder};
-WebSocketTransport.prototype.expressInterest=function(a,b,c){if(null!=this.ws){var d=encodeToBinaryInterest(b),a=new Uint8Array(d.length);a.set(d);b=new PITEntry(b.name.getName(),c);PITTable.push(b);this.ws.send(a.buffer);console.log("ws.send() returned.")}else return console.log("WebSocket connection is not established."),null};var ccndIdFetcher="/%C1.M.S.localhost/%C1.M.SRV/ccnd/KEY";
-WebSocketTransport.prototype.connectWebSocket=function(a){null!=this.ws&&delete this.ws;this.ws=new WebSocket("ws://"+a.host+":"+a.port);console.log("ws connection created.");this.ws.binaryType="arraybuffer";var b=this;this.ws.onmessage=function(c){c=c.data;if(null==c||void 0==c||""==c)console.log("INVALID ANSWER");else if(c instanceof ArrayBuffer){c=new Uint8Array(c);3<LOG&&console.log("BINARY RESPONSE IS "+c);try{if(c.length+b.buffer.byteOffset>=b.buffer.byteLength){console.log("NDN.ws.onmessage: buffer overflow. Accumulate received length: "+
+NDN.prototype.registerPrefix=function(a,b,c){return this.transport.registerPrefix(this,a,b,c)};var WebSocketTransport=function(){this.ccndid=this.ws=null;this.maxBufferSize=1E4;this.buffer=new Uint8Array(this.maxBufferSize);this.structureDecoder=new BinaryXMLStructureDecoder},ccndIdFetcher="/%C1.M.S.localhost/%C1.M.SRV/ccnd/KEY";
+WebSocketTransport.prototype.connectWebSocket=function(a){null!=this.ws&&delete this.ws;this.ws=new WebSocket("ws://"+a.host+":"+a.port);0<LOG&&console.log("ws connection created.");this.ws.binaryType="arraybuffer";var b=this;this.ws.onmessage=function(c){c=c.data;if(null==c||void 0==c||""==c)console.log("INVALID ANSWER");else if(c instanceof ArrayBuffer){c=new Uint8Array(c);3<LOG&&console.log("BINARY RESPONSE IS "+DataUtils.toHex(c));try{if(c.length+b.buffer.byteOffset>=b.buffer.byteLength){console.log("NDN.ws.onmessage: buffer overflow. Accumulate received length: "+
 b.buffer.byteOffset+". Current packet length: "+c.length+".");delete b.structureDecoder;delete b.buffer;b.structureDecoder=new BinaryXMLStructureDecoder;b.buffer=new Uint8Array(b.maxBufferSize);return}b.buffer.set(c,b.buffer.byteOffset);if(!b.structureDecoder.findElementEnd(b.buffer)){console.log("Incomplete packet received. Length "+c.length+". Wait for more input.");console.log("self.buffer length: "+b.buffer.length);return}}catch(d){console.log("NDN.ws.onmessage exception: "+d);return}c=new BinaryXMLDecoder(b.buffer);
-if(c.peekStartElement(CCNProtocolDTags.Interest)){console.log("Interest packet received.");var e=new Interest;e.from_ccnb(c);3<LOG&&console.log(e);var f=escape(e.name.getName());console.log(f);f=getEntryForRegisteredPrefix(f);null!=f&&f.closure.upcall(Closure.UPCALL_INTEREST,new UpcallInfo(a,e,0,null))}else c.peekStartElement(CCNProtocolDTags.ContentObject)?(console.log("ContentObject packet received."),e=new ContentObject,e.from_ccnb(c),3<LOG&&console.log(e),f=e.name.getName(),console.log(f),null==
-b.ccndid&&null!=f.match(ccndIdFetcher)?!e.signedInfo||!e.signedInfo.publisher||!e.signedInfo.publisher.publisherPublicKeyDigest?(console.log("Cannot contact router"),a.readyStatus=NDN.CLOSED,a.onclose(),console.log("NDN.onclose event fired.")):(console.log("Connected to ccnd."),b.ccndid=e.signedInfo.publisher.publisherPublicKeyDigest,3<LOG&&console.log(b.ccndid),a.readyStatus=NDN.OPENED,a.onopen(),console.log("NDN.onopen event fired.")):(f=getEntryForExpressedInterest(f),null!=f&&f.closure.upcall(Closure.UPCALL_CONTENT,
-new UpcallInfo(a,null,0,e)))):console.log("Incoming packet is not Interest or ContentObject. Discard now.");delete c;delete b.structureDecoder;delete b.buffer;b.structureDecoder=new BinaryXMLStructureDecoder;b.buffer=new Uint8Array(b.maxBufferSize)}};this.ws.onopen=function(a){console.log(a);console.log("ws.onopen: WebSocket connection opened.");console.log("ws.onopen: ReadyState: "+this.readyState);interest=new Interest(new Name(ccndIdFetcher));interest.InterestLifetime=4200;var a=encodeToBinaryInterest(interest),
-d=new Uint8Array(a.length);d.set(a);b.ws.send(d.buffer)};this.ws.onerror=function(a){console.log("ws.onerror: ReadyState: "+this.readyState);console.log(a);console.log("ws.onerror: WebSocket error: "+a.data)};this.ws.onclose=function(){console.log("ws.onclose: WebSocket connection closed.");b.ws=null;a.readyStatus=NDN.CLOSED;a.onclose();console.log("NDN.onclose event fired.")}};var PITTable=[],PITEntry=function(a,b){this.interest=a;this.closure=b};
-function getEntryForExpressedInterest(a){for(var b=0;b<PITTable.length;b++)if(null!=a.match(PITTable[b].interest))return PITTable[b];return null}var CSTable=[],CSEntry=function(a,b){this.name=a;this.closure=b};function getEntryForRegisteredPrefix(a){for(var b=0;b<CSTable.length;b++)if(null!=CSTable[b].name.match(a))return CSTable[b];return null}
-WebSocketTransport.prototype.registerPrefix=function(a,b,c){if(null!=this.ws)if(null==this.ccndid)console.log("ccnd node ID unkonwn. Cannot register prefix.");else{var a=new ForwardingEntry("selfreg",b,null,null,3,2147483647),a=encodeForwardingEntry(a),d=new SignedInfo;d.setFields();a=new ContentObject(new Name,d,a,new Signature);a.sign();a=encodeToBinaryContentObject(a);a=new Name(["ccnx",this.ccndid,"selfreg",a]);a=new Interest(a);a.scope=1;d=encodeToBinaryInterest(a);a=new Uint8Array(d.length);
-a.set(d);console.log("Send Interest registration packet.");b=new CSEntry(b.getName(),c);CSTable.push(b);this.ws.send(a.buffer);return 0}else return console.log("WebSocket connection is not established."),-1};
+if(c.peekStartElement(CCNProtocolDTags.Interest)){3<LOG&&console.log("Interest packet received.");var e=new Interest;e.from_ccnb(c);3<LOG&&console.log(e);var f=escape(e.name.getName());3<LOG&&console.log(f);f=getEntryForRegisteredPrefix(f);null!=f&&f.closure.upcall(Closure.UPCALL_INTEREST,new UpcallInfo(a,e,0,null))}else c.peekStartElement(CCNProtocolDTags.ContentObject)?(3<LOG&&console.log("ContentObject packet received."),e=new ContentObject,e.from_ccnb(c),3<LOG&&console.log(e),f=e.name.getName(),
+3<LOG&&console.log(f),null==b.ccndid&&null!=f.match(ccndIdFetcher)?!e.signedInfo||!e.signedInfo.publisher||!e.signedInfo.publisher.publisherPublicKeyDigest?(console.log("Cannot contact router, close NDN now."),a.readyStatus=NDN.CLOSED,a.onclose()):(b.ccndid=e.signedInfo.publisher.publisherPublicKeyDigest,3<LOG&&console.log(b.ccndid),a.readyStatus=NDN.OPENED,a.onopen()):(f=getEntryForExpressedInterest(f),null!=f&&(clearTimeout(f.closure.timerID),f.closure.upcall(Closure.UPCALL_CONTENT,new UpcallInfo(a,
+null,0,e))))):console.log("Incoming packet is not Interest or ContentObject. Discard now.");delete c;delete b.structureDecoder;delete b.buffer;b.structureDecoder=new BinaryXMLStructureDecoder;b.buffer=new Uint8Array(b.maxBufferSize)}};this.ws.onopen=function(a){3<LOG&&console.log(a);3<LOG&&console.log("ws.onopen: WebSocket connection opened.");3<LOG&&console.log("ws.onopen: ReadyState: "+this.readyState);a=new Interest(new Name(ccndIdFetcher));a.InterestLifetime=4200;var a=encodeToBinaryInterest(a),
+d=new Uint8Array(a.length);d.set(a);b.ws.send(d.buffer)};this.ws.onerror=function(a){console.log("ws.onerror: ReadyState: "+this.readyState);console.log(a);console.log("ws.onerror: WebSocket error: "+a.data)};this.ws.onclose=function(){console.log("ws.onclose: WebSocket connection closed.");b.ws=null;a.readyStatus=NDN.CLOSED;a.onclose()}};var PITTable=[],PITEntry=function(a,b){this.interest=a;this.closure=b};
+function getEntryForExpressedInterest(a){for(var b=0;b<PITTable.length;b++)if(null!=a.match(PITTable[b].interest))return PITTable[b];return null}
+WebSocketTransport.prototype.expressInterest=function(a,b,c){if(null!=this.ws){var d=encodeToBinaryInterest(b),e=new Uint8Array(d.length);e.set(d);var f=new PITEntry(b.name.getName(),c);PITTable.push(f);this.ws.send(e.buffer);3<LOG&&console.log("ws.send() returned.");c.timerID=setTimeout(function(){console.log("Interest time out.");index=PITTable.indexOf(f);PITTable.splice(index,1);c.upcall(Closure.UPCALL_INTEREST_TIMED_OUT,new UpcallInfo(a,b,0,null))},NDN.InterestTimeOut)}else console.log("WebSocket connection is not established.")};
+var CSTable=[],CSEntry=function(a,b){this.name=a;this.closure=b};function getEntryForRegisteredPrefix(a){for(var b=0;b<CSTable.length;b++)if(null!=CSTable[b].name.match(a))return CSTable[b];return null}
+WebSocketTransport.prototype.registerPrefix=function(a,b,c){if(null!=this.ws){if(null==this.ccndid)return console.log("ccnd node ID unkonwn. Cannot register prefix."),-1;var a=new ForwardingEntry("selfreg",b,null,null,3,2147483647),a=encodeForwardingEntry(a),d=new SignedInfo;d.setFields();a=new ContentObject(new Name,d,a,new Signature);a.sign();a=encodeToBinaryContentObject(a);a=new Name(["ccnx",this.ccndid,"selfreg",a]);a=new Interest(a);a.scope=1;d=encodeToBinaryInterest(a);a=new Uint8Array(d.length);
+a.set(d);3<LOG&&console.log("Send Interest registration packet.");b=new CSEntry(b.getName(),c);CSTable.push(b);this.ws.send(a.buffer);return 0}console.log("WebSocket connection is not established.");return-1};
 var CCNProtocolDTags={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,Key:27,KeyLocator:28,KeyName:29,Length:30,Link:31,LinkAuthenticator:32,NameComponentCount:33,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,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,StatusResponse:112,StatusCode:113,StatusText:114,SyncNode:115,SyncNodeKind:116,SyncNodeElement:117,SyncVersion:118,SyncNodeElements:119,SyncContentHash:120,
@@ -27,14 +28,15 @@
 Name.prototype.add=function(a){var b;if("string"==typeof a)b=DataUtils.stringToUtf8Array(a);else if("object"==typeof a&&a instanceof Uint8Array)b=new Uint8Array(a);else if("object"==typeof a&&a instanceof ArrayBuffer)b=new Uint8Array(new ArrayBuffer(a.byteLength)),b.set(new Uint8Array(a));else if("object"==typeof a)b=new Uint8Array(a);else throw Error("Cannot add Name element at index "+this.components.length+": Invalid type");return this.components.push(b)};
 Name.prototype.to_uri=function(){for(var a="",b=0;b<this.components.length;++b)a+="/"+Name.toEscapedString(this.components[b]);return a};Name.prototype.getPrefix=function(a){return new Name(this.components.slice(0,a))};Name.prototype.getComponent=function(a){var b=new ArrayBuffer(this.components[a].length);(new Uint8Array(b)).set(this.components[a]);return b};
 Name.prototype.indexOfFileName=function(){for(var a=this.components.length-1;0<=a;--a){var b=this.components[a];if(!(0>=b.length)&&!(0==b[0]||192==b[0]||193==b[0]||245<=b[0]&&255>=b[0]))return a}return-1};
-Name.toEscapedString=function(a){for(var b="",c=!1,d=0;d<a.length;++d)if(46!=a[d]){c=!0;break}if(c)for(d=0;d<a.length;++d)c=a[d],b=48<=c&&57>=c||65<=c&&90>=c||97<=c&&122>=c||43==c||45==c||46==c||95==c?b+String.fromCharCode(c):b+("%"+(16>c?"0":"")+c.toString(16).toUpperCase());else{b="...";for(d=0;d<a.length;++d)b+="."}return b};
+Name.prototype.getContentDigestValue=function(){for(var a=Name.ContentDigestPrefix.length+32+Name.ContentDigestSuffix.length,b=this.components.length-1;0<=b;--b)if(this.components[b].length==a&&DataUtils.arraysEqual(this.components[b].subarray(0,Name.ContentDigestPrefix.length),Name.ContentDigestPrefix)&&DataUtils.arraysEqual(this.components[b].subarray(this.components[b].length-Name.ContentDigestSuffix.length,this.components[b].length),Name.ContentDigestSuffix))return this.components[b].subarray(Name.ContentDigestPrefix.length,
+Name.ContentDigestPrefix.length+32);return null};Name.ContentDigestPrefix=new Uint8Array([193,46,77,46,71,193,1,170,2,133]);Name.ContentDigestSuffix=new Uint8Array([0]);Name.toEscapedString=function(a){for(var b="",c=!1,d=0;d<a.length;++d)if(46!=a[d]){c=!0;break}if(c)for(d=0;d<a.length;++d)c=a[d],b=48<=c&&57>=c||65<=c&&90>=c||97<=c&&122>=c||43==c||45==c||46==c||95==c?b+String.fromCharCode(c):b+("%"+(16>c?"0":"")+c.toString(16).toUpperCase());else{b="...";for(d=0;d<a.length;++d)b+="."}return b};
 var ContentObject=function(a,b,c,d){this.name="string"===typeof a?new Name(a):a;this.signedInfo=b;this.content=c;this.signature=d;this.rawSignatureData=this.endContent=this.startSignedInfo=this.endSIG=this.startSIG=null};
 ContentObject.prototype.sign=function(){var a=this.encodeObject(this.name),b=this.encodeObject(this.signedInfo),c=this.encodeContent(),d=new ArrayBuffer(a.length+b.length+c.length),d=new Uint8Array(d);d.set(a,0);d.set(b,a.length);d.set(c,a.length+b.length);4<LOG&&console.log("Signature Data is (binary) "+d);4<LOG&&console.log("Signature Data is (RawString)");4<LOG&&console.log(DataUtils.toString(d));a=new RSAKey;a.readPrivateKeyFromPEMString(globalKeyManager.privateKey);a=a.signByteArrayWithSHA256(d);
 4<LOG&&console.log("SIGNATURE SAVED IS");4<LOG&&console.log(a);4<LOG&&console.log(DataUtils.toNumbers(a.trim()));this.signature.signature=DataUtils.toNumbers(a.trim())};ContentObject.prototype.encodeObject=function(a){var b=new BinaryXMLEncoder;a.to_ccnb(b);return b.getReducedOstream()};ContentObject.prototype.encodeContent=function(){var a=new BinaryXMLEncoder;a.writeElement(CCNProtocolDTags.Content,this.content);return a.getReducedOstream()};
 ContentObject.prototype.saveRawData=function(a){this.rawSignatureData=a.subarray(this.startSIG,this.endSIG)};
 ContentObject.prototype.from_ccnb=function(a){a.readStartElement(this.getElementLabel());a.peekStartElement(CCNProtocolDTags.Signature)&&(this.signature=new Signature,this.signature.from_ccnb(a));this.startSIG=a.offset;this.name=new Name;this.name.from_ccnb(a);a.peekStartElement(CCNProtocolDTags.SignedInfo)&&(this.signedInfo=new SignedInfo,this.signedInfo.from_ccnb(a));this.content=a.readBinaryElement(CCNProtocolDTags.Content);this.endSIG=a.offset;a.readEndElement();this.saveRawData(a.istream)};
 ContentObject.prototype.to_ccnb=function(a){a.writeStartElement(this.getElementLabel());null!=this.signature&&this.signature.to_ccnb(a);this.startSIG=a.offset;null!=this.name&&this.name.to_ccnb(a);null!=this.signedInfo&&this.signedInfo.to_ccnb(a);a.writeElement(CCNProtocolDTags.Content,this.content);this.endSIG=a.offset;a.writeEndElement();this.saveRawData(a.ostream)};ContentObject.prototype.getElementLabel=function(){return CCNProtocolDTags.ContentObject};
-var Signature=function(a,b,c){this.Witness=a;this.signature=b;this.digestAlgorithm=c},generateSignature=function(a,b,c){var d=new BinaryXMLEncoder;a.to_ccnb(d);toHex(d.getReducedOstream());d=new BinaryXMLEncoder;b.to_ccnb(d);toHex(d.getReducedOstream());d=new BinaryXMLEncoder;c.to_ccnb(d);toHex(d.getReducedOstream())};
+var Signature=function(a,b,c){this.Witness=a;this.signature=b;this.digestAlgorithm=c};
 Signature.prototype.from_ccnb=function(a){a.readStartElement(this.getElementLabel());4<LOG&&console.log("STARTED DECODING SIGNATURE ");a.peekStartElement(CCNProtocolDTags.DigestAlgorithm)&&(4<LOG&&console.log("DIGIEST ALGORITHM FOUND"),this.digestAlgorithm=a.readUTF8Element(CCNProtocolDTags.DigestAlgorithm));a.peekStartElement(CCNProtocolDTags.Witness)&&(4<LOG&&console.log("WITNESS FOUND FOUND"),this.Witness=a.readBinaryElement(CCNProtocolDTags.Witness));this.signature=a.readBinaryElement(CCNProtocolDTags.SignatureBits);
 4<LOG&&console.log("READ SIGNATURE ");a.readEndElement()};
 Signature.prototype.to_ccnb=function(a){if(!this.validate())throw Error("Cannot encode: field values missing.");a.writeStartElement(this.getElementLabel());null!=this.digestAlgorithm&&!this.digestAlgorithm.equals(CCNDigestHelper.DEFAULT_DIGEST_ALGORITHM)&&a.writeElement(CCNProtocolDTags.DigestAlgorithm,OIDLookup.getDigestOID(this.DigestAlgorithm));null!=this.Witness&&a.writeElement(CCNProtocolDTags.Witness,this.Witness);a.writeElement(CCNProtocolDTags.SignatureBits,this.signature);a.writeEndElement()};
@@ -48,8 +50,8 @@
 SignedInfo.prototype.to_ccnb=function(a){if(!this.validate())throw Error("Cannot encode : field values missing.");a.writeStartElement(this.getElementLabel());null!=this.publisher&&(3<LOG&&console.log("ENCODING PUBLISHER KEY"+this.publisher.publisherPublicKeyDigest),this.publisher.to_ccnb(a));null!=this.timestamp&&a.writeDateTime(CCNProtocolDTags.Timestamp,this.timestamp);null!=this.type&&0!=this.type&&a.writeElement(CCNProtocolDTags.type,this.type);null!=this.freshnessSeconds&&a.writeElement(CCNProtocolDTags.FreshnessSeconds,
 this.freshnessSeconds);null!=this.finalBlockID&&a.writeElement(CCNProtocolDTags.FinalBlockID,this.finalBlockID);null!=this.locator&&this.locator.to_ccnb(a);a.writeEndElement()};SignedInfo.prototype.valueToType=function(){return null};SignedInfo.prototype.getElementLabel=function(){return CCNProtocolDTags.SignedInfo};SignedInfo.prototype.validate=function(){return null==this.publisher||null==this.timestamp||null==this.locator?!1:!0};
 var DateFormat=function(){var a=/d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,b=/\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,c=/[^-+\dA-Z]/g,d=function(a,b){a=String(a);for(b=b||2;a.length<b;)a="0"+a;return a};return function(e,f,g){var h=dateFormat;1==arguments.length&&("[object String]"==Object.prototype.toString.call(e)&&!/\d/.test(e))&&(f=e,e=void 0);e=e?new Date(e):new Date;if(isNaN(e))throw SyntaxError("invalid date");
-f=String(h.masks[f]||f||h.masks["default"]);"UTC:"==f.slice(0,4)&&(f=f.slice(4),g=!0);var j=g?"getUTC":"get",l=e[j+"Date"](),n=e[j+"Day"](),m=e[j+"Month"](),p=e[j+"FullYear"](),k=e[j+"Hours"](),q=e[j+"Minutes"](),r=e[j+"Seconds"](),j=e[j+"Milliseconds"](),s=g?0:e.getTimezoneOffset(),t={d:l,dd:d(l),ddd:h.i18n.dayNames[n],dddd:h.i18n.dayNames[n+7],m:m+1,mm:d(m+1),mmm:h.i18n.monthNames[m],mmmm:h.i18n.monthNames[m+12],yy:String(p).slice(2),yyyy:p,h:k%12||12,hh:d(k%12||12),H:k,HH:d(k),M:q,MM:d(q),s:r,
-ss:d(r),l:d(j,3),L:d(99<j?Math.round(j/10):j),t:12>k?"a":"p",tt:12>k?"am":"pm",T:12>k?"A":"P",TT:12>k?"AM":"PM",Z:g?"UTC":(String(e).match(b)||[""]).pop().replace(c,""),o:(0<s?"-":"+")+d(100*Math.floor(Math.abs(s)/60)+Math.abs(s)%60,4),S:["th","st","nd","rd"][3<l%10?0:(10!=l%100-l%10)*l%10]};return f.replace(a,function(a){return a in t?t[a]:a.slice(1,a.length-1)})}}();
+f=String(h.masks[f]||f||h.masks["default"]);"UTC:"==f.slice(0,4)&&(f=f.slice(4),g=!0);var j=g?"getUTC":"get",l=e[j+"Date"](),n=e[j+"Day"](),m=e[j+"Month"](),p=e[j+"FullYear"](),k=e[j+"Hours"](),q=e[j+"Minutes"](),s=e[j+"Seconds"](),j=e[j+"Milliseconds"](),r=g?0:e.getTimezoneOffset(),t={d:l,dd:d(l),ddd:h.i18n.dayNames[n],dddd:h.i18n.dayNames[n+7],m:m+1,mm:d(m+1),mmm:h.i18n.monthNames[m],mmmm:h.i18n.monthNames[m+12],yy:String(p).slice(2),yyyy:p,h:k%12||12,hh:d(k%12||12),H:k,HH:d(k),M:q,MM:d(q),s:s,
+ss:d(s),l:d(j,3),L:d(99<j?Math.round(j/10):j),t:12>k?"a":"p",tt:12>k?"am":"pm",T:12>k?"A":"P",TT:12>k?"AM":"PM",Z:g?"UTC":(String(e).match(b)||[""]).pop().replace(c,""),o:(0<r?"-":"+")+d(100*Math.floor(Math.abs(r)/60)+Math.abs(r)%60,4),S:["th","st","nd","rd"][3<l%10?0:(10!=l%100-l%10)*l%10]};return f.replace(a,function(a){return a in t?t[a]:a.slice(1,a.length-1)})}}();
 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'"};DateFormat.i18n={dayNames:"Sun Mon Tue Wed Thu Fri Sat Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),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".split(" ")};
 Date.prototype.format=function(a,b){return dateFormat(this,a,b)};var Interest=function(a,b,c,d,e,f,g,h,j,l,n){this.name=a;this.faceInstance=b;this.maxSuffixComponents=d;this.minSuffixComponents=c;this.publisherPublicKeyDigest=e;this.exclude=f;this.childSelector=g;this.answerOriginKind=h;this.scope=j;this.interestLifetime=l;this.nonce=n};Interest.RECURSIVE_POSTFIX="*";Interest.CHILD_SELECTOR_LEFT=0;Interest.CHILD_SELECTOR_RIGHT=1;Interest.ANSWER_CONTENT_STORE=1;Interest.ANSWER_GENERATED=2;
 Interest.ANSWER_STALE=4;Interest.MARK_STALE=16;Interest.DEFAULT_ANSWER_ORIGIN_KIND=Interest.ANSWER_CONTENT_STORE|Interest.ANSWER_GENERATED;
@@ -149,14 +151,17 @@
 function rstr2b64(a){try{b64pad}catch(b){b64pad=""}for(var c="",d=a.length,e=0;e<d;e+=3)for(var f=a.charCodeAt(e)<<16|(e+1<d?a.charCodeAt(e+1)<<8:0)|(e+2<d?a.charCodeAt(e+2):0),g=0;4>g;g++)c=8*e+6*g>8*a.length?c+b64pad:c+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".charAt(f>>>6*(3-g)&63);return c}
 function rstr2any(a,b){var c=b.length,d=[],e,f,g,h,j=Array(Math.ceil(a.length/2));for(e=0;e<j.length;e++)j[e]=a.charCodeAt(2*e)<<8|a.charCodeAt(2*e+1);for(;0<j.length;){h=[];for(e=g=0;e<j.length;e++)if(g=(g<<16)+j[e],f=Math.floor(g/c),g-=f*c,0<h.length||0<f)h[h.length]=f;d[d.length]=g;j=h}c="";for(e=d.length-1;0<=e;e--)c+=b.charAt(d[e]);d=Math.ceil(8*a.length/(Math.log(b.length)/Math.log(2)));for(e=c.length;e<d;e++)c=b[0]+c;return c}
 function str2rstr_utf8(a){for(var b="",c=-1,d,e;++c<a.length;)d=a.charCodeAt(c),e=c+1<a.length?a.charCodeAt(c+1):0,55296<=d&&(56319>=d&&56320<=e&&57343>=e)&&(d=65536+((d&1023)<<10)+(e&1023),c++),127>=d?b+=String.fromCharCode(d):2047>=d?b+=String.fromCharCode(192|d>>>6&31,128|d&63):65535>=d?b+=String.fromCharCode(224|d>>>12&15,128|d>>>6&63,128|d&63):2097151>=d&&(b+=String.fromCharCode(240|d>>>18&7,128|d>>>12&63,128|d>>>6&63,128|d&63));return b}
-function str2rstr_utf16le(a){for(var b="",c=0;c<a.length;c++)b+=String.fromCharCode(a.charCodeAt(c)&255,a.charCodeAt(c)>>>8&255);return b}function str2rstr_utf16be(a){for(var b="",c=0;c<a.length;c++)b+=String.fromCharCode(a.charCodeAt(c)>>>8&255,a.charCodeAt(c)&255);return b}function rstr2binb(a){for(var b=Array(a.length>>2),c=0;c<b.length;c++)b[c]=0;for(c=0;c<8*a.length;c+=8)b[c>>5]|=(a.charCodeAt(c/8)&255)<<24-c%32;return b}
-function byteArray2binb(a){for(var b=Array(a.length>>2),c=0;c<b.length;c++)b[c]=0;for(c=0;c<8*a.length;c+=8)b[c>>5]|=(a[c/8]&255)<<24-c%32;return b}function binb2rstr(a){for(var b="",c=0;c<32*a.length;c+=8)b+=String.fromCharCode(a[c>>5]>>>24-c%32&255);return b}function sha256_S(a,b){return a>>>b|a<<32-b}function sha256_R(a,b){return a>>>b}function sha256_Ch(a,b,c){return a&b^~a&c}function sha256_Maj(a,b,c){return a&b^a&c^b&c}
-function sha256_Sigma0256(a){return sha256_S(a,2)^sha256_S(a,13)^sha256_S(a,22)}function sha256_Sigma1256(a){return sha256_S(a,6)^sha256_S(a,11)^sha256_S(a,25)}function sha256_Gamma0256(a){return sha256_S(a,7)^sha256_S(a,18)^sha256_R(a,3)}function sha256_Gamma1256(a){return sha256_S(a,17)^sha256_S(a,19)^sha256_R(a,10)}function sha256_Sigma0512(a){return sha256_S(a,28)^sha256_S(a,34)^sha256_S(a,39)}function sha256_Sigma1512(a){return sha256_S(a,14)^sha256_S(a,18)^sha256_S(a,41)}
-function sha256_Gamma0512(a){return sha256_S(a,1)^sha256_S(a,8)^sha256_R(a,7)}function sha256_Gamma1512(a){return sha256_S(a,19)^sha256_S(a,61)^sha256_R(a,6)}
+function str2rstr_utf16le(a){for(var b="",c=0;c<a.length;c++)b+=String.fromCharCode(a.charCodeAt(c)&255,a.charCodeAt(c)>>>8&255);return b}function str2rstr_utf16be(a){for(var b="",c=0;c<a.length;c++)b+=String.fromCharCode(a.charCodeAt(c)>>>8&255,a.charCodeAt(c)&255);return b}function rstr2binb(a){for(var b=Array(a.length>>2),c=0;c<8*a.length;c+=8)b[c>>5]|=(a.charCodeAt(c/8)&255)<<24-c%32;return b}
+function byteArray2binb(a){for(var b=Array(a.length>>2),c=0;c<8*a.length;c+=8)b[c>>5]|=(a[c/8]&255)<<24-c%32;return b}function binb2rstr(a){for(var b="",c=0;c<32*a.length;c+=8)b+=String.fromCharCode(a[c>>5]>>>24-c%32&255);return b}function sha256_S(a,b){return a>>>b|a<<32-b}function sha256_R(a,b){return a>>>b}function sha256_Ch(a,b,c){return a&b^~a&c}function sha256_Maj(a,b,c){return a&b^a&c^b&c}function sha256_Sigma0256(a){return sha256_S(a,2)^sha256_S(a,13)^sha256_S(a,22)}
+function sha256_Sigma1256(a){return sha256_S(a,6)^sha256_S(a,11)^sha256_S(a,25)}function sha256_Gamma0256(a){return sha256_S(a,7)^sha256_S(a,18)^sha256_R(a,3)}function sha256_Gamma1256(a){return sha256_S(a,17)^sha256_S(a,19)^sha256_R(a,10)}function sha256_Sigma0512(a){return sha256_S(a,28)^sha256_S(a,34)^sha256_S(a,39)}function sha256_Sigma1512(a){return sha256_S(a,14)^sha256_S(a,18)^sha256_S(a,41)}function sha256_Gamma0512(a){return sha256_S(a,1)^sha256_S(a,8)^sha256_R(a,7)}
+function sha256_Gamma1512(a){return sha256_S(a,19)^sha256_S(a,61)^sha256_R(a,6)}
 var sha256_K=[1116352408,1899447441,-1245643825,-373957723,961987163,1508970993,-1841331548,-1424204075,-670586216,310598401,607225278,1426881987,1925078388,-2132889090,-1680079193,-1046744716,-459576895,-272742522,264347078,604807628,770255983,1249150122,1555081692,1996064986,-1740746414,-1473132947,-1341970488,-1084653625,-958395405,-710438585,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,-2117940946,-1838011259,-1564481375,-1474664885,-1035236496,-949202525,
--778901479,-694614492,-200395387,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,-2067236844,-1933114872,-1866530822,-1538233109,-1090935817,-965641998];
-function binb_sha256(a,b){var c=[1779033703,-1150833019,1013904242,-1521486534,1359893119,-1694144372,528734635,1541459225],d=Array(64),e,f,g,h,j,l,n,m,p,k,q,r;a[b>>5]|=128<<24-b%32;a[(b+64>>9<<4)+15]=b;for(p=0;p<a.length;p+=16){e=c[0];f=c[1];g=c[2];h=c[3];j=c[4];l=c[5];n=c[6];m=c[7];for(k=0;64>k;k++)d[k]=16>k?a[k+p]:safe_add(safe_add(safe_add(sha256_Gamma1256(d[k-2]),d[k-7]),sha256_Gamma0256(d[k-15])),d[k-16]),q=safe_add(safe_add(safe_add(safe_add(m,sha256_Sigma1256(j)),sha256_Ch(j,l,n)),sha256_K[k]),
-d[k]),r=safe_add(sha256_Sigma0256(e),sha256_Maj(e,f,g)),m=n,n=l,l=j,j=safe_add(h,q),h=g,g=f,f=e,e=safe_add(q,r);c[0]=safe_add(e,c[0]);c[1]=safe_add(f,c[1]);c[2]=safe_add(g,c[2]);c[3]=safe_add(h,c[3]);c[4]=safe_add(j,c[4]);c[5]=safe_add(l,c[5]);c[6]=safe_add(n,c[6]);c[7]=safe_add(m,c[7])}return c}function safe_add(a,b){var c=(a&65535)+(b&65535);return(a>>16)+(b>>16)+(c>>16)<<16|c&65535}var b64map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",b64pad="=";
+-778901479,-694614492,-200395387,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,-2067236844,-1933114872,-1866530822,-1538233109,-1090935817,-965641998];function binb_sha256(a,b){var c=[1779033703,-1150833019,1013904242,-1521486534,1359893119,-1694144372,528734635,1541459225],d=Array(64);a[b>>5]|=128<<24-b%32;a[(b+64>>9<<4)+15]=b;for(var e=0;e<a.length;e+=16)processBlock_sha256(a,e,c,d);return c}
+function processBlock_sha256(a,b,c,d){var e,f,g,h,j,l,n,m,p,k,q;e=c[0];f=c[1];g=c[2];h=c[3];j=c[4];l=c[5];n=c[6];m=c[7];for(p=0;64>p;p++)d[p]=16>p?a[p+b]:safe_add(safe_add(safe_add(sha256_Gamma1256(d[p-2]),d[p-7]),sha256_Gamma0256(d[p-15])),d[p-16]),k=safe_add(safe_add(safe_add(safe_add(m,sha256_Sigma1256(j)),sha256_Ch(j,l,n)),sha256_K[p]),d[p]),q=safe_add(sha256_Sigma0256(e),sha256_Maj(e,f,g)),m=n,n=l,l=j,j=safe_add(h,k),h=g,g=f,f=e,e=safe_add(k,q);c[0]=safe_add(e,c[0]);c[1]=safe_add(f,c[1]);c[2]=
+safe_add(g,c[2]);c[3]=safe_add(h,c[3]);c[4]=safe_add(j,c[4]);c[5]=safe_add(l,c[5]);c[6]=safe_add(n,c[6]);c[7]=safe_add(m,c[7])}function safe_add(a,b){var c=(a&65535)+(b&65535);return(a>>16)+(b>>16)+(c>>16)<<16|c&65535}var Sha256=function(){this.W=Array(64);this.hash=[1779033703,-1150833019,1013904242,-1521486534,1359893119,-1694144372,528734635,1541459225];this.nTotalBytes=0;this.buffer=new Uint8Array(64);this.nBufferBytes=0};
+Sha256.prototype.update=function(a){this.nTotalBytes+=a.length;if(0<this.nBufferBytes){var b=this.buffer.length-this.nBufferBytes;if(a.length<b){this.buffer.set(a,this.nBufferBytes);this.nBufferBytes+=a.length;return}this.buffer.set(a.subarray(0,b),this.nBufferBytes);processBlock_sha256(byteArray2binb(this.buffer),0,this.hash,this.W);this.nBufferBytes=0;a=a.subarray(b,a.length);if(0==a.length)return}b=a.length>>6;if(0<b){for(var b=64*b,c=byteArray2binb(a.subarray(0,b)),d=0;d<c.length;d+=16)processBlock_sha256(c,
+d,this.hash,this.W);a=a.subarray(b,a.length)}0<a.length&&(this.buffer.set(a),this.nBufferBytes=a.length)};Sha256.prototype.finalize=function(){var a=byteArray2binb(this.buffer.subarray(0,this.nBufferBytes)),b=8*this.nBufferBytes;a[b>>5]|=128<<24-b%32;a[(b+64>>9<<4)+15]=8*this.nTotalBytes;for(b=0;b<a.length;b+=16)processBlock_sha256(a,b,this.hash,this.W);return Sha256.binb2Uint8Array(this.hash)};
+Sha256.binb2Uint8Array=function(a){for(var b=new Uint8Array(4*a.length),c=0,d=0;d<32*a.length;d+=8)b[c++]=a[d>>5]>>>24-d%32&255;return b};var b64map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",b64pad="=";
 function hex2b64(a){var b,c,d="";for(b=0;b+3<=a.length;b+=3)c=parseInt(a.substring(b,b+3),16),d+=b64map.charAt(c>>6)+b64map.charAt(c&63);b+1==a.length?(c=parseInt(a.substring(b,b+1),16),d+=b64map.charAt(c<<2)):b+2==a.length&&(c=parseInt(a.substring(b,b+2),16),d+=b64map.charAt(c>>2)+b64map.charAt((c&3)<<4));for(;0<(d.length&3);)d+=b64pad;return d}
 function b64tohex(a){var b="",c,d=0,e;for(c=0;c<a.length&&a.charAt(c)!=b64pad;++c)v=b64map.indexOf(a.charAt(c)),0>v||(0==d?(b+=int2char(v>>2),e=v&3,d=1):1==d?(b+=int2char(e<<2|v>>4),e=v&15,d=2):2==d?(b+=int2char(e),b+=int2char(v>>2),e=v&3,d=3):(b+=int2char(e<<2|v>>4),b+=int2char(v&15),d=0));1==d&&(b+=int2char(e<<2));return b}function b64toBA(a){var a=b64tohex(a),b,c=[];for(b=0;2*b<a.length;++b)c[b]=parseInt(a.substring(2*b,2*b+2),16);return c}function parseBigInt(a,b){return new BigInteger(a,b)}
 function linebrk(a,b){for(var c="",d=0;d+b<a.length;)c+=a.substring(d,d+b)+"\n",d+=b;return c+a.substring(d,a.length)}function byte2Hex(a){return 16>a?"0"+a.toString(16):a.toString(16)}