In _x509_getSubjectPublicKeyPosFromCertHex and _x509_getPublicKeyHexArrayFromCertHex, added an optional position argument to enable decoding a SubjectPublicKeyInfo directly.
diff --git a/js/tools/build/ndn-js-uncomp.js b/js/tools/build/ndn-js-uncomp.js
index 73d3862..3ec855a 100644
--- a/js/tools/build/ndn-js-uncomp.js
+++ b/js/tools/build/ndn-js-uncomp.js
@@ -92,7 +92,6 @@
     this.transport = getTransport();
     this.getHostAndPort = (settings.getHostAndPort || this.transport.defaultGetHostAndPort);
 	this.host = (settings.host !== undefined ? settings.host : 'localhost');
-    dump("this.host " + this.host + "\n");
 	this.port = (settings.port || 9696);
     this.readyStatus = NDN.UNOPEN;
     // Event handler
@@ -341,7 +340,22 @@
 				var entry = getEntryForRegisteredPrefix(nameStr);
 				if (entry != null) {
 					//console.log(entry);
-					entry.closure.upcall(Closure.UPCALL_INTEREST, new UpcallInfo(ndn, interest, 0, null));
+					var info = new UpcallInfo(ndn, interest, 0, null);
+					var ret = entry.closure.upcall(Closure.UPCALL_INTEREST, info);
+					if (ret == Closure.RESULT_INTEREST_CONSUMED && info.contentObject != null) { 
+						var coBinary = encodeToBinaryContentObject(info.contentObject);
+						// If we directly use coBinary.buffer to feed ws.send(), WebSocket 
+						// will end up sending a packet with 10000 bytes of data. That 
+						// is, WebSocket will flush the entire buffer in BinaryXMLEncoder
+						// regardless of the offset of the Uint8Array. So we have to
+						// create a new Uint8Array buffer with just the right size and
+						// copy the content from coBinary to the new buffer.
+						//    ---Wentao
+						var bytearray = new Uint8Array(coBinary.length);
+						bytearray.set(coBinary);
+						
+						self.ws.send(bytearray.buffer);
+					}
 				}
 				
 			} else if (decoder.peekStartElement(CCNProtocolDTags.ContentObject)) {  // Content packet
@@ -1015,26 +1029,37 @@
 
 /*
  * 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.
+ *   or null if not found.  See Name.getComponentContentDigestValue.
  */
 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);
+        var digestValue = Name.getComponentContentDigestValue(this.components[i]);
+        if (digestValue != null)
+           return digestValue;
     }
     
     return null;
 }
 
