first commit
diff --git a/src/CCNProtocolDTags.js b/src/CCNProtocolDTags.js
new file mode 100644
index 0000000..cab4a4c
--- /dev/null
+++ b/src/CCNProtocolDTags.js
@@ -0,0 +1,125 @@
+
+
+
+exports.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"
+};
+
+
diff --git a/src/ContentName.js b/src/ContentName.js
new file mode 100644
index 0000000..54d70f9
--- /dev/null
+++ b/src/ContentName.js
@@ -0,0 +1,46 @@
+
+var CCNProtocolDTags = require('./CCNProtocolDTags').CCNProtocolDTags;
+
+var ContentName = function ContentName(_Components){
+
+
+ this.SCHEME = "ccnx:";
+
+ this.ORIGINAL_SCHEME = "ccn:";
+
+ this.SEPARATOR = "/";
+ this.ROOT = null;
+
+ this.Components = _Components;
+};
+
+exports.ContentName = ContentName;
+
+ContentName.prototype.decode = function(/*XMLDecoder*/ decoder) {
+ decoder.readStartElement(this.getElementLabel());
+
+ this.Components = new Array(); //new ArrayList<byte []>();
+
+ while (decoder.peekStartElement(CCNProtocolDTags.Component)) {
+ this.Components.add(decoder.readBinaryElement(CCNProtocolDTags.Component));
+ }
+
+ decoder.readEndElement();
+};
+
+ContentName.prototype.encode = function(/*XMLEncoder*/ encoder) {
+ //if (!validate()) {
+ //throw new ContentEncodingException("Cannot encode " + this.getClass().getName() + ": field values missing.");
+ //}
+
+ encoder.writeStartElement(this.getElementLabel());
+ var count = this.Components.length;
+ for (var i=0; i < count; ++i) {
+ encoder.writeElement(CCNProtocolDTags.Component, this.Components.get(i));
+ }
+ encoder.writeEndElement();
+};
+
+ContentName.prototype.getElementLabel = function(){
+ return CCNProtocolDTags.Name;
+};
diff --git a/src/ContentObject.js b/src/ContentObject.js
new file mode 100644
index 0000000..fb1ff09
--- /dev/null
+++ b/src/ContentObject.js
@@ -0,0 +1,61 @@
+
+var CCNProtocolDTags = require('./CCNProtocolDTags').CCNProtocolDTags;
+
+var ContentObject = function ContentObject(_Name,_SignedInfo,_Content,_Signature){
+
+
+ this.Name = _Name;
+ this.SignedInfo = _SignedInfo;
+ this.Content=_Content;
+ this.Signature = _Signature;
+
+};
+
+exports.ContentObject = ContentObject;
+
+
+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) {
+
+ if((null == this.Name) && (null==this.SignedInfo) && (null ==this.Signature)){
+
+ throw "Illegal input inside encode of Content Object";
+ }
+ /*
+ * if (!validate()) {
+ throw new ContentEncodingException("Cannot encode " + this.getClass().getName() + ": field values missing.");
+ }*/
+
+ encoder.writeStartElement(this.getElementLabel());
+
+ this.Signature.encode(encoder);
+ this.Name.encode(encoder);
+ this.SignedInfo.encode(encoder);
+
+ encoder.writeElement(CCNProtocolDTags.Content, this.Content);
+
+ encoder.writeEndElement();
+
+};
+
+
+ContentObject.prototype.getElementLabel= function(){returnCCNProtocolDTags.ContentObject;};
\ No newline at end of file
diff --git a/src/Exclude.js b/src/Exclude.js
new file mode 100644
index 0000000..667c8cf
--- /dev/null
+++ b/src/Exclude.js
@@ -0,0 +1,54 @@
+
+var CCNProtocolDTags = require('./CCNProtocolDTags').CCNProtocolDTags;
+
+var Exclude = function Exclude(_Values){
+
+ this.OPTIMUM_FILTER_SIZE = 100;
+
+
+ this.Values = _Values; //array of elements
+
+}
+exports.Exclude = Exclude;
+
+Exclude.prototype.decode = function(/*XMLDecoder*/ decoder) {
+
+
+
+ decoder.readStartElement(this.getElementLabel());
+
+ //TODO BUGS
+ /*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 everything is null, output nothing
+ if (empty())
+ return;
+
+ encoder.writeStartElement(getElementLabel());
+
+ /*
+ for (Element element : _values)
+ element.encode(encoder);
+ */
+
+ encoder.writeEndElement();
+ };
+
+Exclude.prototype.getElementLabel = function() { return CCNProtocolDTags.Exclude; };
+
diff --git a/src/ExcludeAny.js b/src/ExcludeAny.js
new file mode 100644
index 0000000..4fbeb14
--- /dev/null
+++ b/src/ExcludeAny.js
@@ -0,0 +1,21 @@
+
+var CCNProtocolDTags = require('./CCNProtocolDTags').CCNProtocolDTags;
+
+var ExcludeAny = function ExcludeAny() {
+
+};
+
+exports.ExcludeAny= 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/src/ExcludeComponent.js b/src/ExcludeComponent.js
new file mode 100644
index 0000000..91d6cae
--- /dev/null
+++ b/src/ExcludeComponent.js
@@ -0,0 +1,23 @@
+var CCNProtocolDTags = require('./CCNProtocolDTags').CCNProtocolDTags;
+
+/*
+ * _Body is an array of componenets
+ */
+var ExcludeComponent = function ExcludeComponent(_Body) {
+
+ //TODO Check BODY is an Array of componenets.
+
+ this.Body = _Body
+};
+exports.ExcludeComponent = ExcludeComponent;
+
+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/src/Interest.js b/src/Interest.js
new file mode 100644
index 0000000..1fd2585
--- /dev/null
+++ b/src/Interest.js
@@ -0,0 +1,128 @@
+var CCNProtocolDTags = require('./CCNProtocolDTags').CCNProtocolDTags;
+
+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;
+
+ /*Not sure if the rest is needed*/
+ this.Publisher = _Publisher;
+
+ this.UserTime=_UserTime;
+
+ 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 = ANSWER_CONTENT_STORE | ANSWER_GENERATED;
+
+
+};
+exports.Interest = Interest;
+
+Interest.prototype.decode(/*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 something about that guy
+ /*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
+
+ /*if (null != this.PublisherID)
+ publisherID().encode(encoder);*/
+
+ //if (null != this.Exclude)
+ //exclude().encode(encoder);
+
+ if (null != this.ChildSelector)
+ encoder.writeElement(CCNProtocolDTags.ChildSelector, this.ChildSelector);
+
+ if (this.DEFAULT_ANSWER_ORIGIN_KIND != this.AnswerOriginKind)
+ 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/src/KeyLocator.js b/src/KeyLocator.js
new file mode 100644
index 0000000..7d230da
--- /dev/null
+++ b/src/KeyLocator.js
@@ -0,0 +1,119 @@
+var CCNProtocolDTags = require('./CCNProtocolDTags').CCNProtocolDTags;
+
+var KeyLocatorType = function(){
+
+};
+
+
+exports.KeyLocatorType = {
+ NAME:1,
+ KEY:2,
+ CERTIFICATE:3
+};
+
+exports.KeyLocatorType = KeyLocatorType;
+
+var KeyLocator = function KeyLocator(_Input,_Type){
+
+ //this.KeyName = _KeyName;
+ //this.PublicKey = _PublicKey;
+ //this.Certificate = _Certificate;
+
+ 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;
+ }
+
+};
+
+exports.KeyLocator = KeyLocator;
+
+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, SHOULDN'T be like that
+ //this.Key = CryptoUtil.getPublicKey(encodedKey);
+
+ this.PublicKey = encodedKey;
+
+
+ } catch (e) {
+ console.log("Cannot parse stored key: error: " + e);
+ throw new ContentDecodingException("Cannot parse key: ", e);
+ }
+
+ if (null == 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) {
+ /*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.getEncoded() );
+
+ } 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) {
+ 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/src/KeyName.js b/src/KeyName.js
new file mode 100644
index 0000000..d534944
--- /dev/null
+++ b/src/KeyName.js
@@ -0,0 +1,50 @@
+var CCNProtocolDTags = require('./CCNProtocolDTags').CCNProtocolDTags;
+
+
+var KeyName = function KeyName() {
+
+
+ this.ContentName = this.ContentName;//ContentName
+ this.PublisherID =this.PublisherID;//PublisherID
+
+};
+
+exports.KeyName = KeyName;
+
+KeyName.prototype.decode=function( decoder){
+
+
+ decoder.readStartElement(this.getElementLabel());
+
+ this.ContentName = new ContentName();
+ this.ContentName.decode(decoder);
+
+ if (PublisherID.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/src/PublisherID.js b/src/PublisherID.js
new file mode 100644
index 0000000..26009da
--- /dev/null
+++ b/src/PublisherID.js
@@ -0,0 +1,76 @@
+var CCNProtocolDTags = require('./CCNProtocolDTags').CCNProtocolDTags;
+
+
+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;
+}; exports.PublisherType = PublisherType;
+
+PublisherType.prototype.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;
+
+
+ this.PublisherID = generatePublicKeyDigest(key);//ByteArray
+ //CryptoUtil.generateKeyID(PUBLISHER_ID_DIGEST_ALGORITHM, key);
+ this.PublisherType = isIssuer ? PublisherType.ISSUER_KEY : PublisherType.KEY;//publisher Type
+
+};
+
+exports.PublisherID = PublisherID;
+
+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 (!this.PublisherType.isTypeTagVal(nextTag)) {
+ throw new Exception("Invalid publisher ID, got unexpected type: " + nextTag);
+ }
+ this.PublisherID = decoder.readBinaryElement(nextTag);
+ if (null == _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);
+};
+
+PublisherID.prototype.getElementLabel = function() {
+ return this.PublisherType.Tag;
+};
+
+
+PublisherID.prototype.validate = function(){
+ return ((null != id() && (null != type())));
+};
+
+
+
diff --git a/src/PublisherPublicKeyDigest.js b/src/PublisherPublicKeyDigest.js
new file mode 100644
index 0000000..3d3987a
--- /dev/null
+++ b/src/PublisherPublicKeyDigest.js
@@ -0,0 +1,38 @@
+
+var PublisherID = require('./PublisherID').PublisherID;
+var CCNProtocolDTags = require('./CCNProtocolDTags').CCNProtocolDTags;
+
+var PublisherPublicKeyDigest = function PublisherPublicKeyDigest(_pkd){
+
+ if( typeof _pkd == "ByteArray") this.PublisherPublicKeyDigest = _pkd; // Byte Array
+ else if( typeof _pkd == "PublicKey") ;//TODO...
+
+};
+
+exports.PublisherPublicKeyDigest = PublisherPublicKeyDigest;
+
+
+PublisherPublicKeyDigest.prototype.decode = function( decoder) {
+
+ this.PublisherPublicKeyDigest = decoder.readBinaryElement(this.getElementLabel());
+ if (null == this.PublisherPublicKeyDigest) {
+ throw new Exception("Cannot parse publisher key digest.");
+ }
+ if (this.PublisherPublicKeyDigest.length != PublisherID.PUBLISHER_ID_LEN) {
+
+ this.PublisherPublicKeyDigest = new PublisherPublicKeyDigest(this.PublisherPublicKeyDigest).PublisherKeyDigest;
+ }
+ };
+
+PublisherPublicKeyDigest.prototype.encode= function( encoder) {
+ if (!this.validate()) {
+ throw new Exception("Cannot encode : field values missing.");
+ }
+ 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/src/Signature.js b/src/Signature.js
new file mode 100644
index 0000000..d4c3fa4
--- /dev/null
+++ b/src/Signature.js
@@ -0,0 +1,58 @@
+var CCNProtocolDTags = require('./CCNProtocolDTags').CCNProtocolDTags;
+
+
+var Signature = function Signature(_Witness,_Signature,_DigestAlgorithm) {
+
+ this.Witness = _Witness;//byte [] _witness;
+ this.Signature = _Signature;//byte [] _signature;
+ this.DigestAlgorithm = _DigestAlgorithm//String _digestAlgorithm;
+};
+
+exports.Signature = Signature;
+
+
+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();
+
+};
+
+
+exports.Signature = Signature;
+
+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/src/SignedInfo.js b/src/SignedInfo.js
new file mode 100644
index 0000000..14b72ef
--- /dev/null
+++ b/src/SignedInfo.js
@@ -0,0 +1,106 @@
+var CCNProtocolDTags = require('./CCNProtocolDTags').CCNProtocolDTags;
+
+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
+
+};
+
+//exports.SignedInfo.Working;
+
+
+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 valueToType
+
+ this.Type = valueToType(binType);
+ 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) {
+
+ 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/src/encoding/BinaryXMLCodec.js b/src/encoding/BinaryXMLCodec.js
new file mode 100644
index 0000000..077c7e2
--- /dev/null
+++ b/src/encoding/BinaryXMLCodec.js
@@ -0,0 +1,135 @@
+
+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 = 0x0000007FFL;
+var bits_18 = 0x00003FFFFL;
+var bits_32 = 0x0FFFFFFFFL;
+
+
+var TypeAndVal = function TypeAndVal(_type,_val) {
+ this.type = _type;
+ this.val = _val;
+
+};
+exports.TypeAndVal = TypeAndVal;
+
+var BinaryXMLCodec = function BinaryXMLCodec(){
+
+ this.CODEC_NAME = "Binary";
+
+
+
+};
+
+exports.BinaryXMLCodec = BinaryXMLCodec;
+
+
+
+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 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;;
+
+ 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.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);
+};
+
+//TODO
\ No newline at end of file
diff --git a/src/encoding/BinaryXMLDecoder.js b/src/encoding/BinaryXMLDecoder.js
new file mode 100644
index 0000000..4a8b1c4
--- /dev/null
+++ b/src/encoding/BinaryXMLDecoder.js
@@ -0,0 +1,89 @@
+var MARK_LEN=512;
+var DEBUG_MAX_LEN = 32768;
+
+var BinaryXMLDecoder = new BinaryXMLDecoder(_Istream){
+ this.Istream = _Istream;
+
+};
+
+
+BinaryXMLDecoder.prototype.readStartElement =function(
+ //String
+ startTag,
+ //TreeMap<String, String>
+ attributes) {
+
+ try {
+ BinaryXMLCodec.TypeAndVal tv = BinaryXMLCodec.decodeTypeAndVal(this.Istream);
+
+ if (null == tv) {
+ throw new Exception("Expected start element: " + startTag + " got something not a tag.");
+ }
+
+ String decodedTag = null;
+
+ if (tv.type() == BinaryXMLCodec.XML_TAG) {
+
+ decodedTag = BinaryXMLCodec.decodeUString(this.Istream, tv.val()+1);
+
+ } else if (tv.type() == BinaryXMLCodec.XML_DTAG) {
+ decodedTag = tagToString(tv.val());
+ }
+
+ if ((null == decodedTag) || (!decodedTag.equals(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 {
+
+ BinaryXMLCodec.TypeAndVal nextTV = BinaryXMLCodec.peekTypeAndVal(_istream);
+
+ while ((null != nextTV) && ((BinaryXMLCodec.XML_ATTR == nextTV.type()) ||
+ (BinaryXMLCodec.XML_DATTR == nextTV.type()))) {
+
+ BinaryXMLCodec.TypeAndVal thisTV = BinaryXMLCodec.decodeTypeAndVal(this.Istream);
+
+ var attributeName = null;
+ if (BinaryXMLCodec.XML_ATTR == thisTV.type()) {
+
+ attributeName = BinaryXMLCodec.decodeUString(_istream, thisTV.val()+1);
+
+ } else if (BinaryXMLCodec.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 = BinaryXMLCodec.decodeUString(_istream);
+
+ attributes.put(attributeName, attributeValue);
+
+ nextTV = BinaryXMLCodec.peekTypeAndVal(_istream);
+ }
+
+ } catch ( e) {
+
+ throw new ContentDecodingException("readStartElement", e);
+ }
+};
+
+//TODO
\ No newline at end of file
diff --git a/src/encoding/BinaryXMLEncoder.js b/src/encoding/BinaryXMLEncoder.js
new file mode 100644
index 0000000..7ccf3b4
--- /dev/null
+++ b/src/encoding/BinaryXMLEncoder.js
@@ -0,0 +1,31 @@
+
+var BinaryXMLEncoder = function BinaryXMLEncoder(){
+
+BinaryXMLEncoder.prototype.writeStartElement = function(
+ //String
+ tag,
+ //TreeMap<String,String>
+ attributes){
+
+}
+ try {
+ var dictionaryVal = stringToTag(tag);
+
+ if (null == dictionaryVal) {
+ BinaryXMLCodec.encodeUString(_ostream, tag, BinaryXMLCodec.XML_TAG);
+
+ } else {
+ BinaryXMLCodec.encodeTypeAndVal(BinaryXMLCodec.XML_DTAG, dictionaryVal, _ostream);
+ }
+
+ if (null != attributes) {
+ writeAttributes(attributes);
+ }
+
+ } catch (e) {
+ throw new Exception(e);
+ }
+};
+
+
+//TODO
\ No newline at end of file
diff --git a/src/encoding/TextXMLCodec.js b/src/encoding/TextXMLCodec.js
new file mode 100644
index 0000000..ea64188
--- /dev/null
+++ b/src/encoding/TextXMLCodec.js
@@ -0,0 +1 @@
+//TODO
\ No newline at end of file
diff --git a/src/encoding/TextXMLDecoder.js b/src/encoding/TextXMLDecoder.js
new file mode 100644
index 0000000..ea64188
--- /dev/null
+++ b/src/encoding/TextXMLDecoder.js
@@ -0,0 +1 @@
+//TODO
\ No newline at end of file
diff --git a/src/encoding/TextXMLEncoder.js b/src/encoding/TextXMLEncoder.js
new file mode 100644
index 0000000..ea64188
--- /dev/null
+++ b/src/encoding/TextXMLEncoder.js
@@ -0,0 +1 @@
+//TODO
\ No newline at end of file