/**
* This class represents an NDN Data MetaInfo object.
* Copyright (C) 2014-2015 Regents of the University of California.
* @author: Meki Cheraoui
* @author: Jeff Thompson <[email protected]>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* A copy of the GNU Lesser General Public License is in the file COPYING.
*/
var BinaryXMLEncoder = require('./encoding/binary-xml-encoder.js').BinaryXMLEncoder;
var BinaryXMLDecoder = require('./encoding/binary-xml-decoder.js').BinaryXMLDecoder;
var Blob = require('./util/blob.js').Blob;
var NDNProtocolDTags = require('./util/ndn-protoco-id-tags.js').NDNProtocolDTags;
var KeyLocator = require('./key-locator.js').KeyLocator;
var KeyLocatorType = require('./key-locator.js').KeyLocatorType;
var Name = require('./name.js').Name;
var PublisherPublicKeyDigest = require('./publisher-public-key-digest.js').PublisherPublicKeyDigest;
var NDNTime = require('./util/ndn-time.js').NDNTime;
var globalKeyManager = require('./security/key-manager.js').globalKeyManager;
var WireFormat = require('./encoding/wire-format.js').WireFormat;
var LOG = require('./log.js').Log.LOG;
var ContentType = {
BLOB:0,
// ContentType DATA is deprecated. Use ContentType.BLOB .
DATA:0,
LINK:1,
KEY: 2,
// ContentType ENCR, GONE and NACK are not supported in NDN-TLV encoding and are deprecated.
ENCR:3,
GONE:4,
NACK:5
};
exports.ContentType = ContentType;
/**
* Create a new MetaInfo with the optional values.
* @constructor
*/
var MetaInfo = function MetaInfo(publisherOrMetaInfo, timestamp, type, locator, freshnessSeconds, finalBlockId, skipSetFields)
{
if (typeof publisherOrMetaInfo === 'object' &&
publisherOrMetaInfo instanceof MetaInfo) {
// Copy values.
var metaInfo = publisherOrMetaInfo;
this.publisher_ = metaInfo.publisher_;
this.timestamp_ = metaInfo.timestamp; // NDNTime // deprecated
this.type_ = metaInfo.type_;
this.locator_ = metaInfo.locator_ == null ?
new KeyLocator() : new KeyLocator(metaInfo.locator_);
this.freshnessPeriod_ = metaInfo.freshnessPeriod_;
this.finalBlockId_ = metaInfo.finalBlockId_;
}
else {
this.publisher = publisherOrMetaInfo; // deprecated
this.timestamp = timestamp; // NDNTime // deprecated
this.type = type == null || type < 0 ? ContentType.BLOB : type;
// The KeyLocator in MetaInfo is deprecated. Use the one in the Signature.
this.locator = locator == null ? new KeyLocator() : new KeyLocator(locator);
this.freshnessSeconds = freshnessSeconds; // deprecated
this.finalBlockID = finalBlockId; // byte array // deprecated
if (!skipSetFields) {
// Temporarily set ENABLE_NDNX so that setFields doesn't throw.
var saveEnableNdnx = WireFormat.ENABLE_NDNX;
try {
WireFormat.ENABLE_NDNX = true;
this.setFields();
}
finally {
WireFormat.ENABLE_NDNX = saveEnableNdnx;
}
}
}
this.changeCount_ = 0;
};
exports.MetaInfo = MetaInfo;
/**
* Get the content type.
* @returns {number} The content type as an int from ContentType.
*/
MetaInfo.prototype.getType = function()
{
return this.type_;
};
/**
* Get the freshness period.
* @returns {number} The freshness period in milliseconds, or null if not
* specified.
*/
MetaInfo.prototype.getFreshnessPeriod = function()
{
return this.freshnessPeriod_;
};
/**
* Get the final block ID.
* @returns {Name.Component} The final block ID as a Name.Component. If the
* Name.Component getValue().size() is 0, then the final block ID is not specified.
*/
MetaInfo.prototype.getFinalBlockId = function()
{
return this.finalBlockId_;
};
/**
* @deprecated Use getFinalBlockId.
*/
MetaInfo.prototype.getFinalBlockID = function()
{
return this.getFinalBlockId();
};
/**
* @deprecated Use getFinalBlockId. This method returns a Buffer which is the former
* behavior of getFinalBlockId, and should only be used while updating your code.
*/
MetaInfo.prototype.getFinalBlockIDAsBuffer = function()
{
return this.finalBlockId_.getValue().buf();
};
/**
* Set the content type.
* @param {number} type The content type as an int from ContentType. If null,
* this uses ContentType.BLOB.
*/
MetaInfo.prototype.setType = function(type)
{
this.type_ = type == null || type < 0 ? ContentType.BLOB : type;
++this.changeCount_;
};
/**
* Set the freshness period.
* @param {type} freshnessPeriod The freshness period in milliseconds, or null
* for not specified.
*/
MetaInfo.prototype.setFreshnessPeriod = function(freshnessPeriod)
{
// Use attribute freshnessSeconds for backwards compatibility.
if (freshnessPeriod == null || freshnessPeriod < 0)
this.freshnessPeriod_ = null;
else
this.freshnessPeriod_ = freshnessPeriod;
++this.changeCount_;
};
MetaInfo.prototype.setFinalBlockId = function(finalBlockId)
{
this.finalBlockId_ = typeof finalBlockId === 'object' &&
finalBlockId instanceof Name.Component ?
finalBlockId : new Name.Component(finalBlockId);
++this.changeCount_;
};
/**
* @deprecated Use setFinalBlockId.
*/
MetaInfo.prototype.setFinalBlockID = function(finalBlockId)
{
this.setFinalBlockId(finalBlockId);
};
/**
* @deprecated This sets fields for NDNx signing. Use KeyChain.
*/
MetaInfo.prototype.setFields = function()
{
if (!WireFormat.ENABLE_NDNX)
throw new Error
("Signing with NDNx-style keys is deprecated. To enable while you upgrade your code to use KeyChain.sign, set WireFormat.ENABLE_NDNX = true");
var key = globalKeyManager.getKey();
this.publisher = new PublisherPublicKeyDigest(key.getKeyID());
var d = new Date();
var time = d.getTime();
this.timestamp = new NDNTime(time);
if (LOG > 4) console.log('TIME msec is');
if (LOG > 4) console.log(this.timestamp.msec);
//DATA
this.type = ContentType.BLOB;
if (LOG > 4) console.log('PUBLIC KEY TO WRITE TO DATA PACKET IS ');
if (LOG > 4) console.log(key.publicToDER().toString('hex'));
this.locator = new KeyLocator(key.getKeyID(), KeyLocatorType.KEY_LOCATOR_DIGEST);
++this.changeCount_;
};
MetaInfo.prototype.from_ndnb = function(decoder)
{
decoder.readElementStartDTag(this.getElementLabel());
if (decoder.peekDTag(NDNProtocolDTags.PublisherPublicKeyDigest)) {
if (LOG > 4) console.log('DECODING PUBLISHER KEY');
this.publisher = new PublisherPublicKeyDigest();
this.publisher.from_ndnb(decoder);
}
if (decoder.peekDTag(NDNProtocolDTags.Timestamp)) {
if (LOG > 4) console.log('DECODING TIMESTAMP');
this.timestamp = decoder.readDateTimeDTagElement(NDNProtocolDTags.Timestamp);
}
if (decoder.peekDTag(NDNProtocolDTags.Type)) {
var binType = decoder.readBinaryDTagElement(NDNProtocolDTags.Type);
if (LOG > 4) console.log('Binary Type of of Signed Info is '+binType);
this.type = binType;
//TODO Implement type of Key Reading
if (null == this.type)
throw new Error("Cannot parse signedInfo type: bytes.");
}
else
this.type = ContentType.DATA; // default
if (decoder.peekDTag(NDNProtocolDTags.FreshnessSeconds)) {
this.freshnessSeconds = decoder.readIntegerDTagElement(NDNProtocolDTags.FreshnessSeconds);
if (LOG > 4) console.log('FRESHNESS IN SECONDS IS '+ this.freshnessSeconds);
}
if (decoder.peekDTag(NDNProtocolDTags.FinalBlockID)) {
if (LOG > 4) console.log('DECODING FINAL BLOCKID');
this.finalBlockID = decoder.readBinaryDTagElement(NDNProtocolDTags.FinalBlockID);
}
if (decoder.peekDTag(NDNProtocolDTags.KeyLocator)) {
if (LOG > 4) console.log('DECODING KEY LOCATOR');
this.locator = new KeyLocator();
this.locator.from_ndnb(decoder);
}
decoder.readElementClose();
++this.changeCount_;
};
/**
* Encode this MetaInfo in ndnb, using the given keyLocator instead of the
* locator in this object.
* @param {BinaryXMLEncoder} encoder The encoder.
* @param {KeyLocator} keyLocator The key locator to use (from
* Data.getSignatureOrMetaInfoKeyLocator).
*/
MetaInfo.prototype.to_ndnb = function(encoder, keyLocator) {
if (!this.validate())
throw new Error("Cannot encode : field values missing.");
encoder.writeElementStartDTag(this.getElementLabel());
if (null != this.publisher) {
// We have a publisherPublicKeyDigest, so use it.
if (LOG > 3) console.log('ENCODING PUBLISHER KEY' + this.publisher.publisherPublicKeyDigest);
this.publisher.to_ndnb(encoder);
}
else {
if (null != keyLocator &&
keyLocator.getType() == KeyLocatorType.KEY_LOCATOR_DIGEST &&
!keyLocator.getKeyData().isNull() &&
keyLocator.getKeyData().size() > 0)
// We have a TLV-style KEY_LOCATOR_DIGEST, so encode as the
// publisherPublicKeyDigest.
encoder.writeDTagElement
(NDNProtocolDTags.PublisherPublicKeyDigest, keyLocator.getKeyData().buf());
}
if (null != this.timestamp)
encoder.writeDateTimeDTagElement(NDNProtocolDTags.Timestamp, this.timestamp);
if (null != this.type && this.type != 0)
encoder.writeDTagElement(NDNProtocolDTags.type, this.type);
if (null != this.freshnessSeconds)
encoder.writeDTagElement(NDNProtocolDTags.FreshnessSeconds, this.freshnessSeconds);
if (null != this.finalBlockID)
encoder.writeDTagElement(NDNProtocolDTags.FinalBlockID, this.finalBlockID);
if (null != keyLocator)
keyLocator.to_ndnb(encoder);
encoder.writeElementClose();
};
MetaInfo.prototype.valueToType = function()
{
return null;
};
MetaInfo.prototype.getElementLabel = function() {
return NDNProtocolDTags.SignedInfo;
};
/**
* @@deprecated This is only used with to_ndnb.
*/
MetaInfo.prototype.validate = function()
{
// We don't do partial matches any more, even though encoder/decoder
// is still pretty generous.
if (null == this.timestamp_)
return false;
return true;
};
/**
* Get the change count, which is incremented each time this object is changed.
* @returns {number} The change count.
*/
MetaInfo.prototype.getChangeCount = function()
{
return this.changeCount_;
};
// Define properties so we can change member variable types and implement changeCount_.
Object.defineProperty(MetaInfo.prototype, "type",
{ get: function() { return this.getType(); },
set: function(val) { this.setType(val); } });
/**
* @deprecated Use getFreshnessPeriod and setFreshnessPeriod.
*/
Object.defineProperty(MetaInfo.prototype, "freshnessSeconds",
{ get: function() {
if (this.freshnessPeriod_ == null || this.freshnessPeriod_ < 0)
return null;
else
// Convert from milliseconds.
return this.freshnessPeriod_ / 1000.0;
},
set: function(val) {
if (val == null || val < 0)
this.freshnessPeriod_ = null;
else
// Convert to milliseconds.
this.freshnessPeriod_ = val * 1000.0;
++this.changeCount_;
} });
/**
* @deprecated Use KeyLocator where keyLocatorType is KEY_LOCATOR_DIGEST.
*/
Object.defineProperty(MetaInfo.prototype, "publisher",
{ get: function() { return this.publisher_; },
set: function(val) { this.publisher_ = val; ++this.changeCount_; } });
/**
* @deprecated Use getFinalBlockId and setFinalBlockId.
*/
Object.defineProperty(MetaInfo.prototype, "finalBlockID",
{ get: function() { return this.getFinalBlockIDAsBuffer(); },
set: function(val) { this.setFinalBlockId(val); } });
/**
* @deprecated
*/
Object.defineProperty(MetaInfo.prototype, "timestamp",
{ get: function() { return this.timestamp_; },
set: function(val) { this.timestamp_ = val; ++this.changeCount_; } });
/**
* @deprecated
*/
Object.defineProperty(MetaInfo.prototype, "locator",
{ get: function() { return this.locator_; },
set: function(val) { this.locator_ = val; ++this.changeCount_; } });
/**
* @deprecated Use new MetaInfo.
*/
var SignedInfo = function SignedInfo(publisherOrMetaInfo, timestamp, type, locator, freshnessSeconds, finalBlockId)
{
// Call the base constructor.
MetaInfo.call(this, publisherOrMetaInfo, timestamp, type, locator, freshnessSeconds, finalBlockId);
}
// Set skipSetFields true since we only need the prototype functions.
SignedInfo.prototype = new MetaInfo(null, null, null, null, null, null, true);
exports.SignedInfo = SignedInfo;