+/*
+ * If component is a ContentDigest, return the digest value as a Uint8Array subarray (don't modify!).
+ * If not a ContentDigest, return null.
+ * A ContentDigest component is Name.ContentDigestPrefix + 32 bytes + Name.ContentDigestSuffix.
+ */
+Name.getComponentContentDigestValue = function(component) {
+    var digestComponentLength = Name.ContentDigestPrefix.length + 32 + Name.ContentDigestSuffix.length; 
+    // Check for the correct length and equal ContentDigestPrefix and ContentDigestSuffix.
+    if (component.length == digestComponentLength &&
+        DataUtils.arraysEqual(component.subarray(0, Name.ContentDigestPrefix.length), 
+                              Name.ContentDigestPrefix) &&
+        DataUtils.arraysEqual(component.subarray
+           (component.length - Name.ContentDigestSuffix.length, component.length),
+                              Name.ContentDigestSuffix))
+       return component.subarray(Name.ContentDigestPrefix.length, Name.ContentDigestPrefix.length + 32);
+   else
+       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]);
@@ -1080,7 +1105,7 @@
 var ContentObject = function ContentObject(_name,_signedInfo,_content,_signature){
 	
 	
-	if (typeof _name === 'string'){
+	if (typeof _name == 'string') {
 		this.name = new Name(_name);
 	}
 	else{
@@ -1088,7 +1113,13 @@
 		this.name = _name;
 	}
 	this.signedInfo = _signedInfo;
-	this.content=_content;
+	
+	if (typeof _content == 'string') {
+		this.content = DataUtils.toNumbersFromString(_content);
+	} else {
+		this.content = _content;
+	}
+	
 	this.signature = _signature;
 
 	
@@ -1344,6 +1375,9 @@
     this.locator =_locator;//KeyLocator
     this.freshnessSeconds =_freshnessSeconds; // Integer
     this.finalBlockID=_finalBlockID; //byte array
+    
+    // SWT: merge setFields() method into constructor
+    this.setFields();
 
 };
 
@@ -4046,7 +4080,7 @@
 /**
  * Raw String to Uint8Array.
  */
-DataUtils.toNumbersFromString = function( str ){
+DataUtils.toNumbersFromString = function(str) {
 	var bytes = new Uint8Array(str.length);
 	for(var i=0;i<str.length;i++)
 		bytes[i] = str.charCodeAt(i);
@@ -4518,6 +4552,10 @@
 	    if(LOG>2) console.log('EXPONENT is ');
 	    if(LOG>2) console.log(exp);
 	    
+        var a = _x509_getPublicKeyHexArrayFromCertHex(publickeyHex, _x509_getSubjectPublicKeyPosFromCertHex(publickeyHex, 0));
+        output += "a[0] " + a[0] + "<br/>";
+        output += "a[1] " + a[1] + "<br/>";
+        
 	    /*var c1 = hex_sha256(input);
 	      var c2 = signature;
 	      
@@ -4558,6 +4596,8 @@
 
     return output;
 }
+
+
 /**
  * @author: Meki Cheraoui
  * See COPYING for copyright and distribution information.
@@ -6192,6 +6232,300 @@
 ASN1HEX.getDecendantIndexByNthList = _asnhex_getDecendantIndexByNthList;

 ASN1HEX.getDecendantHexVByNthList = _asnhex_getDecendantHexVByNthList;

 ASN1HEX.getDecendantHexTLVByNthList = _asnhex_getDecendantHexTLVByNthList;

+/*! x509-1.1.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license

+ */

+// 

+// x509.js - X509 class to read subject public key from certificate.

+//

+// version: 1.1 (10-May-2012)

+//

+// Copyright (c) 2010-2012 Kenji Urushima (kenji.urushima@gmail.com)

+//

+// This software is licensed under the terms of the MIT License.

+// http://kjur.github.com/jsrsasign/license

+//

+// The above copyright and license notice shall be 

+// included in all copies or substantial portions of the Software.

+// 

+

+// Depends:

+//   base64.js

+//   rsa.js

+//   asn1hex.js

+

+function _x509_pemToBase64(sCertPEM) {

+  var s = sCertPEM;

+  s = s.replace("-----BEGIN CERTIFICATE-----", "");

+  s = s.replace("-----END CERTIFICATE-----", "");

+  s = s.replace(/[ \n]+/g, "");

+  return s;

+}

+

+function _x509_pemToHex(sCertPEM) {

+  var b64Cert = _x509_pemToBase64(sCertPEM);

+  var hCert = b64tohex(b64Cert);

+  return hCert;

+}

+

+function _x509_getHexTbsCertificateFromCert(hCert) {

+  var pTbsCert = ASN1HEX.getStartPosOfV_AtObj(hCert, 0);

+  return pTbsCert;

+}

+

+// NOTE: privateKeyUsagePeriod field of X509v2 not supported.

+// NOTE: v1 and v3 supported

+function _x509_getSubjectPublicKeyInfoPosFromCertHex(hCert) {

+  var pTbsCert = ASN1HEX.getStartPosOfV_AtObj(hCert, 0);

+  var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pTbsCert); 

+  if (a.length < 1) return -1;

+  if (hCert.substring(a[0], a[0] + 10) == "a003020102") { // v3

+    if (a.length < 6) return -1;

+    return a[6];

+  } else {

+    if (a.length < 5) return -1;

+    return a[5];

+  }

+}

+

+// NOTE: Without BITSTRING encapsulation.

+// If pInfo is supplied, it is the position in hCert of the SubjectPublicKeyInfo.

+function _x509_getSubjectPublicKeyPosFromCertHex(hCert, pInfo) {

+  if (pInfo == null)

+      pInfo = _x509_getSubjectPublicKeyInfoPosFromCertHex(hCert);

+  if (pInfo == -1) return -1;    

+  var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pInfo); 

+  

+  if (a.length != 2) return -1;

+  var pBitString = a[1];

+  if (hCert.substring(pBitString, pBitString + 2) != '03') return -1;

+  var pBitStringV = ASN1HEX.getStartPosOfV_AtObj(hCert, pBitString);

+

+  if (hCert.substring(pBitStringV, pBitStringV + 2) != '00') return -1;

+  return pBitStringV + 2;

+}

+

+// If p is supplied, it is the public key position in hCert.

+function _x509_getPublicKeyHexArrayFromCertHex(hCert, p) {

+  if (p == null)

+      p = _x509_getSubjectPublicKeyPosFromCertHex(hCert);

+  var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, p); 

+  //var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a[3]); 

+  if(LOG>4){

+	  console.log('a is now');

+	  console.log(a);

+  }

+  

+  //if (a.length != 2) return [];

+  if (a.length < 2) return [];

+

+  var hN = ASN1HEX.getHexOfV_AtObj(hCert, a[0]);

+  var hE = ASN1HEX.getHexOfV_AtObj(hCert, a[1]);

+  if (hN != null && hE != null) {

+    return [hN, hE];

+  } else {

+    return [];

+  }

+}

+

+function _x509_getPublicKeyHexArrayFromCertPEM(sCertPEM) {

+  var hCert = _x509_pemToHex(sCertPEM);

+  var a = _x509_getPublicKeyHexArrayFromCertHex(hCert);

+  return a;

+}

+

+// ===== get basic fields from hex =====================================

+/**

+ * get hexadecimal string of serialNumber field of certificate.<br/>

+ * @name getSerialNumberHex

+ * @memberOf X509#

+ * @function

+ */

+function _x509_getSerialNumberHex() {

+  return ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 1]);

+}

+

+/**

+ * get hexadecimal string of issuer field of certificate.<br/>

+ * @name getIssuerHex

+ * @memberOf X509#

+ * @function

+ */

+function _x509_getIssuerHex() {

+  return ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 3]);

+}

+

+/**

+ * get string of issuer field of certificate.<br/>

+ * @name getIssuerString

+ * @memberOf X509#

+ * @function

+ */

+function _x509_getIssuerString() {

+  return _x509_hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 3]));

+}

+

+/**

+ * get hexadecimal string of subject field of certificate.<br/>

+ * @name getSubjectHex

+ * @memberOf X509#

+ * @function

+ */

+function _x509_getSubjectHex() {

+  return ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 5]);

+}

+

+/**

+ * get string of subject field of certificate.<br/>

+ * @name getSubjectString

+ * @memberOf X509#

+ * @function

+ */

+function _x509_getSubjectString() {

+  return _x509_hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 5]));

+}

+

+/**

+ * get notBefore field string of certificate.<br/>

+ * @name getNotBefore

+ * @memberOf X509#

+ * @function

+ */

+function _x509_getNotBefore() {

+  var s = ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 4, 0]);

+  s = s.replace(/(..)/g, "%$1");

+  s = decodeURIComponent(s);

+  return s;

+}

+

+/**

+ * get notAfter field string of certificate.<br/>

+ * @name getNotAfter

+ * @memberOf X509#

+ * @function

+ */

+function _x509_getNotAfter() {

+  var s = ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 4, 1]);

+  s = s.replace(/(..)/g, "%$1");

+  s = decodeURIComponent(s);

+  return s;

+}

+

+// ===== read certificate =====================================

+

+_x509_DN_ATTRHEX = {

+    "0603550406": "C",

+    "060355040a": "O",

+    "060355040b": "OU",

+    "0603550403": "CN",

+    "0603550405": "SN",

+    "0603550408": "ST",

+    "0603550407": "L" };

+

+function _x509_hex2dn(hDN) {

+  var s = "";

+  var a = ASN1HEX.getPosArrayOfChildren_AtObj(hDN, 0);

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

+    var hRDN = ASN1HEX.getHexOfTLV_AtObj(hDN, a[i]);

+    s = s + "/" + _x509_hex2rdn(hRDN);

+  }

+  return s;

+}

+

+function _x509_hex2rdn(hRDN) {

+    var hType = ASN1HEX.getDecendantHexTLVByNthList(hRDN, 0, [0, 0]);

+    var hValue = ASN1HEX.getDecendantHexVByNthList(hRDN, 0, [0, 1]);

+    var type = "";

+    try { type = _x509_DN_ATTRHEX[hType]; } catch (ex) { type = hType; }

+    hValue = hValue.replace(/(..)/g, "%$1");

+    var value = decodeURIComponent(hValue);

+    return type + "=" + value;

+}

+

+// ===== read certificate =====================================

+

+

+/**

+ * read PEM formatted X.509 certificate from string.<br/>

+ * @name readCertPEM

+ * @memberOf X509#

+ * @function

+ * @param {String} sCertPEM string for PEM formatted X.509 certificate

+ */

+function _x509_readCertPEM(sCertPEM) {

+  var hCert = _x509_pemToHex(sCertPEM);

+  var a = _x509_getPublicKeyHexArrayFromCertHex(hCert);

+  if(LOG>4){

+	  console.log('HEX VALUE IS ' + hCert);

+	  console.log('type of a' + typeof a);

+	  console.log('a VALUE IS ');

+	  console.log(a);

+	  console.log('a[0] VALUE IS ' + a[0]);

+	  console.log('a[1] VALUE IS ' + a[1]);

+  }

+  var rsa = new RSAKey();

+  rsa.setPublic(a[0], a[1]);

+  this.subjectPublicKeyRSA = rsa;

+  this.subjectPublicKeyRSA_hN = a[0];

+  this.subjectPublicKeyRSA_hE = a[1];

+  this.hex = hCert;

+}

+

+/**

+ * read hex formatted X.509 certificate from string.

+ * @name readCertHex

+ * @memberOf X509#

+ * @function

+ * @param {String} hCert string for hex formatted X.509 certificate

+ */

+function _x509_readCertHex(hCert) {

+  hCert = hCert.toLowerCase();

+  var a = _x509_getPublicKeyHexArrayFromCertHex(hCert);

+  var rsa = new RSAKey();

+  rsa.setPublic(a[0], a[1]);

+  this.subjectPublicKeyRSA = rsa;

+  this.subjectPublicKeyRSA_hN = a[0];

+  this.subjectPublicKeyRSA_hE = a[1];

+  this.hex = hCert;

+}

+

+function _x509_readCertPEMWithoutRSAInit(sCertPEM) {

+  var hCert = _x509_pemToHex(sCertPEM);

+  var a = _x509_getPublicKeyHexArrayFromCertHex(hCert);

+  this.subjectPublicKeyRSA.setPublic(a[0], a[1]);

+  this.subjectPublicKeyRSA_hN = a[0];

+  this.subjectPublicKeyRSA_hE = a[1];

+  this.hex = hCert;

+}

+

+/**

+ * X.509 certificate class.<br/>

+ * @class X.509 certificate class

+ * @property {RSAKey} subjectPublicKeyRSA Tom Wu's RSAKey object

+ * @property {String} subjectPublicKeyRSA_hN hexadecimal string for modulus of RSA public key

+ * @property {String} subjectPublicKeyRSA_hE hexadecimal string for public exponent of RSA public key

+ * @property {String} hex hexacedimal string for X.509 certificate.

+ * @author Kenji Urushima

+ * @version 1.0.1 (08 May 2012)

+ * @see <a href="http://kjur.github.com/jsrsasigns/">'jwrsasign'(RSA Sign JavaScript Library) home page http://kjur.github.com/jsrsasign/</a>

+ */

+function X509() {

+  this.subjectPublicKeyRSA = null;

+  this.subjectPublicKeyRSA_hN = null;

+  this.subjectPublicKeyRSA_hE = null;

+  this.hex = null;

+}

+

+X509.prototype.readCertPEM = _x509_readCertPEM;

+X509.prototype.readCertHex = _x509_readCertHex;

+X509.prototype.readCertPEMWithoutRSAInit = _x509_readCertPEMWithoutRSAInit;

+X509.prototype.getSerialNumberHex = _x509_getSerialNumberHex;

+X509.prototype.getIssuerHex = _x509_getIssuerHex;

+X509.prototype.getSubjectHex = _x509_getSubjectHex;

+X509.prototype.getIssuerString = _x509_getIssuerString;

+X509.prototype.getSubjectString = _x509_getSubjectString;

+X509.prototype.getNotBefore = _x509_getNotBefore;

+X509.prototype.getNotAfter = _x509_getNotAfter;

+

 // Copyright (c) 2005  Tom Wu

 // All Rights Reserved.

 // See "LICENSE" for details.