// Domain Public by Eric Wendelin http://www.eriwen.com/ (2008)
//                  Luke Smith http://lucassmith.name/ (2008)
//                  Loic Dachary <loic@dachary.org> (2008)
//                  Johan Euphrosine <proppy@aminche.com> (2008)
//                  Oyvind Sean Kinsey http://kinsey.no/blog (2010)
//                  Victor Homyakov <victor-homyakov@users.sourceforge.net> (2010)
/*global module, exports, define, ActiveXObject*/
(function(global, factory) {
    if (typeof exports === 'object') {
        // Node
        module.exports.printStackTrace = factory();
    } else if (typeof define === 'function' && define.amd) {
        // AMD
        define(factory);
    } else {
        // Browser globals
        global.printStackTrace = factory();
    }
}(this, function() {
    /**
     * Main function giving a function stack trace with a forced or passed in Error
     *
     * @cfg {Error} e The error to create a stacktrace from (optional)
     * @cfg {Boolean} guess If we should try to resolve the names of anonymous functions
     * @return {Array} of Strings with functions, lines, files, and arguments where possible
     */
    function printStackTrace(options) {
        options = options || {guess: true};
        var ex = options.e || null, guess = !!options.guess, mode = options.mode || null;
        var p = new printStackTrace.implementation(), result = p.run(ex, mode);
        return (guess) ? p.guessAnonymousFunctions(result) : result;
    }

    printStackTrace.implementation = function() {
    };

    printStackTrace.implementation.prototype = {
        /**
         * @param {Error} [ex] The error to create a stacktrace from (optional)
         * @param {String} [mode] Forced mode (optional, mostly for unit tests)
         */
        run: function(ex, mode) {
            ex = ex || this.createException();
            mode = mode || this.mode(ex);
            if (mode === 'other') {
                return this.other(arguments.callee);
            } else {
                return this[mode](ex);
            }
        },

        createException: function() {
            try {
                this.undef();
            } catch (e) {
                return e;
            }
        },

        /**
         * Mode could differ for different exception, e.g.
         * exceptions in Chrome may or may not have arguments or stack.
         *
         * @return {String} mode of operation for the exception
         */
        mode: function(e) {
            if (typeof window !== 'undefined' && window.navigator.userAgent.indexOf('PhantomJS') > -1) {
                return 'phantomjs';
            }

            if (e['arguments'] && e.stack) {
                return 'chrome';
            }

            if (e.stack && e.sourceURL) {
                return 'safari';
            }

            if (e.stack && e.number) {
                return 'ie';
            }

            if (e.stack && e.fileName) {
                return 'firefox';
            }

            if (e.message && e['opera#sourceloc']) {
                // e.message.indexOf("Backtrace:") > -1 -> opera9
                // 'opera#sourceloc' in e -> opera9, opera10a
                // !e.stacktrace -> opera9
                if (!e.stacktrace) {
                    return 'opera9'; // use e.message
                }
                if (e.message.indexOf('\n') > -1 && e.message.split('\n').length > e.stacktrace.split('\n').length) {
                    // e.message may have more stack entries than e.stacktrace
                    return 'opera9'; // use e.message
                }
                return 'opera10a'; // use e.stacktrace
            }

            if (e.message && e.stack && e.stacktrace) {
                // e.stacktrace && e.stack -> opera10b
                if (e.stacktrace.indexOf("called from line") < 0) {
                    return 'opera10b'; // use e.stacktrace, format differs from 'opera10a'
                }
                // e.stacktrace && e.stack -> opera11
                return 'opera11'; // use e.stacktrace, format differs from 'opera10a', 'opera10b'
            }

            if (e.stack && !e.fileName) {
                // Chrome 27 does not have e.arguments as earlier versions,
                // but still does not have e.fileName as Firefox
                return 'chrome';
            }

            return 'other';
        },

        /**
         * Given a context, function name, and callback function, overwrite it so that it calls
         * printStackTrace() first with a callback and then runs the rest of the body.
         *
         * @param {Object} context of execution (e.g. window)
         * @param {String} functionName to instrument
         * @param {Function} callback function to call with a stack trace on invocation
         */
        instrumentFunction: function(context, functionName, callback) {
            context = context || window;
            var original = context[functionName];
            context[functionName] = function instrumented() {
                callback.call(this, printStackTrace().slice(4));
                return context[functionName]._instrumented.apply(this, arguments);
            };
            context[functionName]._instrumented = original;
        },

        /**
         * Given a context and function name of a function that has been
         * instrumented, revert the function to it's original (non-instrumented)
         * state.
         *
         * @param {Object} context of execution (e.g. window)
         * @param {String} functionName to de-instrument
         */
        deinstrumentFunction: function(context, functionName) {
            if (context[functionName].constructor === Function &&
                context[functionName]._instrumented &&
                context[functionName]._instrumented.constructor === Function) {
                context[functionName] = context[functionName]._instrumented;
            }
        },

        /**
         * Given an Error object, return a formatted Array based on Chrome's stack string.
         *
         * @param e - Error object to inspect
         * @return Array<String> of function calls, files and line numbers
         */
        chrome: function(e) {
            return (e.stack + '\n')
                .replace(/^[\s\S]+?\s+at\s+/, ' at ') // remove message
                .replace(/^\s+(at eval )?at\s+/gm, '') // remove 'at' and indentation
                .replace(/^([^\(]+?)([\n$])/gm, '{anonymous}() ($1)$2')
                .replace(/^Object.<anonymous>\s*\(([^\)]+)\)/gm, '{anonymous}() ($1)')
                .replace(/^(.+) \((.+)\)$/gm, '$1@$2')
                .split('\n')
                .slice(0, -1);
        },

        /**
         * Given an Error object, return a formatted Array based on Safari's stack string.
         *
         * @param e - Error object to inspect
         * @return Array<String> of function calls, files and line numbers
         */
        safari: function(e) {
            return e.stack.replace(/\[native code\]\n/m, '')
                .replace(/^(?=\w+Error\:).*$\n/m, '')
                .replace(/^@/gm, '{anonymous}()@')
                .split('\n');
        },

        /**
         * Given an Error object, return a formatted Array based on IE's stack string.
         *
         * @param e - Error object to inspect
         * @return Array<String> of function calls, files and line numbers
         */
        ie: function(e) {
            return e.stack
                .replace(/^\s*at\s+(.*)$/gm, '$1')
                .replace(/^Anonymous function\s+/gm, '{anonymous}() ')
                .replace(/^(.+)\s+\((.+)\)$/gm, '$1@$2')
                .split('\n')
                .slice(1);
        },

        /**
         * Given an Error object, return a formatted Array based on Firefox's stack string.
         *
         * @param e - Error object to inspect
         * @return Array<String> of function calls, files and line numbers
         */
        firefox: function(e) {
            return e.stack.replace(/(?:\n@:0)?\s+$/m, '')
                .replace(/^(?:\((\S*)\))?@/gm, '{anonymous}($1)@')
                .split('\n');
        },

        opera11: function(e) {
            var ANON = '{anonymous}', lineRE = /^.*line (\d+), column (\d+)(?: in (.+))? in (\S+):$/;
            var lines = e.stacktrace.split('\n'), result = [];

            for (var i = 0, len = lines.length; i < len; i += 2) {
                var match = lineRE.exec(lines[i]);
                if (match) {
                    var location = match[4] + ':' + match[1] + ':' + match[2];
                    var fnName = match[3] || "global code";
                    fnName = fnName.replace(/<anonymous function: (\S+)>/, "$1").replace(/<anonymous function>/, ANON);
                    result.push(fnName + '@' + location + ' -- ' + lines[i + 1].replace(/^\s+/, ''));
                }
            }

            return result;
        },

        opera10b: function(e) {
            // "<anonymous function: run>([arguments not available])@file://localhost/G:/js/stacktrace.js:27\n" +
            // "printStackTrace([arguments not available])@file://localhost/G:/js/stacktrace.js:18\n" +
            // "@file://localhost/G:/js/test/functional/testcase1.html:15"
            var lineRE = /^(.*)@(.+):(\d+)$/;
            var lines = e.stacktrace.split('\n'), result = [];

            for (var i = 0, len = lines.length; i < len; i++) {
                var match = lineRE.exec(lines[i]);
                if (match) {
                    var fnName = match[1] ? (match[1] + '()') : "global code";
                    result.push(fnName + '@' + match[2] + ':' + match[3]);
                }
            }

            return result;
        },

        /**
         * Given an Error object, return a formatted Array based on Opera 10's stacktrace string.
         *
         * @param e - Error object to inspect
         * @return Array<String> of function calls, files and line numbers
         */
        opera10a: function(e) {
            // "  Line 27 of linked script file://localhost/G:/js/stacktrace.js\n"
            // "  Line 11 of inline#1 script in file://localhost/G:/js/test/functional/testcase1.html: In function foo\n"
            var ANON = '{anonymous}', lineRE = /Line (\d+).*script (?:in )?(\S+)(?:: In function (\S+))?$/i;
            var lines = e.stacktrace.split('\n'), result = [];

            for (var i = 0, len = lines.length; i < len; i += 2) {
                var match = lineRE.exec(lines[i]);
                if (match) {
                    var fnName = match[3] || ANON;
                    result.push(fnName + '()@' + match[2] + ':' + match[1] + ' -- ' + lines[i + 1].replace(/^\s+/, ''));
                }
            }

            return result;
        },

        // Opera 7.x-9.2x only!
        opera9: function(e) {
            // "  Line 43 of linked script file://localhost/G:/js/stacktrace.js\n"
            // "  Line 7 of inline#1 script in file://localhost/G:/js/test/functional/testcase1.html\n"
            var ANON = '{anonymous}', lineRE = /Line (\d+).*script (?:in )?(\S+)/i;
            var lines = e.message.split('\n'), result = [];

            for (var i = 2, len = lines.length; i < len; i += 2) {
                var match = lineRE.exec(lines[i]);
                if (match) {
                    result.push(ANON + '()@' + match[2] + ':' + match[1] + ' -- ' + lines[i + 1].replace(/^\s+/, ''));
                }
            }

            return result;
        },

        phantomjs: function(e) {
            var ANON = '{anonymous}', lineRE = /(\S+) \((\S+)\)/i;
            var lines = e.stack.split('\n'), result = [];

            for (var i = 1, len = lines.length; i < len; i++) {
                lines[i] = lines[i].replace(/^\s+at\s+/gm, '');
                var match = lineRE.exec(lines[i]);
                if (match) {
                    result.push(match[1] + '()@' + match[2]);
                }
                else {
                    result.push(ANON + '()@' + lines[i]);
                }
            }

            return result;
        },

        // Safari 5-, IE 9-, and others
        other: function(curr) {
            var ANON = '{anonymous}', fnRE = /function(?:\s+([\w$]+))?\s*\(/, stack = [], fn, args, maxStackSize = 10;
            var slice = Array.prototype.slice;
            while (curr && stack.length < maxStackSize) {
                fn = fnRE.test(curr.toString()) ? RegExp.$1 || ANON : ANON;
                try {
                    args = slice.call(curr['arguments'] || []);
                } catch (e) {
                    args = ['Cannot access arguments: ' + e];
                }
                stack[stack.length] = fn + '(' + this.stringifyArguments(args) + ')';
                try {
                    curr = curr.caller;
                } catch (e) {
                    stack[stack.length] = 'Cannot access caller: ' + e;
                    break;
                }
            }
            return stack;
        },

        /**
         * Given arguments array as a String, substituting type names for non-string types.
         *
         * @param {Arguments,Array} args
         * @return {String} stringified arguments
         */
        stringifyArguments: function(args) {
            var result = [];
            var slice = Array.prototype.slice;
            for (var i = 0; i < args.length; ++i) {
                var arg = args[i];
                if (arg === undefined) {
                    result[i] = 'undefined';
                } else if (arg === null) {
                    result[i] = 'null';
                } else if (arg.constructor) {
                    // TODO constructor comparison does not work for iframes
                    if (arg.constructor === Array) {
                        if (arg.length < 3) {
                            result[i] = '[' + this.stringifyArguments(arg) + ']';
                        } else {
                            result[i] = '[' + this.stringifyArguments(slice.call(arg, 0, 1)) + '...' + this.stringifyArguments(slice.call(arg, -1)) + ']';
                        }
                    } else if (arg.constructor === Object) {
                        result[i] = '#object';
                    } else if (arg.constructor === Function) {
                        result[i] = '#function';
                    } else if (arg.constructor === String) {
                        result[i] = '"' + arg + '"';
                    } else if (arg.constructor === Number) {
                        result[i] = arg;
                    } else {
                        result[i] = '?';
                    }
                }
            }
            return result.join(',');
        },

        sourceCache: {},

        /**
         * @return {String} the text from a given URL
         */
        ajax: function(url) {
            var req = this.createXMLHTTPObject();
            if (req) {
                try {
                    req.open('GET', url, false);
                    //req.overrideMimeType('text/plain');
                    //req.overrideMimeType('text/javascript');
                    req.send(null);
                    //return req.status == 200 ? req.responseText : '';
                    return req.responseText;
                } catch (e) {
                }
            }
            return '';
        },

        /**
         * Try XHR methods in order and store XHR factory.
         *
         * @return {XMLHttpRequest} XHR function or equivalent
         */
        createXMLHTTPObject: function() {
            var xmlhttp, XMLHttpFactories = [
                function() {
                    return new XMLHttpRequest();
                }, function() {
                    return new ActiveXObject('Msxml2.XMLHTTP');
                }, function() {
                    return new ActiveXObject('Msxml3.XMLHTTP');
                }, function() {
                    return new ActiveXObject('Microsoft.XMLHTTP');
                }
            ];
            for (var i = 0; i < XMLHttpFactories.length; i++) {
                try {
                    xmlhttp = XMLHttpFactories[i]();
                    // Use memoization to cache the factory
                    this.createXMLHTTPObject = XMLHttpFactories[i];
                    return xmlhttp;
                } catch (e) {
                }
            }
        },

        /**
         * Given a URL, check if it is in the same domain (so we can get the source
         * via Ajax).
         *
         * @param url {String} source url
         * @return {Boolean} False if we need a cross-domain request
         */
        isSameDomain: function(url) {
            return typeof location !== "undefined" && url.indexOf(location.hostname) !== -1; // location may not be defined, e.g. when running from nodejs.
        },

        /**
         * Get source code from given URL if in the same domain.
         *
         * @param url {String} JS source URL
         * @return {Array} Array of source code lines
         */
        getSource: function(url) {
            // TODO reuse source from script tags?
            if (!(url in this.sourceCache)) {
                this.sourceCache[url] = this.ajax(url).split('\n');
            }
            return this.sourceCache[url];
        },

        guessAnonymousFunctions: function(stack) {
            for (var i = 0; i < stack.length; ++i) {
                var reStack = /\{anonymous\}\(.*\)@(.*)/,
                    reRef = /^(.*?)(?::(\d+))(?::(\d+))?(?: -- .+)?$/,
                    frame = stack[i], ref = reStack.exec(frame);

                if (ref) {
                    var m = reRef.exec(ref[1]);
                    if (m) { // If falsey, we did not get any file/line information
                        var file = m[1], lineno = m[2], charno = m[3] || 0;
                        if (file && this.isSameDomain(file) && lineno) {
                            var functionName = this.guessAnonymousFunction(file, lineno, charno);
                            stack[i] = frame.replace('{anonymous}', functionName);
                        }
                    }
                }
            }
            return stack;
        },

        guessAnonymousFunction: function(url, lineNo, charNo) {
            var ret;
            try {
                ret = this.findFunctionName(this.getSource(url), lineNo);
            } catch (e) {
                ret = 'getSource failed with url: ' + url + ', exception: ' + e.toString();
            }
            return ret;
        },

        findFunctionName: function(source, lineNo) {
            // FIXME findFunctionName fails for compressed source
            // (more than one function on the same line)
            // function {name}({args}) m[1]=name m[2]=args
            var reFunctionDeclaration = /function\s+([^(]*?)\s*\(([^)]*)\)/;
            // {name} = function ({args}) TODO args capture
            // /['"]?([0-9A-Za-z_]+)['"]?\s*[:=]\s*function(?:[^(]*)/
            var reFunctionExpression = /['"]?([$_A-Za-z][$_A-Za-z0-9]*)['"]?\s*[:=]\s*function\b/;
            // {name} = eval()
            var reFunctionEvaluation = /['"]?([$_A-Za-z][$_A-Za-z0-9]*)['"]?\s*[:=]\s*(?:eval|new Function)\b/;
            // Walk backwards in the source lines until we find
            // the line which matches one of the patterns above
            var code = "", line, maxLines = Math.min(lineNo, 20), m, commentPos;
            for (var i = 0; i < maxLines; ++i) {
                // lineNo is 1-based, source[] is 0-based
                line = source[lineNo - i - 1];
                commentPos = line.indexOf('//');
                if (commentPos >= 0) {
                    line = line.substr(0, commentPos);
                }
                // TODO check other types of comments? Commented code may lead to false positive
                if (line) {
                    code = line + code;
                    m = reFunctionExpression.exec(code);
                    if (m && m[1]) {
                        return m[1];
                    }
                    m = reFunctionDeclaration.exec(code);
                    if (m && m[1]) {
                        //return m[1] + "(" + (m[2] || "") + ")";
                        return m[1];
                    }
                    m = reFunctionEvaluation.exec(code);
                    if (m && m[1]) {
                        return m[1];
                    }
                }
            }
            return '(?)';
        }
    };

    return printStackTrace;
}));
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Ryan Bennett
 *
 * 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.
 */

// define a shim require function so that a node/browserify require calls dont cause errors when ndn-js is used via <script> tag

/** @ignore */
var ndn = ndn || {}
/** @ignore */
var exports = ndn;

/** @ignore */
var module = {}
/** @ignore */
function require(){return ndn;}
/**
 * Copyright (C) 2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

// This is included after stacktrace.js and browserify-require.js so that
// require().printStackTrace works.

exports.printStackTrace = printStackTrace;
/**
 * This module checks for the availability of various crypto.subtle api's at runtime,
 * exporting a function that returns the known availability of necessary NDN crypto apis
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Ryan Bennett <nomad.ry@gmail.com>
 *
 * 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.
 */

function DetectSubtleCrypto(){
  var use = false;
  var baselineSupport = (
                            (typeof crypto !== 'undefined' && crypto && crypto.subtle)
                            && (
                                (location.protocol === "https:" || "chrome-extension:" || "chrome:")
                                || (location.hostname === "localhost" || location.hostname === "127.0.0.1")
                               )
                        ) ? true : false ;
  if (baselineSupport) {
    var algo = { name: "RSASSA-PKCS1-v1_5", modulusLength: 2048, hash:{name:"SHA-256"}, publicExponent: new Uint8Array([0x01, 0x00, 0x01])};
    var keypair;
    //try to perform every RSA crypto operation we need, if everything works, set use = true
    crypto.subtle.generateKey(
      algo,
      true, //exportable;
      ["sign", "verify"]).then(function(key){
        keypair = key;
        return crypto.subtle.sign(algo, key.privateKey, new Uint8Array([1,2,3,4,5]));
      }).then(function(signature){
        return crypto.subtle.verify(algo, keypair.publicKey, signature, new Uint8Array([1,2,3,4,5]));
      }).then(function(verified){
        return crypto.subtle.exportKey("pkcs8",keypair.privateKey);
      }).then(function(pkcs8){
        return crypto.subtle.importKey("pkcs8", pkcs8, algo, true, ["sign"]);
      }).then(function(importedKey){
        return crypto.subtle.exportKey("spki", keypair.publicKey);
      }).then(function(spki){
        return crypto.subtle.importKey("spki", spki, algo, true, ["verify"]);
      }).then(function(importedKey){
        var testDigest = new Uint8Array([1,2,3,4,5]);
        return crypto.subtle.digest({name:"SHA-256"}, testDigest.buffer);
      }).then(function(result){
        use = true;
      }, function(err){
        console.log("DetectSubtleCrypto encountered error, not using crypto.subtle: ", err)
      });
  }
  return function useSubtleCrypto(){
    return use;
  }
}

var UseSubtleCrypto = DetectSubtleCrypto();

exports.UseSubtleCrypto = UseSubtleCrypto;
/*! CryptoJS v3.1.2 core-fix.js
 * code.google.com/p/crypto-js
 * (c) 2009-2013 by Jeff Mott. All rights reserved.
 * code.google.com/p/crypto-js/wiki/License
 * THIS IS FIX of 'core.js' to fix Hmac issue.
 * https://code.google.com/p/crypto-js/issues/detail?id=84
 * https://crypto-js.googlecode.com/svn-history/r667/branches/3.x/src/core.js
 */
/**
 * CryptoJS core components.
 */
var CryptoJS = CryptoJS || (function (Math, undefined) {
    /**
     * CryptoJS namespace.
     */
    var C = {};

    /**
     * Library namespace.
     */
    var C_lib = C.lib = {};

    /**
     * Base object for prototypal inheritance.
     */
    var Base = C_lib.Base = (function () {
        function F() {}

        return {
            /**
             * Creates a new object that inherits from this object.
             *
             * @param {Object} overrides Properties to copy into the new object.
             *
             * @return {Object} The new object.
             *
             * @static
             *
             * @example
             *
             *     var MyType = CryptoJS.lib.Base.extend({
             *         field: 'value',
             *
             *         method: function () {
             *         }
             *     });
             */
            extend: function (overrides) {
                // Spawn
                F.prototype = this;
                var subtype = new F();

                // Augment
                if (overrides) {
                    subtype.mixIn(overrides);
                }

                // Create default initializer
                if (!subtype.hasOwnProperty('init')) {
                    subtype.init = function () {
                        subtype.$super.init.apply(this, arguments);
                    };
                }

                // Initializer's prototype is the subtype object
                subtype.init.prototype = subtype;

                // Reference supertype
                subtype.$super = this;

                return subtype;
            },

            /**
             * Extends this object and runs the init method.
             * Arguments to create() will be passed to init().
             *
             * @return {Object} The new object.
             *
             * @static
             *
             * @example
             *
             *     var instance = MyType.create();
             */
            create: function () {
                var instance = this.extend();
                instance.init.apply(instance, arguments);

                return instance;
            },

            /**
             * Initializes a newly created object.
             * Override this method to add some logic when your objects are created.
             *
             * @example
             *
             *     var MyType = CryptoJS.lib.Base.extend({
             *         init: function () {
             *             // ...
             *         }
             *     });
             */
            init: function () {
            },

            /**
             * Copies properties into this object.
             *
             * @param {Object} properties The properties to mix in.
             *
             * @example
             *
             *     MyType.mixIn({
             *         field: 'value'
             *     });
             */
            mixIn: function (properties) {
                for (var propertyName in properties) {
                    if (properties.hasOwnProperty(propertyName)) {
                        this[propertyName] = properties[propertyName];
                    }
                }

                // IE won't copy toString using the loop above
                if (properties.hasOwnProperty('toString')) {
                    this.toString = properties.toString;
                }
            },

            /**
             * Creates a copy of this object.
             *
             * @return {Object} The clone.
             *
             * @example
             *
             *     var clone = instance.clone();
             */
            clone: function () {
                return this.init.prototype.extend(this);
            }
        };
    }());

    /**
     * An array of 32-bit words.
     *
     * @property {Array} words The array of 32-bit words.
     * @property {number} sigBytes The number of significant bytes in this word array.
     */
    var WordArray = C_lib.WordArray = Base.extend({
        /**
         * Initializes a newly created word array.
         *
         * @param {Array} words (Optional) An array of 32-bit words.
         * @param {number} sigBytes (Optional) The number of significant bytes in the words.
         *
         * @example
         *
         *     var wordArray = CryptoJS.lib.WordArray.create();
         *     var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]);
         *     var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6);
         */
        init: function (words, sigBytes) {
            words = this.words = words || [];

            if (sigBytes != undefined) {
                this.sigBytes = sigBytes;
            } else {
                this.sigBytes = words.length * 4;
            }
        },

        /**
         * Converts this word array to a string.
         *
         * @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex
         *
         * @return {string} The stringified word array.
         *
         * @example
         *
         *     var string = wordArray + '';
         *     var string = wordArray.toString();
         *     var string = wordArray.toString(CryptoJS.enc.Utf8);
         */
        toString: function (encoder) {
            return (encoder || Hex).stringify(this);
        },

        /**
         * Concatenates a word array to this word array.
         *
         * @param {WordArray} wordArray The word array to append.
         *
         * @return {WordArray} This word array.
         *
         * @example
         *
         *     wordArray1.concat(wordArray2);
         */
        concat: function (wordArray) {
            // Shortcuts
            var thisWords = this.words;
            var thatWords = wordArray.words;
            var thisSigBytes = this.sigBytes;
            var thatSigBytes = wordArray.sigBytes;

            // Clamp excess bits
            this.clamp();

            // Concat
            if (thisSigBytes % 4) {
                // Copy one byte at a time
                for (var i = 0; i < thatSigBytes; i++) {
                    var thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
                    thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8);
                }
            } else {
                // Copy one word at a time
                for (var i = 0; i < thatSigBytes; i += 4) {
                    thisWords[(thisSigBytes + i) >>> 2] = thatWords[i >>> 2];
                }
            }
            this.sigBytes += thatSigBytes;

            // Chainable
            return this;
        },

        /**
         * Removes insignificant bits.
         *
         * @example
         *
         *     wordArray.clamp();
         */
        clamp: function () {
            // Shortcuts
            var words = this.words;
            var sigBytes = this.sigBytes;

            // Clamp
            words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8);
            words.length = Math.ceil(sigBytes / 4);
        },

        /**
         * Creates a copy of this word array.
         *
         * @return {WordArray} The clone.
         *
         * @example
         *
         *     var clone = wordArray.clone();
         */
        clone: function () {
            var clone = Base.clone.call(this);
            clone.words = this.words.slice(0);

            return clone;
        },

        /**
         * Creates a word array filled with random bytes.
         *
         * @param {number} nBytes The number of random bytes to generate.
         *
         * @return {WordArray} The random word array.
         *
         * @static
         *
         * @example
         *
         *     var wordArray = CryptoJS.lib.WordArray.random(16);
         */
        random: function (nBytes) {
            var words = [];
            for (var i = 0; i < nBytes; i += 4) {
                words.push((Math.random() * 0x100000000) | 0);
            }

            return new WordArray.init(words, nBytes);
        }
    });

    /**
     * Encoder namespace.
     */
    var C_enc = C.enc = {};

    /**
     * Hex encoding strategy.
     */
    var Hex = C_enc.Hex = {
        /**
         * Converts a word array to a hex string.
         *
         * @param {WordArray} wordArray The word array.
         *
         * @return {string} The hex string.
         *
         * @static
         *
         * @example
         *
         *     var hexString = CryptoJS.enc.Hex.stringify(wordArray);
         */
        stringify: function (wordArray) {
            // Shortcuts
            var words = wordArray.words;
            var sigBytes = wordArray.sigBytes;

            // Convert
            var hexChars = [];
            for (var i = 0; i < sigBytes; i++) {
                var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
                hexChars.push((bite >>> 4).toString(16));
                hexChars.push((bite & 0x0f).toString(16));
            }

            return hexChars.join('');
        },

        /**
         * Converts a hex string to a word array.
         *
         * @param {string} hexStr The hex string.
         *
         * @return {WordArray} The word array.
         *
         * @static
         *
         * @example
         *
         *     var wordArray = CryptoJS.enc.Hex.parse(hexString);
         */
        parse: function (hexStr) {
            // Shortcut
            var hexStrLength = hexStr.length;

            // Convert
            var words = [];
            for (var i = 0; i < hexStrLength; i += 2) {
                words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4);
            }

            return new WordArray.init(words, hexStrLength / 2);
        }
    };

    /**
     * Latin1 encoding strategy.
     */
    var Latin1 = C_enc.Latin1 = {
        /**
         * Converts a word array to a Latin1 string.
         *
         * @param {WordArray} wordArray The word array.
         *
         * @return {string} The Latin1 string.
         *
         * @static
         *
         * @example
         *
         *     var latin1String = CryptoJS.enc.Latin1.stringify(wordArray);
         */
        stringify: function (wordArray) {
            // Shortcuts
            var words = wordArray.words;
            var sigBytes = wordArray.sigBytes;

            // Convert
            var latin1Chars = [];
            for (var i = 0; i < sigBytes; i++) {
                var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
                latin1Chars.push(String.fromCharCode(bite));
            }

            return latin1Chars.join('');
        },

        /**
         * Converts a Latin1 string to a word array.
         *
         * @param {string} latin1Str The Latin1 string.
         *
         * @return {WordArray} The word array.
         *
         * @static
         *
         * @example
         *
         *     var wordArray = CryptoJS.enc.Latin1.parse(latin1String);
         */
        parse: function (latin1Str) {
            // Shortcut
            var latin1StrLength = latin1Str.length;

            // Convert
            var words = [];
            for (var i = 0; i < latin1StrLength; i++) {
                words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8);
            }

            return new WordArray.init(words, latin1StrLength);
        }
    };

    /**
     * UTF-8 encoding strategy.
     */
    var Utf8 = C_enc.Utf8 = {
        /**
         * Converts a word array to a UTF-8 string.
         *
         * @param {WordArray} wordArray The word array.
         *
         * @return {string} The UTF-8 string.
         *
         * @static
         *
         * @example
         *
         *     var utf8String = CryptoJS.enc.Utf8.stringify(wordArray);
         */
        stringify: function (wordArray) {
            try {
                return decodeURIComponent(escape(Latin1.stringify(wordArray)));
            } catch (e) {
                throw new Error('Malformed UTF-8 data');
            }
        },

        /**
         * Converts a UTF-8 string to a word array.
         *
         * @param {string} utf8Str The UTF-8 string.
         *
         * @return {WordArray} The word array.
         *
         * @static
         *
         * @example
         *
         *     var wordArray = CryptoJS.enc.Utf8.parse(utf8String);
         */
        parse: function (utf8Str) {
            return Latin1.parse(unescape(encodeURIComponent(utf8Str)));
        }
    };

    /**
     * Abstract buffered block algorithm template.
     *
     * The property blockSize must be implemented in a concrete subtype.
     *
     * @property {number} _minBufferSize The number of blocks that should be kept unprocessed in the buffer. Default: 0
     */
    var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({
        /**
         * Resets this block algorithm's data buffer to its initial state.
         *
         * @example
         *
         *     bufferedBlockAlgorithm.reset();
         */
        reset: function () {
            // Initial values
            this._data = new WordArray.init();
            this._nDataBytes = 0;
        },

        /**
         * Adds new data to this block algorithm's buffer.
         *
         * @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8.
         *
         * @example
         *
         *     bufferedBlockAlgorithm._append('data');
         *     bufferedBlockAlgorithm._append(wordArray);
         */
        _append: function (data) {
            // Convert string to WordArray, else assume WordArray already
            if (typeof data == 'string') {
                data = Utf8.parse(data);
            }

            // Append
            this._data.concat(data);
            this._nDataBytes += data.sigBytes;
        },

        /**
         * Processes available data blocks.
         *
         * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype.
         *
         * @param {boolean} doFlush Whether all blocks and partial blocks should be processed.
         *
         * @return {WordArray} The processed data.
         *
         * @example
         *
         *     var processedData = bufferedBlockAlgorithm._process();
         *     var processedData = bufferedBlockAlgorithm._process(!!'flush');
         */
        _process: function (doFlush) {
            // Shortcuts
            var data = this._data;
            var dataWords = data.words;
            var dataSigBytes = data.sigBytes;
            var blockSize = this.blockSize;
            var blockSizeBytes = blockSize * 4;

            // Count blocks ready
            var nBlocksReady = dataSigBytes / blockSizeBytes;
            if (doFlush) {
                // Round up to include partial blocks
                nBlocksReady = Math.ceil(nBlocksReady);
            } else {
                // Round down to include only full blocks,
                // less the number of blocks that must remain in the buffer
                nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0);
            }

            // Count words ready
            var nWordsReady = nBlocksReady * blockSize;

            // Count bytes ready
            var nBytesReady = Math.min(nWordsReady * 4, dataSigBytes);

            // Process blocks
            if (nWordsReady) {
                for (var offset = 0; offset < nWordsReady; offset += blockSize) {
                    // Perform concrete-algorithm logic
                    this._doProcessBlock(dataWords, offset);
                }

                // Remove processed words
                var processedWords = dataWords.splice(0, nWordsReady);
                data.sigBytes -= nBytesReady;
            }

            // Return processed words
            return new WordArray.init(processedWords, nBytesReady);
        },

        /**
         * Creates a copy of this object.
         *
         * @return {Object} The clone.
         *
         * @example
         *
         *     var clone = bufferedBlockAlgorithm.clone();
         */
        clone: function () {
            var clone = Base.clone.call(this);
            clone._data = this._data.clone();

            return clone;
        },

        _minBufferSize: 0
    });

    /**
     * Abstract hasher template.
     *
     * @property {number} blockSize The number of 32-bit words this hasher operates on. Default: 16 (512 bits)
     */
    var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({
        /**
         * Configuration options.
         */
        cfg: Base.extend(),

        /**
         * Initializes a newly created hasher.
         *
         * @param {Object} cfg (Optional) The configuration options to use for this hash computation.
         *
         * @example
         *
         *     var hasher = CryptoJS.algo.SHA256.create();
         */
        init: function (cfg) {
            // Apply config defaults
            this.cfg = this.cfg.extend(cfg);

            // Set initial values
            this.reset();
        },

        /**
         * Resets this hasher to its initial state.
         *
         * @example
         *
         *     hasher.reset();
         */
        reset: function () {
            // Reset data buffer
            BufferedBlockAlgorithm.reset.call(this);

            // Perform concrete-hasher logic
            this._doReset();
        },

        /**
         * Updates this hasher with a message.
         *
         * @param {WordArray|string} messageUpdate The message to append.
         *
         * @return {Hasher} This hasher.
         *
         * @example
         *
         *     hasher.update('message');
         *     hasher.update(wordArray);
         */
        update: function (messageUpdate) {
            // Append
            this._append(messageUpdate);

            // Update the hash
            this._process();

            // Chainable
            return this;
        },

        /**
         * Finalizes the hash computation.
         * Note that the finalize operation is effectively a destructive, read-once operation.
         *
         * @param {WordArray|string} messageUpdate (Optional) A final message update.
         *
         * @return {WordArray} The hash.
         *
         * @example
         *
         *     var hash = hasher.finalize();
         *     var hash = hasher.finalize('message');
         *     var hash = hasher.finalize(wordArray);
         */
        finalize: function (messageUpdate) {
            // Final message update
            if (messageUpdate) {
                this._append(messageUpdate);
            }

            // Perform concrete-hasher logic
            var hash = this._doFinalize();

            return hash;
        },

        blockSize: 512/32,

        /**
         * Creates a shortcut function to a hasher's object interface.
         *
         * @param {Hasher} hasher The hasher to create a helper for.
         *
         * @return {Function} The shortcut function.
         *
         * @static
         *
         * @example
         *
         *     var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256);
         */
        _createHelper: function (hasher) {
            return function (message, cfg) {
                return new hasher.init(cfg).finalize(message);
            };
        },

        /**
         * Creates a shortcut function to the HMAC's object interface.
         *
         * @param {Hasher} hasher The hasher to use in this HMAC helper.
         *
         * @return {Function} The shortcut function.
         *
         * @static
         *
         * @example
         *
         *     var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256);
         */
        _createHmacHelper: function (hasher) {
            return function (message, key) {
                return new C_algo.HMAC.init(hasher, key).finalize(message);
            };
        }
    });

    /**
     * Algorithm namespace.
     */
    var C_algo = C.algo = {};

    return C;
}(Math));

exports.CryptoJS = CryptoJS;
module.exports = exports;
/*
CryptoJS v3.1.2
code.google.com/p/crypto-js
(c) 2009-2013 by Jeff Mott. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 
associated documentation files (the "Software"), to deal in the Software without restriction, including 
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 
sell copies of the Software, and to permit persons to whom the Software is furnished to do so, 
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

code.google.com/p/crypto-js/wiki/License
*/

var C = require('./core.js').CryptoJS;
(function (Math) {
    // Shortcuts
    var C_lib = C.lib;
    var WordArray = C_lib.WordArray;
    var Hasher = C_lib.Hasher;
    var C_algo = C.algo;

    // Initialization and round constants tables
    var H = [];
    var K = [];

    // Compute constants
    (function () {
        function isPrime(n) {
            var sqrtN = Math.sqrt(n);
            for (var factor = 2; factor <= sqrtN; factor++) {
                if (!(n % factor)) {
                    return false;
                }
            }

            return true;
        }

        function getFractionalBits(n) {
            return ((n - (n | 0)) * 0x100000000) | 0;
        }

        var n = 2;
        var nPrime = 0;
        while (nPrime < 64) {
            if (isPrime(n)) {
                if (nPrime < 8) {
                    H[nPrime] = getFractionalBits(Math.pow(n, 1 / 2));
                }
                K[nPrime] = getFractionalBits(Math.pow(n, 1 / 3));

                nPrime++;
            }

            n++;
        }
    }());

    // Reusable object
    var W = [];

    /**
     * SHA-256 hash algorithm.
     */
    var SHA256 = C_algo.SHA256 = Hasher.extend({
        _doReset: function () {
            this._hash = new WordArray.init(H.slice(0));
        },

        _doProcessBlock: function (M, offset) {
            // Shortcut
            var H = this._hash.words;

            // Working variables
            var a = H[0];
            var b = H[1];
            var c = H[2];
            var d = H[3];
            var e = H[4];
            var f = H[5];
            var g = H[6];
            var h = H[7];

            // Computation
            for (var i = 0; i < 64; i++) {
                if (i < 16) {
                    W[i] = M[offset + i] | 0;
                } else {
                    var gamma0x = W[i - 15];
                    var gamma0  = ((gamma0x << 25) | (gamma0x >>> 7))  ^
                                  ((gamma0x << 14) | (gamma0x >>> 18)) ^
                                   (gamma0x >>> 3);

                    var gamma1x = W[i - 2];
                    var gamma1  = ((gamma1x << 15) | (gamma1x >>> 17)) ^
                                  ((gamma1x << 13) | (gamma1x >>> 19)) ^
                                   (gamma1x >>> 10);

                    W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16];
                }

                var ch  = (e & f) ^ (~e & g);
                var maj = (a & b) ^ (a & c) ^ (b & c);

                var sigma0 = ((a << 30) | (a >>> 2)) ^ ((a << 19) | (a >>> 13)) ^ ((a << 10) | (a >>> 22));
                var sigma1 = ((e << 26) | (e >>> 6)) ^ ((e << 21) | (e >>> 11)) ^ ((e << 7)  | (e >>> 25));

                var t1 = h + sigma1 + ch + K[i] + W[i];
                var t2 = sigma0 + maj;

                h = g;
                g = f;
                f = e;
                e = (d + t1) | 0;
                d = c;
                c = b;
                b = a;
                a = (t1 + t2) | 0;
            }

            // Intermediate hash value
            H[0] = (H[0] + a) | 0;
            H[1] = (H[1] + b) | 0;
            H[2] = (H[2] + c) | 0;
            H[3] = (H[3] + d) | 0;
            H[4] = (H[4] + e) | 0;
            H[5] = (H[5] + f) | 0;
            H[6] = (H[6] + g) | 0;
            H[7] = (H[7] + h) | 0;
        },

        _doFinalize: function () {
            // Shortcuts
            var data = this._data;
            var dataWords = data.words;

            var nBitsTotal = this._nDataBytes * 8;
            var nBitsLeft = data.sigBytes * 8;

            // Add padding
            dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32);
            dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000);
            dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal;
            data.sigBytes = dataWords.length * 4;

            // Hash final blocks
            this._process();

            // Return final computed hash
            return this._hash;
        },

        clone: function () {
            var clone = Hasher.clone.call(this);
            clone._hash = this._hash.clone();

            return clone;
        }
    });

    /**
     * Shortcut function to the hasher's object interface.
     *
     * @param {WordArray|string} message The message to hash.
     *
     * @return {WordArray} The hash.
     *
     * @static
     *
     * @example
     *
     *     var hash = CryptoJS.SHA256('message');
     *     var hash = CryptoJS.SHA256(wordArray);
     */
    C.SHA256 = Hasher._createHelper(SHA256);

    /**
     * Shortcut function to the HMAC's object interface.
     *
     * @param {WordArray|string} message The message to hash.
     * @param {WordArray|string} key The secret key.
     *
     * @return {WordArray} The HMAC.
     *
     * @static
     *
     * @example
     *
     *     var hmac = CryptoJS.HmacSHA256(message, key);
     */
    C.HmacSHA256 = Hasher._createHmacHelper(SHA256);
}(Math));

exports.CryptoJS = C;
module.exports = exports;
/*
CryptoJS v3.1.2
code.google.com/p/crypto-js
(c) 2009-2013 by Jeff Mott. All rights reserved.
code.google.com/p/crypto-js/wiki/License
*/
(function () {
    // Shortcuts
    var C = CryptoJS;
    var C_lib = C.lib;
    var Base = C_lib.Base;
    var C_enc = C.enc;
    var Utf8 = C_enc.Utf8;
    var C_algo = C.algo;

    /**
     * HMAC algorithm.
     */
    var HMAC = C_algo.HMAC = Base.extend({
        /**
         * Initializes a newly created HMAC.
         *
         * @param {Hasher} hasher The hash algorithm to use.
         * @param {WordArray|string} key The secret key.
         *
         * @example
         *
         *     var hmacHasher = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, key);
         */
        init: function (hasher, key) {
            // Init hasher
            hasher = this._hasher = new hasher.init();

            // Convert string to WordArray, else assume WordArray already
            if (typeof key == 'string') {
                key = Utf8.parse(key);
            }

            // Shortcuts
            var hasherBlockSize = hasher.blockSize;
            var hasherBlockSizeBytes = hasherBlockSize * 4;

            // Allow arbitrary length keys
            if (key.sigBytes > hasherBlockSizeBytes) {
                key = hasher.finalize(key);
            }

            // Clamp excess bits
            key.clamp();

            // Clone key for inner and outer pads
            var oKey = this._oKey = key.clone();
            var iKey = this._iKey = key.clone();

            // Shortcuts
            var oKeyWords = oKey.words;
            var iKeyWords = iKey.words;

            // XOR keys with pad constants
            for (var i = 0; i < hasherBlockSize; i++) {
                oKeyWords[i] ^= 0x5c5c5c5c;
                iKeyWords[i] ^= 0x36363636;
            }
            oKey.sigBytes = iKey.sigBytes = hasherBlockSizeBytes;

            // Set initial values
            this.reset();
        },

        /**
         * Resets this HMAC to its initial state.
         *
         * @example
         *
         *     hmacHasher.reset();
         */
        reset: function () {
            // Shortcut
            var hasher = this._hasher;

            // Reset
            hasher.reset();
            hasher.update(this._iKey);
        },

        /**
         * Updates this HMAC with a message.
         *
         * @param {WordArray|string} messageUpdate The message to append.
         *
         * @return {HMAC} This HMAC instance.
         *
         * @example
         *
         *     hmacHasher.update('message');
         *     hmacHasher.update(wordArray);
         */
        update: function (messageUpdate) {
            this._hasher.update(messageUpdate);

            // Chainable
            return this;
        },

        /**
         * Finalizes the HMAC computation.
         * Note that the finalize operation is effectively a destructive, read-once operation.
         *
         * @param {WordArray|string} messageUpdate (Optional) A final message update.
         *
         * @return {WordArray} The HMAC.
         *
         * @example
         *
         *     var hmac = hmacHasher.finalize();
         *     var hmac = hmacHasher.finalize('message');
         *     var hmac = hmacHasher.finalize(wordArray);
         */
        finalize: function (messageUpdate) {
            // Shortcut
            var hasher = this._hasher;

            // Compute HMAC
            var innerHash = hasher.finalize(messageUpdate);
            hasher.reset();
            var hmac = hasher.finalize(this._oKey.clone().concat(innerHash));

            return hmac;
        }
    });
}());
/*! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
 */
var b64map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var b64pad="=";

function hex2b64(h) {
  var i;
  var c;
  var ret = "";
  for(i = 0; i+3 <= h.length; i+=3) {
    c = parseInt(h.substring(i,i+3),16);
    ret += b64map.charAt(c >> 6) + b64map.charAt(c & 63);
  }
  if(i+1 == h.length) {
    c = parseInt(h.substring(i,i+1),16);
    ret += b64map.charAt(c << 2);
  }
  else if(i+2 == h.length) {
    c = parseInt(h.substring(i,i+2),16);
    ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4);
  }
  if (b64pad) while((ret.length & 3) > 0) ret += b64pad;
  return ret;
}

// convert a base64 string to hex
function b64tohex(s) {
  var ret = ""
  var i;
  var k = 0; // b64 state, 0-3
  var slop;
  var v;
  for(i = 0; i < s.length; ++i) {
    if(s.charAt(i) == b64pad) break;
    v = b64map.indexOf(s.charAt(i));
    if(v < 0) continue;
    if(k == 0) {
      ret += int2char(v >> 2);
      slop = v & 3;
      k = 1;
    }
    else if(k == 1) {
      ret += int2char((slop << 2) | (v >> 4));
      slop = v & 0xf;
      k = 2;
    }
    else if(k == 2) {
      ret += int2char(slop);
      ret += int2char(v >> 2);
      slop = v & 3;
      k = 3;
    }
    else {
      ret += int2char((slop << 2) | (v >> 4));
      ret += int2char(v & 0xf);
      k = 0;
    }
  }
  if(k == 1)
    ret += int2char(slop << 2);
  return ret;
}

// convert a base64 string to a byte/number array
function b64toBA(s) {
  //piggyback on b64tohex for now, optimize later
  var h = b64tohex(s);
  var i;
  var a = new Array();
  for(i = 0; 2*i < h.length; ++i) {
    a[i] = parseInt(h.substring(2*i,2*i+2),16);
  }
  return a;
}

exports.b64tohex = b64tohex;
exports.b64toBA  = b64toBA;
exports.hex2b64  = hex2b64;

module.exports = exports;
/*! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
 */
// prng4.js - uses Arcfour as a PRNG

function Arcfour() {
  this.i = 0;
  this.j = 0;
  this.S = new Array();
}

// Initialize arcfour context from key, an array of ints, each from [0..255]
function ARC4init(key) {
  var i, j, t;
  for(i = 0; i < 256; ++i)
    this.S[i] = i;
  j = 0;
  for(i = 0; i < 256; ++i) {
    j = (j + this.S[i] + key[i % key.length]) & 255;
    t = this.S[i];
    this.S[i] = this.S[j];
    this.S[j] = t;
  }
  this.i = 0;
  this.j = 0;
}

function ARC4next() {
  var t;
  this.i = (this.i + 1) & 255;
  this.j = (this.j + this.S[this.i]) & 255;
  t = this.S[this.i];
  this.S[this.i] = this.S[this.j];
  this.S[this.j] = t;
  return this.S[(t + this.S[this.i]) & 255];
}

Arcfour.prototype.init = ARC4init;
Arcfour.prototype.next = ARC4next;

// Plug in your RNG constructor here
function prng_newstate() {
  return new Arcfour();
}

// Pool size must be a multiple of 4 and greater than 32.
// An array of bytes the size of the pool will be passed to init()
var rng_psize = 256;
/*! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
 */
// Random number generator - requires a PRNG backend, e.g. prng4.js

// For best results, put code like
// <body onClick='rng_seed_time();' onKeyPress='rng_seed_time();'>
// in your main HTML document.

var rng_state;
var rng_pool;
var rng_pptr;

// Mix in a 32-bit integer into the pool
function rng_seed_int(x) {
  rng_pool[rng_pptr++] ^= x & 255;
  rng_pool[rng_pptr++] ^= (x >> 8) & 255;
  rng_pool[rng_pptr++] ^= (x >> 16) & 255;
  rng_pool[rng_pptr++] ^= (x >> 24) & 255;
  if(rng_pptr >= rng_psize) rng_pptr -= rng_psize;
}

// Mix in the current time (w/milliseconds) into the pool
function rng_seed_time() {
  rng_seed_int(new Date().getTime());
}

// Initialize the pool with junk if needed.
if(rng_pool == null) {
  rng_pool = new Array();
  rng_pptr = 0;
  var t;
  if(navigator.appName == "Netscape" && navigator.appVersion < "5" && window.crypto) {
    // Extract entropy (256 bits) from NS4 RNG if available
    var z = window.crypto.random(32);
    for(t = 0; t < z.length; ++t)
      rng_pool[rng_pptr++] = z.charCodeAt(t) & 255;
  }  
  while(rng_pptr < rng_psize) {  // extract some randomness from Math.random()
    t = Math.floor(65536 * Math.random());
    rng_pool[rng_pptr++] = t >>> 8;
    rng_pool[rng_pptr++] = t & 255;
  }
  rng_pptr = 0;
  rng_seed_time();
  //rng_seed_int(window.screenX);
  //rng_seed_int(window.screenY);
}

function rng_get_byte() {
  if(rng_state == null) {
    rng_seed_time();
    rng_state = prng_newstate();
    rng_state.init(rng_pool);
    for(rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr)
      rng_pool[rng_pptr] = 0;
    rng_pptr = 0;
    //rng_pool = null;
  }
  // TODO: allow reseeding after first request
  return rng_state.next();
}

function rng_get_bytes(ba) {
  var i;
  for(i = 0; i < ba.length; ++i) ba[i] = rng_get_byte();
}

function SecureRandom() {}

SecureRandom.prototype.nextBytes = rng_get_bytes;
/*! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
 */
// Depends on jsbn.js and rng.js

// Version 1.1: support utf-8 encoding in pkcs1pad2

var intShim = require("jsbn");

// convert a (hex) string to a bignum object
function parseBigInt(str,r) {
  return new BigInteger(str,r);
}

function linebrk(s,n) {
  var ret = "";
  var i = 0;
  while(i + n < s.length) {
    ret += s.substring(i,i+n) + "\n";
    i += n;
  }
  return ret + s.substring(i,s.length);
}

function byte2Hex(b) {
  if(b < 0x10)
    return "0" + b.toString(16);
  else
    return b.toString(16);
}

// PKCS#1 (type 2, random) pad input string s to n bytes, and return a bigint
function pkcs1pad2(s,n) {
  if(n < s.length + 11) { // TODO: fix for utf-8
    alert("Message too long for RSA");
    return null;
  }
  var ba = new Array();
  var i = s.length - 1;
  while(i >= 0 && n > 0) {
    var c = s.charCodeAt(i--);
    if(c < 128) { // encode using utf-8
      ba[--n] = c;
    }
    else if((c > 127) && (c < 2048)) {
      ba[--n] = (c & 63) | 128;
      ba[--n] = (c >> 6) | 192;
    }
    else {
      ba[--n] = (c & 63) | 128;
      ba[--n] = ((c >> 6) & 63) | 128;
      ba[--n] = (c >> 12) | 224;
    }
  }
  ba[--n] = 0;
  var rng = new SecureRandom();
  var x = new Array();
  while(n > 2) { // random non-zero pad
    x[0] = 0;
    while(x[0] == 0) rng.nextBytes(x);
    ba[--n] = x[0];
  }
  ba[--n] = 2;
  ba[--n] = 0;
  return new BigInteger(ba);
}

// PKCS#1 (OAEP) mask generation function
function oaep_mgf1_arr(seed, len, hash)
{
    var mask = '', i = 0;

    while (mask.length < len)
    {
        mask += hash(String.fromCharCode.apply(String, seed.concat([
                (i & 0xff000000) >> 24,
                (i & 0x00ff0000) >> 16,
                (i & 0x0000ff00) >> 8,
                i & 0x000000ff])));
        i += 1;
    }

    return mask;
}

var SHA1_SIZE = 20;

// PKCS#1 (OAEP) pad input string s to n bytes, and return a bigint
function oaep_pad(s, n, hash)
{
    if (s.length + 2 * SHA1_SIZE + 2 > n)
    {
        throw "Message too long for RSA";
    }

    var PS = '', i;

    for (i = 0; i < n - s.length - 2 * SHA1_SIZE - 2; i += 1)
    {
        PS += '\x00';
    }

    var DB = rstr_sha1('') + PS + '\x01' + s;
    var seed = new Array(SHA1_SIZE);
    new SecureRandom().nextBytes(seed);
    
    var dbMask = oaep_mgf1_arr(seed, DB.length, hash || rstr_sha1);
    var maskedDB = [];

    for (i = 0; i < DB.length; i += 1)
    {
        maskedDB[i] = DB.charCodeAt(i) ^ dbMask.charCodeAt(i);
    }

    var seedMask = oaep_mgf1_arr(maskedDB, seed.length, rstr_sha1);
    var maskedSeed = [0];

    for (i = 0; i < seed.length; i += 1)
    {
        maskedSeed[i + 1] = seed[i] ^ seedMask.charCodeAt(i);
    }

    return new BigInteger(maskedSeed.concat(maskedDB));
}

// "empty" RSA key constructor
function RSAKey() {
  this.n = null;
  this.e = 0;
  this.d = null;
  this.p = null;
  this.q = null;
  this.dmp1 = null;
  this.dmq1 = null;
  this.coeff = null;
}

// Set the public key fields N and e from hex strings
function RSASetPublic(N,E) {
  this.isPublic = true;
  if (typeof N !== "string") 
  {
    this.n = N;
    this.e = E;
  }
  else if(N != null && E != null && N.length > 0 && E.length > 0) {
    this.n = parseBigInt(N,16);
    this.e = parseInt(E,16);
  }
  else
    alert("Invalid RSA public key");
}

// Perform raw public operation on "x": return x^e (mod n)
function RSADoPublic(x) {
  return x.modPowInt(this.e, this.n);
}

// Return the PKCS#1 RSA encryption of "text" as an even-length hex string
function RSAEncrypt(text) {
  var m = pkcs1pad2(text,(this.n.bitLength()+7)>>3);
  if(m == null) return null;
  var c = this.doPublic(m);
  if(c == null) return null;
  var h = c.toString(16);
  if((h.length & 1) == 0) return h; else return "0" + h;
}

// Return the PKCS#1 OAEP RSA encryption of "text" as an even-length hex string
function RSAEncryptOAEP(text, hash) {
  var m = oaep_pad(text, (this.n.bitLength()+7)>>3, hash);
  if(m == null) return null;
  var c = this.doPublic(m);
  if(c == null) return null;
  var h = c.toString(16);
  if((h.length & 1) == 0) return h; else return "0" + h;
}

// Return the PKCS#1 RSA encryption of "text" as a Base64-encoded string
//function RSAEncryptB64(text) {
//  var h = this.encrypt(text);
//  if(h) return hex2b64(h); else return null;
//}

// protected
RSAKey.prototype.doPublic = RSADoPublic;

// public
RSAKey.prototype.setPublic = RSASetPublic;
RSAKey.prototype.encrypt = RSAEncrypt;
RSAKey.prototype.encryptOAEP = RSAEncryptOAEP;
//RSAKey.prototype.encrypt_b64 = RSAEncryptB64;

RSAKey.prototype.type = "RSA";

exports.RSAKey = RSAKey;
module.exports = exports;
/*! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
 */
// Depends on rsa.js and jsbn2.js

// Version 1.1: support utf-8 decoding in pkcs1unpad2

var intShim = require("jsbn");
var BigInteger = intShim.BigInteger ? intShim.BigInteger : intShim ;
var RSAKey = require('./rsa.js').RSAKey;

// Undo PKCS#1 (type 2, random) padding and, if valid, return the plaintext
function pkcs1unpad2(d,n) {
  var b = d.toByteArray();
  var i = 0;
  while(i < b.length && b[i] == 0) ++i;
  if(b.length-i != n-1 || b[i] != 2)
    return null;
  ++i;
  while(b[i] != 0)
    if(++i >= b.length) return null;
  var ret = "";
  while(++i < b.length) {
    var c = b[i] & 255;
    if(c < 128) { // utf-8 decode
      ret += String.fromCharCode(c);
    }
    else if((c > 191) && (c < 224)) {
      ret += String.fromCharCode(((c & 31) << 6) | (b[i+1] & 63));
      ++i;
    }
    else {
      ret += String.fromCharCode(((c & 15) << 12) | ((b[i+1] & 63) << 6) | (b[i+2] & 63));
      i += 2;
    }
  }
  return ret;
}

// PKCS#1 (OAEP) mask generation function
function oaep_mgf1_str(seed, len, hash)
{
    var mask = '', i = 0;

    while (mask.length < len)
    {
        mask += hash(seed + String.fromCharCode.apply(String, [
                (i & 0xff000000) >> 24,
                (i & 0x00ff0000) >> 16,
                (i & 0x0000ff00) >> 8,
                i & 0x000000ff]));
        i += 1;
    }

    return mask;
}

var SHA1_SIZE = 20;

// Undo PKCS#1 (OAEP) padding and, if valid, return the plaintext
function oaep_unpad(d, n, hash)
{
    d = d.toByteArray();

    var i;

    for (i = 0; i < d.length; i += 1)
    {
        d[i] &= 0xff;
    }

    while (d.length < n)
    {
        d.unshift(0);
    }

    d = String.fromCharCode.apply(String, d);

    if (d.length < 2 * SHA1_SIZE + 2)
    {
        throw "Cipher too short";
    }

    var maskedSeed = d.substr(1, SHA1_SIZE)
    var maskedDB = d.substr(SHA1_SIZE + 1);

    var seedMask = oaep_mgf1_str(maskedDB, SHA1_SIZE, hash || rstr_sha1);
    var seed = [], i;

    for (i = 0; i < maskedSeed.length; i += 1)
    {
        seed[i] = maskedSeed.charCodeAt(i) ^ seedMask.charCodeAt(i);
    }

    var dbMask = oaep_mgf1_str(String.fromCharCode.apply(String, seed),
                           d.length - SHA1_SIZE, rstr_sha1);

    var DB = [];

    for (i = 0; i < maskedDB.length; i += 1)
    {
        DB[i] = maskedDB.charCodeAt(i) ^ dbMask.charCodeAt(i);
    }

    DB = String.fromCharCode.apply(String, DB);

    if (DB.substr(0, SHA1_SIZE) !== rstr_sha1(''))
    {
        throw "Hash mismatch";
    }

    DB = DB.substr(SHA1_SIZE);

    var first_one = DB.indexOf('\x01');
    var last_zero = (first_one != -1) ? DB.substr(0, first_one).lastIndexOf('\x00') : -1;

    if (last_zero + 1 != first_one)
    {
        throw "Malformed data";
    }

    return DB.substr(first_one + 1);
}

// Set the private key fields N, e, and d from hex strings
function RSASetPrivate(N,E,D) {
  this.isPrivate = true;
  if (typeof N !== "string")
  {
    this.n = N;
    this.e = E;
    this.d = D;
  }
  else if(N != null && E != null && N.length > 0 && E.length > 0) {
    this.n = parseBigInt(N,16);
    this.e = parseInt(E,16);
    this.d = parseBigInt(D,16);
  }
  else
    alert("Invalid RSA private key");
}

// Set the private key fields N, e, d and CRT params from hex strings
function RSASetPrivateEx(N,E,D,P,Q,DP,DQ,C) {
  this.isPrivate = true;
  if (N == null) throw "RSASetPrivateEx N == null";
  if (E == null) throw "RSASetPrivateEx E == null";
  if (N.length == 0) throw "RSASetPrivateEx N.length == 0";
  if (E.length == 0) throw "RSASetPrivateEx E.length == 0";

  if (N != null && E != null && N.length > 0 && E.length > 0) {
    this.n = parseBigInt(N,16);
    this.e = parseInt(E,16);
    this.d = parseBigInt(D,16);
    this.p = parseBigInt(P,16);
    this.q = parseBigInt(Q,16);
    this.dmp1 = parseBigInt(DP,16);
    this.dmq1 = parseBigInt(DQ,16);
    this.coeff = parseBigInt(C,16);
  } else {
    alert("Invalid RSA private key in RSASetPrivateEx");
  }
}

// Generate a new random private key B bits long, using public expt E
function RSAGenerate(B,E) {
  var rng = new SecureRandom();
  var qs = B>>1;
  this.e = parseInt(E,16);
  var ee = new BigInteger(E,16);
  for(;;) {
    for(;;) {
      this.p = new BigInteger(B-qs,1,rng);
      if(this.p.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.p.isProbablePrime(10)) break;
    }
    for(;;) {
      this.q = new BigInteger(qs,1,rng);
      if(this.q.subtract(BigInteger.ONE).gcd(ee).compareTo(BigInteger.ONE) == 0 && this.q.isProbablePrime(10)) break;
    }
    if(this.p.compareTo(this.q) <= 0) {
      var t = this.p;
      this.p = this.q;
      this.q = t;
    }
    var p1 = this.p.subtract(BigInteger.ONE);	// p1 = p - 1
    var q1 = this.q.subtract(BigInteger.ONE);	// q1 = q - 1
    var phi = p1.multiply(q1);
    if(phi.gcd(ee).compareTo(BigInteger.ONE) == 0) {
      this.n = this.p.multiply(this.q);	// this.n = p * q
      this.d = ee.modInverse(phi);	// this.d = 
      this.dmp1 = this.d.mod(p1);	// this.dmp1 = d mod (p - 1)
      this.dmq1 = this.d.mod(q1);	// this.dmq1 = d mod (q - 1)
      this.coeff = this.q.modInverse(this.p);	// this.coeff = (q ^ -1) mod p
      break;
    }
  }
  this.isPrivate = true;
}

// Perform raw private operation on "x": return x^d (mod n)
function RSADoPrivate(x) {
  if(this.p == null || this.q == null)
    return x.modPow(this.d, this.n);

  // TODO: re-calculate any missing CRT params
  var xp = x.mod(this.p).modPow(this.dmp1, this.p); // xp=cp?
  var xq = x.mod(this.q).modPow(this.dmq1, this.q); // xq=cq?

  while(xp.compareTo(xq) < 0)
    xp = xp.add(this.p);
  // NOTE:
  // xp.subtract(xq) => cp -cq
  // xp.subtract(xq).multiply(this.coeff).mod(this.p) => (cp - cq) * u mod p = h
  // xp.subtract(xq).multiply(this.coeff).mod(this.p).multiply(this.q).add(xq) => cq + (h * q) = M
  return xp.subtract(xq).multiply(this.coeff).mod(this.p).multiply(this.q).add(xq);
}

// Return the PKCS#1 RSA decryption of "ctext".
// "ctext" is an even-length hex string and the output is a plain string.
function RSADecrypt(ctext) {
  var c = parseBigInt(ctext, 16);
  var m = this.doPrivate(c);
  if(m == null) return null;
  return pkcs1unpad2(m, (this.n.bitLength()+7)>>3);
}

// Return the PKCS#1 OAEP RSA decryption of "ctext".
// "ctext" is an even-length hex string and the output is a plain string.
function RSADecryptOAEP(ctext, hash) {
  var c = parseBigInt(ctext, 16);
  var m = this.doPrivate(c);
  if(m == null) return null;
  return oaep_unpad(m, (this.n.bitLength()+7)>>3, hash);
}

// Return the PKCS#1 RSA decryption of "ctext".
// "ctext" is a Base64-encoded string and the output is a plain string.
//function RSAB64Decrypt(ctext) {
//  var h = b64tohex(ctext);
//  if(h) return this.decrypt(h); else return null;
//}

// protected
RSAKey.prototype.doPrivate = RSADoPrivate;

// public
RSAKey.prototype.setPrivate = RSASetPrivate;
RSAKey.prototype.setPrivateEx = RSASetPrivateEx;
RSAKey.prototype.generate = RSAGenerate;
RSAKey.prototype.decrypt = RSADecrypt;
RSAKey.prototype.decryptOAEP = RSADecryptOAEP;
//RSAKey.prototype.b64_decrypt = RSAB64Decrypt;

exports.RSAKey = RSAKey;
module.exports = exports;
/*! crypto-1.1.7.js (c) 2013-2015 Kenji Urushima | kjur.github.com/jsrsasign/license
 */
/*
 * crypto.js - Cryptographic Algorithm Provider class
 *
 * Copyright (c) 2013-2015 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.
 */

/**
 * @fileOverview
 * @name crypto-1.1.js
 * @author Kenji Urushima kenji.urushima@gmail.com
 * @version 1.1.7 (2015-Oct-11)
 * @since jsrsasign 2.2
 * @license <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
 */

var CryptoJS = require('./sha256.js').CryptoJS
  , intShim = require('jsbn');


/** 
 * kjur's class library name space
 * @name KJUR
 * @namespace kjur's class library name space
 */
if (typeof KJUR == "undefined" || !KJUR) KJUR = {};
/**
 * kjur's cryptographic algorithm provider library name space
 * <p>
 * This namespace privides following crytpgrahic classes.
 * <ul>
 * <li>{@link KJUR.crypto.MessageDigest} - Java JCE(cryptograhic extension) style MessageDigest class</li>
 * <li>{@link KJUR.crypto.Signature} - Java JCE(cryptograhic extension) style Signature class</li>
 * <li>{@link KJUR.crypto.Util} - cryptographic utility functions and properties</li>
 * </ul>
 * NOTE: Please ignore method summary and document of this namespace. This caused by a bug of jsdoc2.
 * </p>
 * @name KJUR.crypto
 * @namespace
 */
if (typeof KJUR.crypto == "undefined" || !KJUR.crypto) KJUR.crypto = {};

/**
 * static object for cryptographic function utilities
 * @name KJUR.crypto.Util
 * @class static object for cryptographic function utilities
 * @property {Array} DIGESTINFOHEAD PKCS#1 DigestInfo heading hexadecimal bytes for each hash algorithms
 * @property {Array} DEFAULTPROVIDER associative array of default provider name for each hash and signature algorithms
 * @description
 */
KJUR.crypto.Util = new function() {
    this.DIGESTINFOHEAD = {
	'sha1':      "3021300906052b0e03021a05000414",
        'sha224':    "302d300d06096086480165030402040500041c",
	'sha256':    "3031300d060960864801650304020105000420",
	'sha384':    "3041300d060960864801650304020205000430",
	'sha512':    "3051300d060960864801650304020305000440",
	'md2':       "3020300c06082a864886f70d020205000410",
	'md5':       "3020300c06082a864886f70d020505000410",
	'ripemd160': "3021300906052b2403020105000414"
    };

    /*
     * @since crypto 1.1.1
     */
    this.DEFAULTPROVIDER = {
	'md5':			'cryptojs',
	'sha1':			'cryptojs',
	'sha224':		'cryptojs',
	'sha256':		'cryptojs',
	'sha384':		'cryptojs',
	'sha512':		'cryptojs',
	'ripemd160':		'cryptojs',
	'hmacmd5':		'cryptojs',
	'hmacsha1':		'cryptojs',
	'hmacsha224':		'cryptojs',
	'hmacsha256':		'cryptojs',
	'hmacsha384':		'cryptojs',
	'hmacsha512':		'cryptojs',
	'hmacripemd160':	'cryptojs',

	'MD5withRSA':		'cryptojs/jsrsa',
	'SHA1withRSA':		'cryptojs/jsrsa',
	'SHA224withRSA':	'cryptojs/jsrsa',
	'SHA256withRSA':	'cryptojs/jsrsa',
	'SHA384withRSA':	'cryptojs/jsrsa',
	'SHA512withRSA':	'cryptojs/jsrsa',
	'RIPEMD160withRSA':	'cryptojs/jsrsa',

	'MD5withECDSA':		'cryptojs/jsrsa',
	'SHA1withECDSA':	'cryptojs/jsrsa',
	'SHA224withECDSA':	'cryptojs/jsrsa',
	'SHA256withECDSA':	'cryptojs/jsrsa',
	'SHA384withECDSA':	'cryptojs/jsrsa',
	'SHA512withECDSA':	'cryptojs/jsrsa',
	'RIPEMD160withECDSA':	'cryptojs/jsrsa',

	'SHA1withDSA':		'cryptojs/jsrsa',
	'SHA224withDSA':	'cryptojs/jsrsa',
	'SHA256withDSA':	'cryptojs/jsrsa',

	'MD5withRSAandMGF1':		'cryptojs/jsrsa',
	'SHA1withRSAandMGF1':		'cryptojs/jsrsa',
	'SHA224withRSAandMGF1':		'cryptojs/jsrsa',
	'SHA256withRSAandMGF1':		'cryptojs/jsrsa',
	'SHA384withRSAandMGF1':		'cryptojs/jsrsa',
	'SHA512withRSAandMGF1':		'cryptojs/jsrsa',
	'RIPEMD160withRSAandMGF1':	'cryptojs/jsrsa'
    };

    /*
     * @since crypto 1.1.2
     */
    this.CRYPTOJSMESSAGEDIGESTNAME = {
	'md5':		'CryptoJS.algo.MD5',
	'sha1':		'CryptoJS.algo.SHA1',
	'sha224':	'CryptoJS.algo.SHA224',
	'sha256':	'CryptoJS.algo.SHA256',
	'sha384':	'CryptoJS.algo.SHA384',
	'sha512':	'CryptoJS.algo.SHA512',
	'ripemd160':	'CryptoJS.algo.RIPEMD160'
    };

    /**
     * get hexadecimal DigestInfo
     * @name getDigestInfoHex
     * @memberOf KJUR.crypto.Util
     * @function
     * @param {String} hHash hexadecimal hash value
     * @param {String} alg hash algorithm name (ex. 'sha1')
     * @return {String} hexadecimal string DigestInfo ASN.1 structure
     */
    this.getDigestInfoHex = function(hHash, alg) {
	if (typeof this.DIGESTINFOHEAD[alg] == "undefined")
	    throw "alg not supported in Util.DIGESTINFOHEAD: " + alg;
	return this.DIGESTINFOHEAD[alg] + hHash;
    };

    /**
     * get PKCS#1 padded hexadecimal DigestInfo
     * @name getPaddedDigestInfoHex
     * @memberOf KJUR.crypto.Util
     * @function
     * @param {String} hHash hexadecimal hash value of message to be signed
     * @param {String} alg hash algorithm name (ex. 'sha1')
     * @param {Integer} keySize key bit length (ex. 1024)
     * @return {String} hexadecimal string of PKCS#1 padded DigestInfo
     */
    this.getPaddedDigestInfoHex = function(hHash, alg, keySize) {
	var hDigestInfo = this.getDigestInfoHex(hHash, alg);
	var pmStrLen = keySize / 4; // minimum PM length

	if (hDigestInfo.length + 22 > pmStrLen) // len(0001+ff(*8)+00+hDigestInfo)=22
	    throw "key is too short for SigAlg: keylen=" + keySize + "," + alg;

	var hHead = "0001";
	var hTail = "00" + hDigestInfo;
	var hMid = "";
	var fLen = pmStrLen - hHead.length - hTail.length;
	for (var i = 0; i < fLen; i += 2) {
	    hMid += "ff";
	}
	var hPaddedMessage = hHead + hMid + hTail;
	return hPaddedMessage;
    };

    /**
     * get hexadecimal hash of string with specified algorithm
     * @name hashString
     * @memberOf KJUR.crypto.Util
     * @function
     * @param {String} s input string to be hashed
     * @param {String} alg hash algorithm name
     * @return {String} hexadecimal string of hash value
     * @since 1.1.1
     */
    this.hashString = function(s, alg) {
        var md = new KJUR.crypto.MessageDigest({'alg': alg});
        return md.digestString(s);
    };

    /**
     * get hexadecimal hash of hexadecimal string with specified algorithm
     * @name hashHex
     * @memberOf KJUR.crypto.Util
     * @function
     * @param {String} sHex input hexadecimal string to be hashed
     * @param {String} alg hash algorithm name
     * @return {String} hexadecimal string of hash value
     * @since 1.1.1
     */
    this.hashHex = function(sHex, alg) {
        var md = new KJUR.crypto.MessageDigest({'alg': alg});
        return md.digestHex(sHex);
    };

    /**
     * get hexadecimal SHA1 hash of string
     * @name sha1
     * @memberOf KJUR.crypto.Util
     * @function
     * @param {String} s input string to be hashed
     * @return {String} hexadecimal string of hash value
     * @since 1.0.3
     */
    this.sha1 = function(s) {
        var md = new KJUR.crypto.MessageDigest({'alg':'sha1', 'prov':'cryptojs'});
        return md.digestString(s);
    };

    /**
     * get hexadecimal SHA256 hash of string
     * @name sha256
     * @memberOf KJUR.crypto.Util
     * @function
     * @param {String} s input string to be hashed
     * @return {String} hexadecimal string of hash value
     * @since 1.0.3
     */
    this.sha256 = function(s) {
        var md = new KJUR.crypto.MessageDigest({'alg':'sha256', 'prov':'cryptojs'});
        return md.digestString(s);
    };

    this.sha256Hex = function(s) {
        var md = new KJUR.crypto.MessageDigest({'alg':'sha256', 'prov':'cryptojs'});
        return md.digestHex(s);
    };

    /**
     * get hexadecimal SHA512 hash of string
     * @name sha512
     * @memberOf KJUR.crypto.Util
     * @function
     * @param {String} s input string to be hashed
     * @return {String} hexadecimal string of hash value
     * @since 1.0.3
     */
    this.sha512 = function(s) {
        var md = new KJUR.crypto.MessageDigest({'alg':'sha512', 'prov':'cryptojs'});
        return md.digestString(s);
    };

    this.sha512Hex = function(s) {
        var md = new KJUR.crypto.MessageDigest({'alg':'sha512', 'prov':'cryptojs'});
        return md.digestHex(s);
    };

    /**
     * get hexadecimal MD5 hash of string
     * @name md5
     * @memberOf KJUR.crypto.Util
     * @function
     * @param {String} s input string to be hashed
     * @return {String} hexadecimal string of hash value
     * @since 1.0.3
     */
    this.md5 = function(s) {
        var md = new KJUR.crypto.MessageDigest({'alg':'md5', 'prov':'cryptojs'});
        return md.digestString(s);
    };

    /**
     * get hexadecimal RIPEMD160 hash of string
     * @name ripemd160
     * @memberOf KJUR.crypto.Util
     * @function
     * @param {String} s input string to be hashed
     * @return {String} hexadecimal string of hash value
     * @since 1.0.3
     */
    this.ripemd160 = function(s) {
        var md = new KJUR.crypto.MessageDigest({'alg':'ripemd160', 'prov':'cryptojs'});
        return md.digestString(s);
    };

    /*
     * @since 1.1.2
     */
    this.getCryptoJSMDByName = function(s) {
	
    };
};

/**
 * MessageDigest class which is very similar to java.security.MessageDigest class
 * @name KJUR.crypto.MessageDigest
 * @class MessageDigest class which is very similar to java.security.MessageDigest class
 * @param {Array} params parameters for constructor
 * @description
 * <br/>
 * Currently this supports following algorithm and providers combination:
 * <ul>
 * <li>md5 - cryptojs</li>
 * <li>sha1 - cryptojs</li>
 * <li>sha224 - cryptojs</li>
 * <li>sha256 - cryptojs</li>
 * <li>sha384 - cryptojs</li>
 * <li>sha512 - cryptojs</li>
 * <li>ripemd160 - cryptojs</li>
 * <li>sha256 - sjcl (NEW from crypto.js 1.0.4)</li>
 * </ul>
 * @example
 * // CryptoJS provider sample
 * var md = new KJUR.crypto.MessageDigest({alg: "sha1", prov: "cryptojs"});
 * md.updateString('aaa')
 * var mdHex = md.digest()
 *
 * // SJCL(Stanford JavaScript Crypto Library) provider sample
 * var md = new KJUR.crypto.MessageDigest({alg: "sha256", prov: "sjcl"}); // sjcl supports sha256 only
 * md.updateString('aaa')
 * var mdHex = md.digest()
 */
KJUR.crypto.MessageDigest = function(params) {
    var md = null;
    var algName = null;
    var provName = null;

    /**
     * set hash algorithm and provider
     * @name setAlgAndProvider
     * @memberOf KJUR.crypto.MessageDigest
     * @function
     * @param {String} alg hash algorithm name
     * @param {String} prov provider name
     * @description
     * @example
     * // for SHA1
     * md.setAlgAndProvider('sha1', 'cryptojs');
     * // for RIPEMD160
     * md.setAlgAndProvider('ripemd160', 'cryptojs');
     */
    this.setAlgAndProvider = function(alg, prov) {
	if (alg != null && prov === undefined) prov = KJUR.crypto.Util.DEFAULTPROVIDER[alg];

	// for cryptojs
	if (':md5:sha1:sha224:sha256:sha384:sha512:ripemd160:'.indexOf(alg) != -1 &&
	    prov == 'cryptojs') {
	    try {
		this.md = eval(KJUR.crypto.Util.CRYPTOJSMESSAGEDIGESTNAME[alg]).create();
	    } catch (ex) {
		throw "setAlgAndProvider hash alg set fail alg=" + alg + "/" + ex;
	    }
	    this.updateString = function(str) {
		this.md.update(str);
	    };
	    this.updateHex = function(hex) {
		var wHex = CryptoJS.enc.Hex.parse(hex);
		this.md.update(wHex);
	    };
	    this.digest = function() {
		var hash = this.md.finalize();
		return hash.toString(CryptoJS.enc.Hex);
	    };
	    this.digestString = function(str) {
		this.updateString(str);
		return this.digest();
	    };
	    this.digestHex = function(hex) {
		this.updateHex(hex);
		return this.digest();
	    };
	}
	if (':sha256:'.indexOf(alg) != -1 &&
	    prov == 'sjcl') {
	    try {
		this.md = new sjcl.hash.sha256();
	    } catch (ex) {
		throw "setAlgAndProvider hash alg set fail alg=" + alg + "/" + ex;
	    }
	    this.updateString = function(str) {
		this.md.update(str);
	    };
	    this.updateHex = function(hex) {
		var baHex = sjcl.codec.hex.toBits(hex);
		this.md.update(baHex);
	    };
	    this.digest = function() {
		var hash = this.md.finalize();
		return sjcl.codec.hex.fromBits(hash);
	    };
	    this.digestString = function(str) {
		this.updateString(str);
		return this.digest();
	    };
	    this.digestHex = function(hex) {
		this.updateHex(hex);
		return this.digest();
	    };
	}
    };

    /**
     * update digest by specified string
     * @name updateString
     * @memberOf KJUR.crypto.MessageDigest
     * @function
     * @param {String} str string to update
     * @description
     * @example
     * md.updateString('New York');
     */
    this.updateString = function(str) {
	throw "updateString(str) not supported for this alg/prov: " + this.algName + "/" + this.provName;
    };

    /**
     * update digest by specified hexadecimal string
     * @name updateHex
     * @memberOf KJUR.crypto.MessageDigest
     * @function
     * @param {String} hex hexadecimal string to update
     * @description
     * @example
     * md.updateHex('0afe36');
     */
    this.updateHex = function(hex) {
	throw "updateHex(hex) not supported for this alg/prov: " + this.algName + "/" + this.provName;
    };

    /**
     * completes hash calculation and returns hash result
     * @name digest
     * @memberOf KJUR.crypto.MessageDigest
     * @function
     * @description
     * @example
     * md.digest()
     */
    this.digest = function() {
	throw "digest() not supported for this alg/prov: " + this.algName + "/" + this.provName;
    };

    /**
     * performs final update on the digest using string, then completes the digest computation
     * @name digestString
     * @memberOf KJUR.crypto.MessageDigest
     * @function
     * @param {String} str string to final update
     * @description
     * @example
     * md.digestString('aaa')
     */
    this.digestString = function(str) {
	throw "digestString(str) not supported for this alg/prov: " + this.algName + "/" + this.provName;
    };

    /**
     * performs final update on the digest using hexadecimal string, then completes the digest computation
     * @name digestHex
     * @memberOf KJUR.crypto.MessageDigest
     * @function
     * @param {String} hex hexadecimal string to final update
     * @description
     * @example
     * md.digestHex('0f2abd')
     */
    this.digestHex = function(hex) {
	throw "digestHex(hex) not supported for this alg/prov: " + this.algName + "/" + this.provName;
    };

    if (params !== undefined) {
	if (params['alg'] !== undefined) {
	    this.algName = params['alg'];
	    if (params['prov'] === undefined)
		this.provName = KJUR.crypto.Util.DEFAULTPROVIDER[this.algName];
	    this.setAlgAndProvider(this.algName, this.provName);
	}
    }
};

/**
 * Mac(Message Authentication Code) class which is very similar to java.security.Mac class 
 * @name KJUR.crypto.Mac
 * @class Mac class which is very similar to java.security.Mac class
 * @param {Array} params parameters for constructor
 * @description
 * <br/>
 * Currently this supports following algorithm and providers combination:
 * <ul>
 * <li>hmacmd5 - cryptojs</li>
 * <li>hmacsha1 - cryptojs</li>
 * <li>hmacsha224 - cryptojs</li>
 * <li>hmacsha256 - cryptojs</li>
 * <li>hmacsha384 - cryptojs</li>
 * <li>hmacsha512 - cryptojs</li>
 * </ul>
 * NOTE: HmacSHA224 and HmacSHA384 issue was fixed since jsrsasign 4.1.4.
 * Please use 'ext/cryptojs-312-core-fix*.js' instead of 'core.js' of original CryptoJS
 * to avoid those issue.
 * <br/>
 * NOTE2: Hmac signature bug was fixed in jsrsasign 4.9.0 by providing CryptoJS
 * bug workaround.
 * <br/>
 * Please see {@link KJUR.crypto.Mac.setPassword}, how to provide password
 * in various ways in detail.
 * @example
 * var mac = new KJUR.crypto.Mac({alg: "HmacSHA1", "pass": "pass"});
 * mac.updateString('aaa')
 * var macHex = md.doFinal()
 *
 * // other password representation 
 * var mac = new KJUR.crypto.Mac({alg: "HmacSHA256", "pass": {"hex":  "6161"}});
 * var mac = new KJUR.crypto.Mac({alg: "HmacSHA256", "pass": {"utf8": "aa"}});
 * var mac = new KJUR.crypto.Mac({alg: "HmacSHA256", "pass": {"rstr": "\x61\x61"}});
 * var mac = new KJUR.crypto.Mac({alg: "HmacSHA256", "pass": {"b64":  "Mi02/+...a=="}});
 * var mac = new KJUR.crypto.Mac({alg: "HmacSHA256", "pass": {"b64u": "Mi02_-...a"}});
 */
KJUR.crypto.Mac = function(params) {
    var mac = null;
    var pass = null;
    var algName = null;
    var provName = null;
    var algProv = null;

    this.setAlgAndProvider = function(alg, prov) {
	alg = alg.toLowerCase();

	if (alg == null) alg = "hmacsha1";

	alg = alg.toLowerCase();
        if (alg.substr(0, 4) != "hmac") {
	    throw "setAlgAndProvider unsupported HMAC alg: " + alg;
	}

	if (prov === undefined) prov = KJUR.crypto.Util.DEFAULTPROVIDER[alg];
	this.algProv = alg + "/" + prov;

	var hashAlg = alg.substr(4);

	// for cryptojs
	if (':md5:sha1:sha224:sha256:sha384:sha512:ripemd160:'.indexOf(hashAlg) != -1 &&
	    prov == 'cryptojs') {
	    try {
		var mdObj = eval(KJUR.crypto.Util.CRYPTOJSMESSAGEDIGESTNAME[hashAlg]);
		this.mac = CryptoJS.algo.HMAC.create(mdObj, this.pass);
	    } catch (ex) {
		throw "setAlgAndProvider hash alg set fail hashAlg=" + hashAlg + "/" + ex;
	    }
	    this.updateString = function(str) {
		this.mac.update(str);
	    };
	    this.updateHex = function(hex) {
		var wHex = CryptoJS.enc.Hex.parse(hex);
		this.mac.update(wHex);
	    };
	    this.doFinal = function() {
		var hash = this.mac.finalize();
		return hash.toString(CryptoJS.enc.Hex);
	    };
	    this.doFinalString = function(str) {
		this.updateString(str);
		return this.doFinal();
	    };
	    this.doFinalHex = function(hex) {
		this.updateHex(hex);
		return this.doFinal();
	    };
	}
    };

    /**
     * update digest by specified string
     * @name updateString
     * @memberOf KJUR.crypto.Mac
     * @function
     * @param {String} str string to update
     * @description
     * @example
     * md.updateString('New York');
     */
    this.updateString = function(str) {
	throw "updateString(str) not supported for this alg/prov: " + this.algProv;
    };

    /**
     * update digest by specified hexadecimal string
     * @name updateHex
     * @memberOf KJUR.crypto.Mac
     * @function
     * @param {String} hex hexadecimal string to update
     * @description
     * @example
     * md.updateHex('0afe36');
     */
    this.updateHex = function(hex) {
	throw "updateHex(hex) not supported for this alg/prov: " + this.algProv;
    };

    /**
     * completes hash calculation and returns hash result
     * @name doFinal
     * @memberOf KJUR.crypto.Mac
     * @function
     * @description
     * @example
     * md.digest()
     */
    this.doFinal = function() {
	throw "digest() not supported for this alg/prov: " + this.algProv;
    };

    /**
     * performs final update on the digest using string, then completes the digest computation
     * @name doFinalString
     * @memberOf KJUR.crypto.Mac
     * @function
     * @param {String} str string to final update
     * @description
     * @example
     * md.digestString('aaa')
     */
    this.doFinalString = function(str) {
	throw "digestString(str) not supported for this alg/prov: " + this.algProv;
    };

    /**
     * performs final update on the digest using hexadecimal string, 
     * then completes the digest computation
     * @name doFinalHex
     * @memberOf KJUR.crypto.Mac
     * @function
     * @param {String} hex hexadecimal string to final update
     * @description
     * @example
     * md.digestHex('0f2abd')
     */
    this.doFinalHex = function(hex) {
	throw "digestHex(hex) not supported for this alg/prov: " + this.algProv;
    };

    /**
     * set password for Mac
     * @name setPassword
     * @memberOf KJUR.crypto.Mac
     * @function
     * @param {Object} pass password for Mac
     * @since crypto 1.1.7 jsrsasign 4.9.0
     * @description
     * This method will set password for (H)Mac internally.
     * Argument 'pass' can be specified as following:
     * <ul>
     * <li>even length string of 0..9, a..f or A-F: implicitly specified as hexadecimal string</li>
     * <li>not above string: implicitly specified as raw string</li>
     * <li>{rstr: "\x65\x70"}: explicitly specified as raw string</li>
     * <li>{hex: "6570"}: explicitly specified as hexacedimal string</li>
     * <li>{utf8: "秘密"}: explicitly specified as UTF8 string</li>
     * <li>{b64: "Mi78..=="}: explicitly specified as Base64 string</li>
     * <li>{b64u: "Mi7-_"}: explicitly specified as Base64URL string</li>
     * </ul>
     * It is *STRONGLY RECOMMENDED* that explicit representation of password argument
     * to avoid ambiguity. For example string  "6161" can mean a string "6161" or 
     * a hexadecimal string of "aa" (i.e. \x61\x61).
     * @example
     * mac = KJUR.crypto.Mac({'alg': 'hmacsha256'});
     * // set password by implicit raw string
     * mac.setPassword("\x65\x70\xb9\x0b");
     * mac.setPassword("password");
     * // set password by implicit hexadecimal string
     * mac.setPassword("6570b90b");
     * mac.setPassword("6570B90B");
     * // set password by explicit raw string
     * mac.setPassword({"rstr": "\x65\x70\xb9\x0b"});
     * // set password by explicit hexadecimal string
     * mac.setPassword({"hex": "6570b90b"});
     * // set password by explicit utf8 string
     * mac.setPassword({"utf8": "passwordパスワード");
     * // set password by explicit Base64 string
     * mac.setPassword({"b64": "Mb+c3f/=="});
     * // set password by explicit Base64URL string
     * mac.setPassword({"b64u": "Mb-c3f_"});
     */
    this.setPassword = function(pass) {
	// internal this.pass shall be CryptoJS DWord Object for CryptoJS bug
	// work around. CrytoJS HMac password can be passed by
	// raw string as described in the manual however it doesn't
	// work properly in some case. If password was passed
	// by CryptoJS DWord which is not described in the manual
	// it seems to work. (fixed since crypto 1.1.7)

	if (typeof pass == 'string') {
	    var hPass = pass;
	    if (pass.length % 2 == 1 || ! pass.match(/^[0-9A-Fa-f]+$/)) { // raw str
		hPass = rstrtohex(pass);
	    }
	    this.pass = CryptoJS.enc.Hex.parse(hPass);
	    return;
	}

	if (typeof pass != 'object')
	    throw "KJUR.crypto.Mac unsupported password type: " + pass;
	
	var hPass = null;
	if (pass.hex  !== undefined) {
	    if (pass.hex.length % 2 != 0 || ! pass.hex.match(/^[0-9A-Fa-f]+$/))
		throw "Mac: wrong hex password: " + pass.hex;
	    hPass = pass.hex;
	}
	if (pass.utf8 !== undefined) hPass = utf8tohex(pass.utf8);
	if (pass.rstr !== undefined) hPass = rstrtohex(pass.rstr);
	if (pass.b64  !== undefined) hPass = b64tohex(pass.b64);
	if (pass.b64u !== undefined) hPass = b64utohex(pass.b64u);

	if (hPass == null)
	    throw "KJUR.crypto.Mac unsupported password type: " + pass;

	this.pass = CryptoJS.enc.Hex.parse(hPass);
    };

    if (params !== undefined) {
	if (params.pass !== undefined) {
	    this.setPassword(params.pass);
	}
	if (params.alg !== undefined) {
	    this.algName = params.alg;
	    if (params['prov'] === undefined)
		this.provName = KJUR.crypto.Util.DEFAULTPROVIDER[this.algName];
	    this.setAlgAndProvider(this.algName, this.provName);
	}
    }
};

/**
 * Signature class which is very similar to java.security.Signature class
 * @name KJUR.crypto.Signature
 * @class Signature class which is very similar to java.security.Signature class
 * @param {Array} params parameters for constructor
 * @property {String} state Current state of this signature object whether 'SIGN', 'VERIFY' or null
 * @description
 * <br/>
 * As for params of constructor's argument, it can be specify following attributes:
 * <ul>
 * <li>alg - signature algorithm name (ex. {MD5,SHA1,SHA224,SHA256,SHA384,SHA512,RIPEMD160}with{RSA,ECDSA,DSA})</li>
 * <li>provider - currently 'cryptojs/jsrsa' only</li>
 * </ul>
 * <h4>SUPPORTED ALGORITHMS AND PROVIDERS</h4>
 * This Signature class supports following signature algorithm and provider names:
 * <ul>
 * <li>MD5withRSA - cryptojs/jsrsa</li>
 * <li>SHA1withRSA - cryptojs/jsrsa</li>
 * <li>SHA224withRSA - cryptojs/jsrsa</li>
 * <li>SHA256withRSA - cryptojs/jsrsa</li>
 * <li>SHA384withRSA - cryptojs/jsrsa</li>
 * <li>SHA512withRSA - cryptojs/jsrsa</li>
 * <li>RIPEMD160withRSA - cryptojs/jsrsa</li>
 * <li>MD5withECDSA - cryptojs/jsrsa</li>
 * <li>SHA1withECDSA - cryptojs/jsrsa</li>
 * <li>SHA224withECDSA - cryptojs/jsrsa</li>
 * <li>SHA256withECDSA - cryptojs/jsrsa</li>
 * <li>SHA384withECDSA - cryptojs/jsrsa</li>
 * <li>SHA512withECDSA - cryptojs/jsrsa</li>
 * <li>RIPEMD160withECDSA - cryptojs/jsrsa</li>
 * <li>MD5withRSAandMGF1 - cryptojs/jsrsa</li>
 * <li>SHA1withRSAandMGF1 - cryptojs/jsrsa</li>
 * <li>SHA224withRSAandMGF1 - cryptojs/jsrsa</li>
 * <li>SHA256withRSAandMGF1 - cryptojs/jsrsa</li>
 * <li>SHA384withRSAandMGF1 - cryptojs/jsrsa</li>
 * <li>SHA512withRSAandMGF1 - cryptojs/jsrsa</li>
 * <li>RIPEMD160withRSAandMGF1 - cryptojs/jsrsa</li>
 * <li>SHA1withDSA - cryptojs/jsrsa</li>
 * <li>SHA224withDSA - cryptojs/jsrsa</li>
 * <li>SHA256withDSA - cryptojs/jsrsa</li>
 * </ul>
 * Here are supported elliptic cryptographic curve names and their aliases for ECDSA:
 * <ul>
 * <li>secp256k1</li>
 * <li>secp256r1, NIST P-256, P-256, prime256v1</li>
 * <li>secp384r1, NIST P-384, P-384</li>
 * </ul>
 * NOTE1: DSA signing algorithm is also supported since crypto 1.1.5.
 * <h4>EXAMPLES</h4>
 * @example
 * // RSA signature generation
 * var sig = new KJUR.crypto.Signature({"alg": "SHA1withRSA"});
 * sig.init(prvKeyPEM);
 * sig.updateString('aaa');
 * var hSigVal = sig.sign();
 *
 * // DSA signature validation
 * var sig2 = new KJUR.crypto.Signature({"alg": "SHA1withDSA"});
 * sig2.init(certPEM);
 * sig.updateString('aaa');
 * var isValid = sig2.verify(hSigVal);
 * 
 * // ECDSA signing
 * var sig = new KJUR.crypto.Signature({'alg':'SHA1withECDSA'});
 * sig.init(prvKeyPEM);
 * sig.updateString('aaa');
 * var sigValueHex = sig.sign();
 *
 * // ECDSA verifying
 * var sig2 = new KJUR.crypto.Signature({'alg':'SHA1withECDSA'});
 * sig.init(certPEM);
 * sig.updateString('aaa');
 * var isValid = sig.verify(sigValueHex);
 */
KJUR.crypto.Signature = function(params) {
    var prvKey = null; // RSAKey/KJUR.crypto.{ECDSA,DSA} object for signing
    var pubKey = null; // RSAKey/KJUR.crypto.{ECDSA,DSA} object for verifying

    var md = null; // KJUR.crypto.MessageDigest object
    var sig = null;
    var algName = null;
    var provName = null;
    var algProvName = null;
    var mdAlgName = null;
    var pubkeyAlgName = null;	// rsa,ecdsa,rsaandmgf1(=rsapss)
    var state = null;
    var pssSaltLen = -1;
    var initParams = null;

    var sHashHex = null; // hex hash value for hex
    var hDigestInfo = null;
    var hPaddedDigestInfo = null;
    var hSign = null;

    this._setAlgNames = function() {
	if (this.algName.match(/^(.+)with(.+)$/)) {
	    this.mdAlgName = RegExp.$1.toLowerCase();
	    this.pubkeyAlgName = RegExp.$2.toLowerCase();
	}
    };

    this._zeroPaddingOfSignature = function(hex, bitLength) {
	var s = "";
	var nZero = bitLength / 4 - hex.length;
	for (var i = 0; i < nZero; i++) {
	    s = s + "0";
	}
	return s + hex;
    };

    /**
     * set signature algorithm and provider
     * @name setAlgAndProvider
     * @memberOf KJUR.crypto.Signature
     * @function
     * @param {String} alg signature algorithm name
     * @param {String} prov provider name
     * @description
     * @example
     * md.setAlgAndProvider('SHA1withRSA', 'cryptojs/jsrsa');
     */
    this.setAlgAndProvider = function(alg, prov) {
	this._setAlgNames();
	if (prov != 'cryptojs/jsrsa')
	    throw "provider not supported: " + prov;

	if (':md5:sha1:sha224:sha256:sha384:sha512:ripemd160:'.indexOf(this.mdAlgName) != -1) {
	    try {
		this.md = new KJUR.crypto.MessageDigest({'alg':this.mdAlgName});
	    } catch (ex) {
		throw "setAlgAndProvider hash alg set fail alg=" +
                      this.mdAlgName + "/" + ex;
	    }

	    this.init = function(keyparam, pass) {
		var keyObj = null;
		try {
		    if (pass === undefined) {
			keyObj = KEYUTIL.getKey(keyparam);
		    } else {
			keyObj = KEYUTIL.getKey(keyparam, pass);
		    }
		} catch (ex) {
		    throw "init failed:" + ex;
		}

		if (keyObj.isPrivate === true) {
		    this.prvKey = keyObj;
		    this.state = "SIGN";
		} else if (keyObj.isPublic === true) {
		    this.pubKey = keyObj;
		    this.state = "VERIFY";
		} else {
		    throw "init failed.:" + keyObj;
		}
	    };

	    this.initSign = function(params) {
		if (typeof params['ecprvhex'] == 'string' &&
                    typeof params['eccurvename'] == 'string') {
		    this.ecprvhex = params['ecprvhex'];
		    this.eccurvename = params['eccurvename'];
		} else {
		    this.prvKey = params;
		}
		this.state = "SIGN";
	    };

	    this.initVerifyByPublicKey = function(params) {
		if (typeof params['ecpubhex'] == 'string' &&
		    typeof params['eccurvename'] == 'string') {
		    this.ecpubhex = params['ecpubhex'];
		    this.eccurvename = params['eccurvename'];
		} else if (params instanceof KJUR.crypto.ECDSA) {
		    this.pubKey = params;
		} else if (params instanceof RSAKey) {
		    this.pubKey = params;
		}
		this.state = "VERIFY";
	    };

	    this.initVerifyByCertificatePEM = function(certPEM) {
		var x509 = new X509();
		x509.readCertPEM(certPEM);
		this.pubKey = x509.subjectPublicKeyRSA;
		this.state = "VERIFY";
	    };

	    this.updateString = function(str) {
		this.md.updateString(str);
	    };

	    this.updateHex = function(hex) {
		this.md.updateHex(hex);
	    };

	    this.sign = function() {
		this.sHashHex = this.md.digest();
		if (typeof this.ecprvhex != "undefined" &&
		    typeof this.eccurvename != "undefined") {
		    var ec = new KJUR.crypto.ECDSA({'curve': this.eccurvename});
		    this.hSign = ec.signHex(this.sHashHex, this.ecprvhex);
		} else if (this.prvKey instanceof RSAKey &&
		           this.pubkeyAlgName == "rsaandmgf1") {
		    this.hSign = this.prvKey.signWithMessageHashPSS(this.sHashHex,
								    this.mdAlgName,
								    this.pssSaltLen);
		} else if (this.prvKey instanceof RSAKey &&
			   this.pubkeyAlgName == "rsa") {
		    this.hSign = this.prvKey.signWithMessageHash(this.sHashHex,
								 this.mdAlgName);
		} else if (this.prvKey instanceof KJUR.crypto.ECDSA) {
		    this.hSign = this.prvKey.signWithMessageHash(this.sHashHex);
		} else if (this.prvKey instanceof KJUR.crypto.DSA) {
		    this.hSign = this.prvKey.signWithMessageHash(this.sHashHex);
		} else {
		    throw "Signature: unsupported public key alg: " + this.pubkeyAlgName;
		}
		return this.hSign;
	    };
	    this.signString = function(str) {
		this.updateString(str);
		return this.sign();
	    };
	    this.signHex = function(hex) {
		this.updateHex(hex);
		return this.sign();
	    };
	    this.verify = function(hSigVal) {
	        this.sHashHex = this.md.digest();
		if (typeof this.ecpubhex != "undefined" &&
		    typeof this.eccurvename != "undefined") {
		    var ec = new KJUR.crypto.ECDSA({curve: this.eccurvename});
		    return ec.verifyHex(this.sHashHex, hSigVal, this.ecpubhex);
		} else if (this.pubKey instanceof RSAKey &&
			   this.pubkeyAlgName == "rsaandmgf1") {
		    return this.pubKey.verifyWithMessageHashPSS(this.sHashHex, hSigVal, 
								this.mdAlgName,
								this.pssSaltLen);
		} else if (this.pubKey instanceof RSAKey &&
			   this.pubkeyAlgName == "rsa") {
		    return this.pubKey.verifyWithMessageHash(this.sHashHex, hSigVal);
		} else if (this.pubKey instanceof KJUR.crypto.ECDSA) {
		    return this.pubKey.verifyWithMessageHash(this.sHashHex, hSigVal);
		} else if (this.pubKey instanceof KJUR.crypto.DSA) {
		    return this.pubKey.verifyWithMessageHash(this.sHashHex, hSigVal);
		} else {
		    throw "Signature: unsupported public key alg: " + this.pubkeyAlgName;
		}
	    };
	}
    };

    /**
     * Initialize this object for signing or verifying depends on key
     * @name init
     * @memberOf KJUR.crypto.Signature
     * @function
     * @param {Object} key specifying public or private key as plain/encrypted PKCS#5/8 PEM file, certificate PEM or {@link RSAKey}, {@link KJUR.crypto.DSA} or {@link KJUR.crypto.ECDSA} object
     * @param {String} pass (OPTION) passcode for encrypted private key
     * @since crypto 1.1.3
     * @description
     * This method is very useful initialize method for Signature class since
     * you just specify key then this method will automatically initialize it
     * using {@link KEYUTIL.getKey} method.
     * As for 'key',  following argument type are supported:
     * <h5>signing</h5>
     * <ul>
     * <li>PEM formatted PKCS#8 encrypted RSA/ECDSA private key concluding "BEGIN ENCRYPTED PRIVATE KEY"</li>
     * <li>PEM formatted PKCS#5 encrypted RSA/DSA private key concluding "BEGIN RSA/DSA PRIVATE KEY" and ",ENCRYPTED"</li>
     * <li>PEM formatted PKCS#8 plain RSA/ECDSA private key concluding "BEGIN PRIVATE KEY"</li>
     * <li>PEM formatted PKCS#5 plain RSA/DSA private key concluding "BEGIN RSA/DSA PRIVATE KEY" without ",ENCRYPTED"</li>
     * <li>RSAKey object of private key</li>
     * <li>KJUR.crypto.ECDSA object of private key</li>
     * <li>KJUR.crypto.DSA object of private key</li>
     * </ul>
     * <h5>verification</h5>
     * <ul>
     * <li>PEM formatted PKCS#8 RSA/EC/DSA public key concluding "BEGIN PUBLIC KEY"</li>
     * <li>PEM formatted X.509 certificate with RSA/EC/DSA public key concluding
     *     "BEGIN CERTIFICATE", "BEGIN X509 CERTIFICATE" or "BEGIN TRUSTED CERTIFICATE".</li>
     * <li>RSAKey object of public key</li>
     * <li>KJUR.crypto.ECDSA object of public key</li>
     * <li>KJUR.crypto.DSA object of public key</li>
     * </ul>
     * @example
     * sig.init(sCertPEM)
     */
    this.init = function(key, pass) {
	throw "init(key, pass) not supported for this alg:prov=" +
	      this.algProvName;
    };

    /**
     * Initialize this object for verifying with a public key
     * @name initVerifyByPublicKey
     * @memberOf KJUR.crypto.Signature
     * @function
     * @param {Object} param RSAKey object of public key or associative array for ECDSA
     * @since 1.0.2
     * @deprecated from crypto 1.1.5. please use init() method instead.
     * @description
     * Public key information will be provided as 'param' parameter and the value will be
     * following:
     * <ul>
     * <li>{@link RSAKey} object for RSA verification</li>
     * <li>associative array for ECDSA verification
     *     (ex. <code>{'ecpubhex': '041f..', 'eccurvename': 'secp256r1'}</code>)
     * </li>
     * </ul>
     * @example
     * sig.initVerifyByPublicKey(rsaPrvKey)
     */
    this.initVerifyByPublicKey = function(rsaPubKey) {
	throw "initVerifyByPublicKey(rsaPubKeyy) not supported for this alg:prov=" +
	      this.algProvName;
    };

    /**
     * Initialize this object for verifying with a certficate
     * @name initVerifyByCertificatePEM
     * @memberOf KJUR.crypto.Signature
     * @function
     * @param {String} certPEM PEM formatted string of certificate
     * @since 1.0.2
     * @deprecated from crypto 1.1.5. please use init() method instead.
     * @description
     * @example
     * sig.initVerifyByCertificatePEM(certPEM)
     */
    this.initVerifyByCertificatePEM = function(certPEM) {
	throw "initVerifyByCertificatePEM(certPEM) not supported for this alg:prov=" +
	    this.algProvName;
    };

    /**
     * Initialize this object for signing
     * @name initSign
     * @memberOf KJUR.crypto.Signature
     * @function
     * @param {Object} param RSAKey object of public key or associative array for ECDSA
     * @deprecated from crypto 1.1.5. please use init() method instead.
     * @description
     * Private key information will be provided as 'param' parameter and the value will be
     * following:
     * <ul>
     * <li>{@link RSAKey} object for RSA signing</li>
     * <li>associative array for ECDSA signing
     *     (ex. <code>{'ecprvhex': '1d3f..', 'eccurvename': 'secp256r1'}</code>)</li>
     * </ul>
     * @example
     * sig.initSign(prvKey)
     */
    this.initSign = function(prvKey) {
	throw "initSign(prvKey) not supported for this alg:prov=" + this.algProvName;
    };

    /**
     * Updates the data to be signed or verified by a string
     * @name updateString
     * @memberOf KJUR.crypto.Signature
     * @function
     * @param {String} str string to use for the update
     * @description
     * @example
     * sig.updateString('aaa')
     */
    this.updateString = function(str) {
	throw "updateString(str) not supported for this alg:prov=" + this.algProvName;
    };

    /**
     * Updates the data to be signed or verified by a hexadecimal string
     * @name updateHex
     * @memberOf KJUR.crypto.Signature
     * @function
     * @param {String} hex hexadecimal string to use for the update
     * @description
     * @example
     * sig.updateHex('1f2f3f')
     */
    this.updateHex = function(hex) {
	throw "updateHex(hex) not supported for this alg:prov=" + this.algProvName;
    };

    /**
     * Returns the signature bytes of all data updates as a hexadecimal string
     * @name sign
     * @memberOf KJUR.crypto.Signature
     * @function
     * @return the signature bytes as a hexadecimal string
     * @description
     * @example
     * var hSigValue = sig.sign()
     */
    this.sign = function() {
	throw "sign() not supported for this alg:prov=" + this.algProvName;
    };

    /**
     * performs final update on the sign using string, then returns the signature bytes of all data updates as a hexadecimal string
     * @name signString
     * @memberOf KJUR.crypto.Signature
     * @function
     * @param {String} str string to final update
     * @return the signature bytes of a hexadecimal string
     * @description
     * @example
     * var hSigValue = sig.signString('aaa')
     */
    this.signString = function(str) {
	throw "digestString(str) not supported for this alg:prov=" + this.algProvName;
    };

    /**
     * performs final update on the sign using hexadecimal string, then returns the signature bytes of all data updates as a hexadecimal string
     * @name signHex
     * @memberOf KJUR.crypto.Signature
     * @function
     * @param {String} hex hexadecimal string to final update
     * @return the signature bytes of a hexadecimal string
     * @description
     * @example
     * var hSigValue = sig.signHex('1fdc33')
     */
    this.signHex = function(hex) {
	throw "digestHex(hex) not supported for this alg:prov=" + this.algProvName;
    };

    /**
     * verifies the passed-in signature.
     * @name verify
     * @memberOf KJUR.crypto.Signature
     * @function
     * @param {String} str string to final update
     * @return {Boolean} true if the signature was verified, otherwise false
     * @description
     * @example
     * var isValid = sig.verify('1fbcefdca4823a7(snip)')
     */
    this.verify = function(hSigVal) {
	throw "verify(hSigVal) not supported for this alg:prov=" + this.algProvName;
    };

    this.initParams = params;

    if (params !== undefined) {
	if (params['alg'] !== undefined) {
	    this.algName = params['alg'];
	    if (params['prov'] === undefined) {
		this.provName = KJUR.crypto.Util.DEFAULTPROVIDER[this.algName];
	    } else {
		this.provName = params['prov'];
	    }
	    this.algProvName = this.algName + ":" + this.provName;
	    this.setAlgAndProvider(this.algName, this.provName);
	    this._setAlgNames();
	}

	if (params['psssaltlen'] !== undefined) this.pssSaltLen = params['psssaltlen'];

	if (params['prvkeypem'] !== undefined) {
	    if (params['prvkeypas'] !== undefined) {
		throw "both prvkeypem and prvkeypas parameters not supported";
	    } else {
		try {
		    var prvKey = new RSAKey();
		    prvKey.readPrivateKeyFromPEMString(params['prvkeypem']);
		    this.initSign(prvKey);
		} catch (ex) {
		    throw "fatal error to load pem private key: " + ex;
		}
	    }
	}
    }
};

/**
 * static object for cryptographic function utilities
 * @name KJUR.crypto.OID
 * @class static object for cryptography related OIDs
 * @property {Array} oidhex2name key value of hexadecimal OID and its name
 *           (ex. '2a8648ce3d030107' and 'secp256r1')
 * @since crypto 1.1.3
 * @description
 */


KJUR.crypto.OID = new function() {
    this.oidhex2name = {
	'2a864886f70d010101': 'rsaEncryption',
	'2a8648ce3d0201': 'ecPublicKey',
	'2a8648ce380401': 'dsa',
	'2a8648ce3d030107': 'secp256r1',
	'2b8104001f': 'secp192k1',
	'2b81040021': 'secp224r1',
	'2b8104000a': 'secp256k1',
	'2b81040023': 'secp521r1',
	'2b81040022': 'secp384r1',
	'2a8648ce380403': 'SHA1withDSA', // 1.2.840.10040.4.3
	'608648016503040301': 'SHA224withDSA', // 2.16.840.1.101.3.4.3.1
	'608648016503040302': 'SHA256withDSA'  // 2.16.840.1.101.3.4.3.2
    };
};

exports.KJUR = KJUR;
module.exports = exports;
/*! rsapem-1.1.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license
 */
//
// rsa-pem.js - adding function for reading/writing PKCS#1 PEM private key
//              to RSAKey class.
//
// version: 1.1.1 (2013-Apr-12)
//
// Copyright (c) 2010-2013 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 on:
//
//
//
// _RSApem_pemToBase64(sPEM)
//
//   removing PEM header, PEM footer and space characters including
//   new lines from PEM formatted RSA private key string.
//

/**
 * @fileOverview
 * @name rsapem-1.1.js
 * @author Kenji Urushima kenji.urushima@gmail.com
 * @version 1.1
 * @license <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
 */

var ASN1HEX = require('./asn1hex-1.1.js').ASN1HEX;
var b64tohex = require('./base64.js').b64tohex;
var RSAKey = require('./rsa2.js').RSAKey;

function _rsapem_pemToBase64(sPEMPrivateKey) {
  var s = sPEMPrivateKey;
  s = s.replace("-----BEGIN RSA PRIVATE KEY-----", "");
  s = s.replace("-----END RSA PRIVATE KEY-----", "");
  s = s.replace(/[ \n]+/g, "");
  return s;
}

function _rsapem_getPosArrayOfChildrenFromHex(hPrivateKey) {
  var a = new Array();
  var v1 = ASN1HEX.getStartPosOfV_AtObj(hPrivateKey, 0);
  var n1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, v1);
  var e1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, n1);
  var d1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, e1);
  var p1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, d1);
  var q1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, p1);
  var dp1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, q1);
  var dq1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, dp1);
  var co1 = ASN1HEX.getPosOfNextSibling_AtObj(hPrivateKey, dq1);
  a.push(v1, n1, e1, d1, p1, q1, dp1, dq1, co1);
  return a;
}

function _rsapem_getHexValueArrayOfChildrenFromHex(hPrivateKey) {
  var posArray = _rsapem_getPosArrayOfChildrenFromHex(hPrivateKey);
  var v =  ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[0]);
  var n =  ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[1]);
  var e =  ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[2]);
  var d =  ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[3]);
  var p =  ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[4]);
  var q =  ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[5]);
  var dp = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[6]);
  var dq = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[7]);
  var co = ASN1HEX.getHexOfV_AtObj(hPrivateKey, posArray[8]);
  var a = new Array();
  a.push(v, n, e, d, p, q, dp, dq, co);
  return a;
}

/**
 * read RSA private key from a ASN.1 hexadecimal string
 * @name readPrivateKeyFromASN1HexString
 * @memberOf RSAKey#
 * @function
 * @param {String} keyHex ASN.1 hexadecimal string of PKCS#1 private key.
 * @since 1.1.1
 */
function _rsapem_readPrivateKeyFromASN1HexString(keyHex) {
  var a = _rsapem_getHexValueArrayOfChildrenFromHex(keyHex);
  this.setPrivateEx(a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8]);
}

/**
 * read PKCS#1 private key from a string
 * @name readPrivateKeyFromPEMString
 * @memberOf RSAKey#
 * @function
 * @param {String} keyPEM string of PKCS#1 private key.
 */
function _rsapem_readPrivateKeyFromPEMString(keyPEM) {
  var keyB64 = _rsapem_pemToBase64(keyPEM);
  var keyHex = b64tohex(keyB64) // depends base64.js
  var a = _rsapem_getHexValueArrayOfChildrenFromHex(keyHex);
  this.setPrivateEx(a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8]);
}

RSAKey.prototype.readPrivateKeyFromPEMString = _rsapem_readPrivateKeyFromPEMString;
RSAKey.prototype.readPrivateKeyFromASN1HexString = _rsapem_readPrivateKeyFromASN1HexString;

exports.RSAKey = RSAKey;
module.exports = exports;
/*! rsasign-1.2.7.js (c) 2012 Kenji Urushima | kjur.github.com/jsrsasign/license
 */
/*
 * rsa-sign.js - adding signing functions to RSAKey class.
 *
 * version: 1.2.7 (2013 Aug 25)
 *
 * Copyright (c) 2010-2013 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.
 */

/**
 * @fileOverview
 * @name rsasign-1.2.js
 * @author Kenji Urushima kenji.urushima@gmail.com
 * @version rsasign 1.2.7
 * @license <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
 */

var intShim = require('jsbn');
var BigInteger = intShim.BigInteger ? intShim.BigInteger : intShim;
var RSAKey = require('./rsapem-1.1.js').RSAKey

var _RE_HEXDECONLY = new RegExp("");
_RE_HEXDECONLY.compile("[^0-9a-f]", "gi");

// ========================================================================
// Signature Generation
// ========================================================================

function _rsasign_getHexPaddedDigestInfoForString(s, keySize, hashAlg) {
    var hashFunc = function(s) { return KJUR.crypto.Util.hashString(s, hashAlg); };
    var sHashHex = hashFunc(s);

    return KJUR.crypto.Util.getPaddedDigestInfoHex(sHashHex, hashAlg, keySize);
}

function _zeroPaddingOfSignature(hex, bitLength) {
    var s = "";
    var nZero = bitLength / 4 - hex.length;
    for (var i = 0; i < nZero; i++) {
	s = s + "0";
    }
    return s + hex;
}

/**
 * sign for a message string with RSA private key.<br/>
 * @name signString
 * @memberOf RSAKey
 * @function
 * @param {String} s message string to be signed.
 * @param {String} hashAlg hash algorithm name for signing.<br/>
 * @return returns hexadecimal string of signature value.
 */
function _rsasign_signString(s, hashAlg) {
    var hashFunc = function(s) { return KJUR.crypto.Util.hashString(s, hashAlg); };
    var sHashHex = hashFunc(s);

    return this.signWithMessageHash(sHashHex, hashAlg);
}

/**
 * sign hash value of message to be signed with RSA private key.<br/>
 * @name signWithMessageHash
 * @memberOf RSAKey
 * @function
 * @param {String} sHashHex hexadecimal string of hash value of message to be signed.
 * @param {String} hashAlg hash algorithm name for signing.<br/>
 * @return returns hexadecimal string of signature value.
 * @since rsasign 1.2.6
 */
function _rsasign_signWithMessageHash(sHashHex, hashAlg) {
    var hPM = KJUR.crypto.Util.getPaddedDigestInfoHex(sHashHex, hashAlg, this.n.bitLength());
    var biPaddedMessage = parseBigInt(hPM, 16);
    var biSign = this.doPrivate(biPaddedMessage);
    var hexSign = biSign.toString(16);
    return _zeroPaddingOfSignature(hexSign, this.n.bitLength());
}

function _rsasign_signStringWithSHA1(s) {
    return _rsasign_signString.call(this, s, 'sha1');
}

function _rsasign_signStringWithSHA256(s) {
    return _rsasign_signString.call(this, s, 'sha256');
}

// PKCS#1 (PSS) mask generation function
function pss_mgf1_str(seed, len, hash) {
    var mask = '', i = 0;

    while (mask.length < len) {
        mask += hextorstr(hash(rstrtohex(seed + String.fromCharCode.apply(String, [
                (i & 0xff000000) >> 24,
                (i & 0x00ff0000) >> 16,
                (i & 0x0000ff00) >> 8,
                i & 0x000000ff]))));
        i += 1;
    }

    return mask;
}

/**
 * sign for a message string with RSA private key by PKCS#1 PSS signing.<br/>
 * @name signStringPSS
 * @memberOf RSAKey
 * @function
 * @param {String} s message string to be signed.
 * @param {String} hashAlg hash algorithm name for signing.
 * @param {Integer} sLen salt byte length from 0 to (keybytelen - hashbytelen - 2).
 *        There are two special values:
 *        <ul>
 *        <li>-1: sets the salt length to the digest length</li>
 *        <li>-2: sets the salt length to maximum permissible value
 *           (i.e. keybytelen - hashbytelen - 2)</li>
 *        </ul>
 *        DEFAULT is -1. (NOTE: OpenSSL's default is -2.)
 * @return returns hexadecimal string of signature value.
 */
function _rsasign_signStringPSS(s, hashAlg, sLen) {
    var hashFunc = function(sHex) { return KJUR.crypto.Util.hashHex(sHex, hashAlg); } 
    var hHash = hashFunc(rstrtohex(s));

    if (sLen === undefined) sLen = -1;
    return this.signWithMessageHashPSS(hHash, hashAlg, sLen);
}

/**
 * sign hash value of message with RSA private key by PKCS#1 PSS signing.<br/>
 * @name signWithMessageHashPSS
 * @memberOf RSAKey
 * @function
 * @param {String} hHash hexadecimal hash value of message to be signed.
 * @param {String} hashAlg hash algorithm name for signing.
 * @param {Integer} sLen salt byte length from 0 to (keybytelen - hashbytelen - 2).
 *        There are two special values:
 *        <ul>
 *        <li>-1: sets the salt length to the digest length</li>
 *        <li>-2: sets the salt length to maximum permissible value
 *           (i.e. keybytelen - hashbytelen - 2)</li>
 *        </ul>
 *        DEFAULT is -1. (NOTE: OpenSSL's default is -2.)
 * @return returns hexadecimal string of signature value.
 * @since rsasign 1.2.6
 */
function _rsasign_signWithMessageHashPSS(hHash, hashAlg, sLen) {
    var mHash = hextorstr(hHash);
    var hLen = mHash.length;
    var emBits = this.n.bitLength() - 1;
    var emLen = Math.ceil(emBits / 8);
    var i;
    var hashFunc = function(sHex) { return KJUR.crypto.Util.hashHex(sHex, hashAlg); } 

    if (sLen === -1 || sLen === undefined) {
        sLen = hLen; // same as hash length
    } else if (sLen === -2) {
        sLen = emLen - hLen - 2; // maximum
    } else if (sLen < -2) {
        throw "invalid salt length";
    }

    if (emLen < (hLen + sLen + 2)) {
        throw "data too long";
    }

    var salt = '';

    if (sLen > 0) {
        salt = new Array(sLen);
        new SecureRandom().nextBytes(salt);
        salt = String.fromCharCode.apply(String, salt);
    }

    var H = hextorstr(hashFunc(rstrtohex('\x00\x00\x00\x00\x00\x00\x00\x00' + mHash + salt)));
    var PS = [];

    for (i = 0; i < emLen - sLen - hLen - 2; i += 1) {
        PS[i] = 0x00;
    }

    var DB = String.fromCharCode.apply(String, PS) + '\x01' + salt;
    var dbMask = pss_mgf1_str(H, DB.length, hashFunc);
    var maskedDB = [];

    for (i = 0; i < DB.length; i += 1) {
        maskedDB[i] = DB.charCodeAt(i) ^ dbMask.charCodeAt(i);
    }

    var mask = (0xff00 >> (8 * emLen - emBits)) & 0xff;
    maskedDB[0] &= ~mask;

    for (i = 0; i < hLen; i++) {
        maskedDB.push(H.charCodeAt(i));
    }

    maskedDB.push(0xbc);

    return _zeroPaddingOfSignature(this.doPrivate(new BigInteger(maskedDB)).toString(16),
				   this.n.bitLength());
}

// ========================================================================
// Signature Verification
// ========================================================================

function _rsasign_getDecryptSignatureBI(biSig, hN, hE) {
    var rsa = new RSAKey();
    rsa.setPublic(hN, hE);
    var biDecryptedSig = rsa.doPublic(biSig);
    return biDecryptedSig;
}

function _rsasign_getHexDigestInfoFromSig(biSig, hN, hE) {
    var biDecryptedSig = _rsasign_getDecryptSignatureBI(biSig, hN, hE);
    var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
    return hDigestInfo;
}

function _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo) {
    for (var algName in KJUR.crypto.Util.DIGESTINFOHEAD) {
	var head = KJUR.crypto.Util.DIGESTINFOHEAD[algName];
	var len = head.length;
	if (hDigestInfo.substring(0, len) == head) {
	    var a = [algName, hDigestInfo.substring(len)];
	    return a;
	}
    }
    return [];
}

function _rsasign_verifySignatureWithArgs(sMsg, biSig, hN, hE) {
    var hDigestInfo = _rsasign_getHexDigestInfoFromSig(biSig, hN, hE);
    var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
    if (digestInfoAry.length == 0) return false;
    var algName = digestInfoAry[0];
    var diHashValue = digestInfoAry[1];
    var ff = function(s) { return KJUR.crypto.Util.hashString(s, algName); };
    var msgHashValue = ff(sMsg);
    return (diHashValue == msgHashValue);
}

function _rsasign_verifyHexSignatureForMessage(hSig, sMsg) {
    var biSig = parseBigInt(hSig, 16);
    var result = _rsasign_verifySignatureWithArgs(sMsg, biSig,
						  this.n.toString(16),
						  this.e.toString(16));
    return result;
}

/**
 * verifies a sigature for a message string with RSA public key.<br/>
 * @name verifyString
 * @memberOf RSAKey#
 * @function
 * @param {String} sMsg message string to be verified.
 * @param {String} hSig hexadecimal string of siganture.<br/>
 *                 non-hexadecimal charactors including new lines will be ignored.
 * @return returns 1 if valid, otherwise 0
 */
function _rsasign_verifyString(sMsg, hSig) {
    hSig = hSig.replace(_RE_HEXDECONLY, '');
    hSig = hSig.replace(/[ \n]+/g, "");
    var biSig = parseBigInt(hSig, 16);
    if (biSig.bitLength() > this.n.bitLength()) return 0;
    var biDecryptedSig = this.doPublic(biSig);
    var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
    var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
  
    if (digestInfoAry.length == 0) return false;
    var algName = digestInfoAry[0];
    var diHashValue = digestInfoAry[1];
    var ff = function(s) { return KJUR.crypto.Util.hashString(s, algName); };
    var msgHashValue = ff(sMsg);
    return (diHashValue == msgHashValue);
}

/**
 * verifies a sigature for a message string with RSA public key.<br/>
 * @name verifyWithMessageHash
 * @memberOf RSAKey
 * @function
 * @param {String} sHashHex hexadecimal hash value of message to be verified.
 * @param {String} hSig hexadecimal string of siganture.<br/>
 *                 non-hexadecimal charactors including new lines will be ignored.
 * @return returns 1 if valid, otherwise 0
 * @since rsasign 1.2.6
 */
function _rsasign_verifyWithMessageHash(sHashHex, hSig) {
    hSig = hSig.replace(_RE_HEXDECONLY, '');
    hSig = hSig.replace(/[ \n]+/g, "");
    var biSig = parseBigInt(hSig, 16);
    if (biSig.bitLength() > this.n.bitLength()) return 0;
    var biDecryptedSig = this.doPublic(biSig);
    var hDigestInfo = biDecryptedSig.toString(16).replace(/^1f+00/, '');
    var digestInfoAry = _rsasign_getAlgNameAndHashFromHexDisgestInfo(hDigestInfo);
  
    if (digestInfoAry.length == 0) return false;
    var algName = digestInfoAry[0];
    var diHashValue = digestInfoAry[1];
    return (diHashValue == sHashHex);
}

/**
 * verifies a sigature for a message string with RSA public key by PKCS#1 PSS sign.<br/>
 * @name verifyStringPSS
 * @memberOf RSAKey
 * @function
 * @param {String} sMsg message string to be verified.
 * @param {String} hSig hexadecimal string of signature value
 * @param {String} hashAlg hash algorithm name
 * @param {Integer} sLen salt byte length from 0 to (keybytelen - hashbytelen - 2).
 *        There are two special values:
 *        <ul>
 *        <li>-1: sets the salt length to the digest length</li>
 *        <li>-2: sets the salt length to maximum permissible value
 *           (i.e. keybytelen - hashbytelen - 2)</li>
 *        </ul>
 *        DEFAULT is -1. (NOTE: OpenSSL's default is -2.)
 * @return returns true if valid, otherwise false
 */
function _rsasign_verifyStringPSS(sMsg, hSig, hashAlg, sLen) {
    var hashFunc = function(sHex) { return KJUR.crypto.Util.hashHex(sHex, hashAlg); };
    var hHash = hashFunc(rstrtohex(sMsg));

    if (sLen === undefined) sLen = -1;
    return this.verifyWithMessageHashPSS(hHash, hSig, hashAlg, sLen);
}

/**
 * verifies a sigature for a hash value of message string with RSA public key by PKCS#1 PSS sign.<br/>
 * @name verifyWithMessageHashPSS
 * @memberOf RSAKey
 * @function
 * @param {String} hHash hexadecimal hash value of message string to be verified.
 * @param {String} hSig hexadecimal string of signature value
 * @param {String} hashAlg hash algorithm name
 * @param {Integer} sLen salt byte length from 0 to (keybytelen - hashbytelen - 2).
 *        There are two special values:
 *        <ul>
 *        <li>-1: sets the salt length to the digest length</li>
 *        <li>-2: sets the salt length to maximum permissible value
 *           (i.e. keybytelen - hashbytelen - 2)</li>
 *        </ul>
 *        DEFAULT is -1 (NOTE: OpenSSL's default is -2.)
 * @return returns true if valid, otherwise false
 * @since rsasign 1.2.6
 */
function _rsasign_verifyWithMessageHashPSS(hHash, hSig, hashAlg, sLen) {
    var biSig = new BigInteger(hSig, 16);

    if (biSig.bitLength() > this.n.bitLength()) {
        return false;
    }

    var hashFunc = function(sHex) { return KJUR.crypto.Util.hashHex(sHex, hashAlg); };
    var mHash = hextorstr(hHash);
    var hLen = mHash.length;
    var emBits = this.n.bitLength() - 1;
    var emLen = Math.ceil(emBits / 8);
    var i;

    if (sLen === -1 || sLen === undefined) {
        sLen = hLen; // same as hash length
    } else if (sLen === -2) {
        sLen = emLen - hLen - 2; // recover
    } else if (sLen < -2) {
        throw "invalid salt length";
    }

    if (emLen < (hLen + sLen + 2)) {
        throw "data too long";
    }

    var em = this.doPublic(biSig).toByteArray();

    for (i = 0; i < em.length; i += 1) {
        em[i] &= 0xff;
    }

    while (em.length < emLen) {
        em.unshift(0);
    }

    if (em[emLen -1] !== 0xbc) {
        throw "encoded message does not end in 0xbc";
    }

    em = String.fromCharCode.apply(String, em);

    var maskedDB = em.substr(0, emLen - hLen - 1);
    var H = em.substr(maskedDB.length, hLen);

    var mask = (0xff00 >> (8 * emLen - emBits)) & 0xff;

    if ((maskedDB.charCodeAt(0) & mask) !== 0) {
        throw "bits beyond keysize not zero";
    }

    var dbMask = pss_mgf1_str(H, maskedDB.length, hashFunc);
    var DB = [];

    for (i = 0; i < maskedDB.length; i += 1) {
        DB[i] = maskedDB.charCodeAt(i) ^ dbMask.charCodeAt(i);
    }

    DB[0] &= ~mask;

    var checkLen = emLen - hLen - sLen - 2;

    for (i = 0; i < checkLen; i += 1) {
        if (DB[i] !== 0x00) {
            throw "leftmost octets not zero";
        }
    }

    if (DB[checkLen] !== 0x01) {
        throw "0x01 marker not found";
    }

    return H === hextorstr(hashFunc(rstrtohex('\x00\x00\x00\x00\x00\x00\x00\x00' + mHash +
				     String.fromCharCode.apply(String, DB.slice(-sLen)))));
}

RSAKey.prototype.signWithMessageHash = _rsasign_signWithMessageHash;
RSAKey.prototype.signString = _rsasign_signString;
RSAKey.prototype.signStringWithSHA1 = _rsasign_signStringWithSHA1;
RSAKey.prototype.signStringWithSHA256 = _rsasign_signStringWithSHA256;
RSAKey.prototype.sign = _rsasign_signString;
RSAKey.prototype.signWithSHA1 = _rsasign_signStringWithSHA1;
RSAKey.prototype.signWithSHA256 = _rsasign_signStringWithSHA256;

RSAKey.prototype.signWithMessageHashPSS = _rsasign_signWithMessageHashPSS;
RSAKey.prototype.signStringPSS = _rsasign_signStringPSS;
RSAKey.prototype.signPSS = _rsasign_signStringPSS;
RSAKey.SALT_LEN_HLEN = -1;
RSAKey.SALT_LEN_MAX = -2;

RSAKey.prototype.verifyWithMessageHash = _rsasign_verifyWithMessageHash;
RSAKey.prototype.verifyString = _rsasign_verifyString;
RSAKey.prototype.verifyHexSignatureForMessage = _rsasign_verifyHexSignatureForMessage;
RSAKey.prototype.verify = _rsasign_verifyString;
RSAKey.prototype.verifyHexSignatureForByteArrayMessage = _rsasign_verifyHexSignatureForMessage;

RSAKey.prototype.verifyWithMessageHashPSS = _rsasign_verifyWithMessageHashPSS;
RSAKey.prototype.verifyStringPSS = _rsasign_verifyStringPSS;
RSAKey.prototype.verifyPSS = _rsasign_verifyStringPSS;
RSAKey.SALT_LEN_RECOVER = -2;

/**
 * @name RSAKey
 * @class key of RSA public key algorithm
 * @description Tom Wu's RSA Key class and extension
 */

exports.RSAKey = RSAKey;
module.exports = exports;
/*! ecdsa-modified-1.0.4.js (c) Stephan Thomas, Kenji Urushima | github.com/bitcoinjs/bitcoinjs-lib/blob/master/LICENSE
 */
/*
 * ecdsa-modified.js - modified Bitcoin.ECDSA class
 * 
 * Copyright (c) 2013 Stefan Thomas (github.com/justmoon)
 *                    Kenji Urushima (kenji.urushima@gmail.com)
 * LICENSE
 *   https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/LICENSE
 */

/**
 * @fileOverview
 * @name ecdsa-modified-1.0.js
 * @author Stefan Thomas (github.com/justmoon) and Kenji Urushima (kenji.urushima@gmail.com)
 * @version 1.0.4 (2013-Oct-06)
 * @since jsrsasign 4.0
 * @license <a href="https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/LICENSE">MIT License</a>
 */

if (typeof KJUR == "undefined" || !KJUR) KJUR = {};
if (typeof KJUR.crypto == "undefined" || !KJUR.crypto) KJUR.crypto = {};

/**
 * class for EC key generation,  ECDSA signing and verifcation
 * @name KJUR.crypto.ECDSA
 * @class class for EC key generation,  ECDSA signing and verifcation
 * @description
 * <p>
 * CAUTION: Most of the case, you don't need to use this class except
 * for generating an EC key pair. Please use {@link KJUR.crypto.Signature} class instead.
 * </p>
 * <p>
 * This class was originally developped by Stefan Thomas for Bitcoin JavaScript library.
 * (See {@link https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/src/ecdsa.js})
 * Currently this class supports following named curves and their aliases.
 * <ul>
 * <li>secp256r1, NIST P-256, P-256, prime256v1 (*)</li>
 * <li>secp256k1 (*)</li>
 * <li>secp384r1, NIST P-384, P-384 (*)</li>
 * </ul>
 * </p>
 */
KJUR.crypto.ECDSA = function(params) {
    var curveName = "secp256r1";	// curve name default
    var ecparams = null;
    var prvKeyHex = null;
    var pubKeyHex = null;

    var rng = new SecureRandom();

    var P_OVER_FOUR = null;

    this.type = "EC";

    function implShamirsTrick(P, k, Q, l) {
	var m = Math.max(k.bitLength(), l.bitLength());
	var Z = P.add2D(Q);
	var R = P.curve.getInfinity();

	for (var i = m - 1; i >= 0; --i) {
	    R = R.twice2D();

	    R.z = BigInteger.ONE;

	    if (k.testBit(i)) {
		if (l.testBit(i)) {
		    R = R.add2D(Z);
		} else {
		    R = R.add2D(P);
		}
	    } else {
		if (l.testBit(i)) {
		    R = R.add2D(Q);
		}
	    }
	}
	
	return R;
    };

    //===========================
    // PUBLIC METHODS
    //===========================
    this.getBigRandom = function (limit) {
	return new BigInteger(limit.bitLength(), rng)
	.mod(limit.subtract(BigInteger.ONE))
	.add(BigInteger.ONE)
	;
    };

    this.setNamedCurve = function(curveName) {
	this.ecparams = KJUR.crypto.ECParameterDB.getByName(curveName);
	this.prvKeyHex = null;
	this.pubKeyHex = null;
	this.curveName = curveName;
    }

    this.setPrivateKeyHex = function(prvKeyHex) {
        this.isPrivate = true;
	this.prvKeyHex = prvKeyHex;
    }

    this.setPublicKeyHex = function(pubKeyHex) {
        this.isPublic = true;
	this.pubKeyHex = pubKeyHex;
    }

    /**
     * generate a EC key pair
     * @name generateKeyPairHex
     * @memberOf KJUR.crypto.ECDSA
     * @function
     * @return {Array} associative array of hexadecimal string of private and public key
     * @since ecdsa-modified 1.0.1
     * @example
     * var ec = new KJUR.crypto.ECDSA({'curve': 'secp256r1'});
     * var keypair = ec.generateKeyPairHex();
     * var pubhex = keypair.ecpubhex; // hexadecimal string of EC private key (=d)
     * var prvhex = keypair.ecprvhex; // hexadecimal string of EC public key
     */
    this.generateKeyPairHex = function() {
	var biN = this.ecparams['n'];
	var biPrv = this.getBigRandom(biN);
	var epPub = this.ecparams['G'].multiply(biPrv);
	var biX = epPub.getX().toBigInteger();
	var biY = epPub.getY().toBigInteger();

	var charlen = this.ecparams['keylen'] / 4;
	var hPrv = ("0000000000" + biPrv.toString(16)).slice(- charlen);
	var hX   = ("0000000000" + biX.toString(16)).slice(- charlen);
	var hY   = ("0000000000" + biY.toString(16)).slice(- charlen);
	var hPub = "04" + hX + hY;

	this.setPrivateKeyHex(hPrv);
	this.setPublicKeyHex(hPub);
	return {'ecprvhex': hPrv, 'ecpubhex': hPub};
    };

    this.signWithMessageHash = function(hashHex) {
	return this.signHex(hashHex, this.prvKeyHex);
    };

    /**
     * signing to message hash
     * @name signHex
     * @memberOf KJUR.crypto.ECDSA
     * @function
     * @param {String} hashHex hexadecimal string of hash value of signing message
     * @param {String} privHex hexadecimal string of EC private key
     * @return {String} hexadecimal string of ECDSA signature
     * @since ecdsa-modified 1.0.1
     * @example
     * var ec = new KJUR.crypto.ECDSA({'curve': 'secp256r1'});
     * var sigValue = ec.signHex(hash, prvKey);
     */
    this.signHex = function (hashHex, privHex) {
	var d = new BigInteger(privHex, 16);
	var n = this.ecparams['n'];
	var e = new BigInteger(hashHex, 16);

	do {
	    var k = this.getBigRandom(n);
	    var G = this.ecparams['G'];
	    var Q = G.multiply(k);
	    var r = Q.getX().toBigInteger().mod(n);
	} while (r.compareTo(BigInteger.ZERO) <= 0);

	var s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n);

	return KJUR.crypto.ECDSA.biRSSigToASN1Sig(r, s);
    };

    this.sign = function (hash, priv) {
	var d = priv;
	var n = this.ecparams['n'];
	var e = BigInteger.fromByteArrayUnsigned(hash);

	do {
	    var k = this.getBigRandom(n);
	    var G = this.ecparams['G'];
	    var Q = G.multiply(k);
	    var r = Q.getX().toBigInteger().mod(n);
	} while (r.compareTo(BigInteger.ZERO) <= 0);

	var s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n);
	return this.serializeSig(r, s);
    };

    this.verifyWithMessageHash = function(hashHex, sigHex) {
	return this.verifyHex(hashHex, sigHex, this.pubKeyHex);
    };

    /**
     * verifying signature with message hash and public key
     * @name verifyHex
     * @memberOf KJUR.crypto.ECDSA
     * @function
     * @param {String} hashHex hexadecimal string of hash value of signing message
     * @param {String} sigHex hexadecimal string of signature value
     * @param {String} pubkeyHex hexadecimal string of public key
     * @return {Boolean} true if the signature is valid, otherwise false
     * @since ecdsa-modified 1.0.1
     * @example
     * var ec = new KJUR.crypto.ECDSA({'curve': 'secp256r1'});
     * var result = ec.verifyHex(msgHashHex, sigHex, pubkeyHex);
     */
    this.verifyHex = function(hashHex, sigHex, pubkeyHex) {
	var r,s;

	var obj = KJUR.crypto.ECDSA.parseSigHex(sigHex);
	r = obj.r;
	s = obj.s;

	var Q;
	Q = ECPointFp.decodeFromHex(this.ecparams['curve'], pubkeyHex);
	var e = new BigInteger(hashHex, 16);

	return this.verifyRaw(e, r, s, Q);
    };

    this.verify = function (hash, sig, pubkey) {
	var r,s;
	if (Bitcoin.Util.isArray(sig)) {
	    var obj = this.parseSig(sig);
	    r = obj.r;
	    s = obj.s;
	} else if ("object" === typeof sig && sig.r && sig.s) {
	    r = sig.r;
	    s = sig.s;
	} else {
	    throw "Invalid value for signature";
	}

	var Q;
	if (pubkey instanceof ECPointFp) {
	    Q = pubkey;
	} else if (Bitcoin.Util.isArray(pubkey)) {
	    Q = ECPointFp.decodeFrom(this.ecparams['curve'], pubkey);
	} else {
	    throw "Invalid format for pubkey value, must be byte array or ECPointFp";
	}
	var e = BigInteger.fromByteArrayUnsigned(hash);

	return this.verifyRaw(e, r, s, Q);
    };

    this.verifyRaw = function (e, r, s, Q) {
	var n = this.ecparams['n'];
	var G = this.ecparams['G'];

	if (r.compareTo(BigInteger.ONE) < 0 ||
	    r.compareTo(n) >= 0)
	    return false;

	if (s.compareTo(BigInteger.ONE) < 0 ||
	    s.compareTo(n) >= 0)
	    return false;

	var c = s.modInverse(n);

	var u1 = e.multiply(c).mod(n);
	var u2 = r.multiply(c).mod(n);

	// TODO(!!!): For some reason Shamir's trick isn't working with
	// signed message verification!? Probably an implementation
	// error!
	//var point = implShamirsTrick(G, u1, Q, u2);
	var point = G.multiply(u1).add(Q.multiply(u2));

	var v = point.getX().toBigInteger().mod(n);

	return v.equals(r);
    };

    /**
     * Serialize a signature into DER format.
     *
     * Takes two BigIntegers representing r and s and returns a byte array.
     */
    this.serializeSig = function (r, s) {
	var rBa = r.toByteArraySigned();
	var sBa = s.toByteArraySigned();

	var sequence = [];
	sequence.push(0x02); // INTEGER
	sequence.push(rBa.length);
	sequence = sequence.concat(rBa);

	sequence.push(0x02); // INTEGER
	sequence.push(sBa.length);
	sequence = sequence.concat(sBa);

	sequence.unshift(sequence.length);
	sequence.unshift(0x30); // SEQUENCE
	return sequence;
    };

    /**
     * Parses a byte array containing a DER-encoded signature.
     *
     * This function will return an object of the form:
     *
     * {
     *   r: BigInteger,
     *   s: BigInteger
     * }
     */
    this.parseSig = function (sig) {
	var cursor;
	if (sig[0] != 0x30)
	    throw new Error("Signature not a valid DERSequence");

	cursor = 2;
	if (sig[cursor] != 0x02)
	    throw new Error("First element in signature must be a DERInteger");;
	var rBa = sig.slice(cursor+2, cursor+2+sig[cursor+1]);

	cursor += 2+sig[cursor+1];
	if (sig[cursor] != 0x02)
	    throw new Error("Second element in signature must be a DERInteger");
	var sBa = sig.slice(cursor+2, cursor+2+sig[cursor+1]);

	cursor += 2+sig[cursor+1];

	//if (cursor != sig.length)
	//  throw new Error("Extra bytes in signature");

	var r = BigInteger.fromByteArrayUnsigned(rBa);
	var s = BigInteger.fromByteArrayUnsigned(sBa);

	return {r: r, s: s};
    };

    this.parseSigCompact = function (sig) {
	if (sig.length !== 65) {
	    throw "Signature has the wrong length";
	}

	// Signature is prefixed with a type byte storing three bits of
	// information.
	var i = sig[0] - 27;
	if (i < 0 || i > 7) {
	    throw "Invalid signature type";
	}

	var n = this.ecparams['n'];
	var r = BigInteger.fromByteArrayUnsigned(sig.slice(1, 33)).mod(n);
	var s = BigInteger.fromByteArrayUnsigned(sig.slice(33, 65)).mod(n);

	return {r: r, s: s, i: i};
    };

    /*
     * Recover a public key from a signature.
     *
     * See SEC 1: Elliptic Curve Cryptography, section 4.1.6, "Public
     * Key Recovery Operation".
     *
     * http://www.secg.org/download/aid-780/sec1-v2.pdf
     */
    /*
    recoverPubKey: function (r, s, hash, i) {
	// The recovery parameter i has two bits.
	i = i & 3;

	// The less significant bit specifies whether the y coordinate
	// of the compressed point is even or not.
	var isYEven = i & 1;

	// The more significant bit specifies whether we should use the
	// first or second candidate key.
	var isSecondKey = i >> 1;

	var n = this.ecparams['n'];
	var G = this.ecparams['G'];
	var curve = this.ecparams['curve'];
	var p = curve.getQ();
	var a = curve.getA().toBigInteger();
	var b = curve.getB().toBigInteger();

	// We precalculate (p + 1) / 4 where p is if the field order
	if (!P_OVER_FOUR) {
	    P_OVER_FOUR = p.add(BigInteger.ONE).divide(BigInteger.valueOf(4));
	}

	// 1.1 Compute x
	var x = isSecondKey ? r.add(n) : r;

	// 1.3 Convert x to point
	var alpha = x.multiply(x).multiply(x).add(a.multiply(x)).add(b).mod(p);
	var beta = alpha.modPow(P_OVER_FOUR, p);

	var xorOdd = beta.isEven() ? (i % 2) : ((i+1) % 2);
	// If beta is even, but y isn't or vice versa, then convert it,
	// otherwise we're done and y == beta.
	var y = (beta.isEven() ? !isYEven : isYEven) ? beta : p.subtract(beta);

	// 1.4 Check that nR is at infinity
	var R = new ECPointFp(curve,
			      curve.fromBigInteger(x),
			      curve.fromBigInteger(y));
	R.validate();

	// 1.5 Compute e from M
	var e = BigInteger.fromByteArrayUnsigned(hash);
	var eNeg = BigInteger.ZERO.subtract(e).mod(n);

	// 1.6 Compute Q = r^-1 (sR - eG)
	var rInv = r.modInverse(n);
	var Q = implShamirsTrick(R, s, G, eNeg).multiply(rInv);

	Q.validate();
	if (!this.verifyRaw(e, r, s, Q)) {
	    throw "Pubkey recovery unsuccessful";
	}

	var pubKey = new Bitcoin.ECKey();
	pubKey.pub = Q;
	return pubKey;
    },
    */

    /*
     * Calculate pubkey extraction parameter.
     *
     * When extracting a pubkey from a signature, we have to
     * distinguish four different cases. Rather than putting this
     * burden on the verifier, Bitcoin includes a 2-bit value with the
     * signature.
     *
     * This function simply tries all four cases and returns the value
     * that resulted in a successful pubkey recovery.
     */
    /*
    calcPubkeyRecoveryParam: function (address, r, s, hash) {
	for (var i = 0; i < 4; i++) {
	    try {
		var pubkey = Bitcoin.ECDSA.recoverPubKey(r, s, hash, i);
		if (pubkey.getBitcoinAddress().toString() == address) {
		    return i;
		}
	    } catch (e) {}
	}
	throw "Unable to find valid recovery factor";
    }
    */

    if (params !== undefined) {
	if (params['curve'] !== undefined) {
	    this.curveName = params['curve'];
	}
    }
    if (this.curveName === undefined) this.curveName = curveName;
    this.setNamedCurve(this.curveName);
    if (params !== undefined) {
	if (params['prv'] !== undefined) this.setPrivateKeyHex(params['prv']);
	if (params['pub'] !== undefined) this.setPublicKeyHex(params['pub']);
    }
};

/**
 * parse ASN.1 DER encoded ECDSA signature
 * @name parseSigHex
 * @memberOf KJUR.crypto.ECDSA
 * @function
 * @static
 * @param {String} sigHex hexadecimal string of ECDSA signature value
 * @return {Array} associative array of signature field r and s of BigInteger
 * @since ecdsa-modified 1.0.1
 * @example
 * var ec = new KJUR.crypto.ECDSA({'curve': 'secp256r1'});
 * var sig = ec.parseSigHex('30...');
 * var biR = sig.r; // BigInteger object for 'r' field of signature.
 * var biS = sig.s; // BigInteger object for 's' field of signature.
 */
KJUR.crypto.ECDSA.parseSigHex = function(sigHex) {
    var p = KJUR.crypto.ECDSA.parseSigHexInHexRS(sigHex);
    var biR = new BigInteger(p.r, 16);
    var biS = new BigInteger(p.s, 16);
    
    return {'r': biR, 's': biS};
};

/**
 * parse ASN.1 DER encoded ECDSA signature
 * @name parseSigHexInHexRS
 * @memberOf KJUR.crypto.ECDSA
 * @function
 * @static
 * @param {String} sigHex hexadecimal string of ECDSA signature value
 * @return {Array} associative array of signature field r and s in hexadecimal
 * @since ecdsa-modified 1.0.3
 * @example
 * var ec = new KJUR.crypto.ECDSA({'curve': 'secp256r1'});
 * var sig = ec.parseSigHexInHexRS('30...');
 * var hR = sig.r; // hexadecimal string for 'r' field of signature.
 * var hS = sig.s; // hexadecimal string for 's' field of signature.
 */
KJUR.crypto.ECDSA.parseSigHexInHexRS = function(sigHex) {
    // 1. ASN.1 Sequence Check
    if (sigHex.substr(0, 2) != "30")
	throw "signature is not a ASN.1 sequence";

    // 2. Items of ASN.1 Sequence Check
    var a = ASN1HEX.getPosArrayOfChildren_AtObj(sigHex, 0);
    if (a.length != 2)
	throw "number of signature ASN.1 sequence elements seem wrong";
    
    // 3. Integer check
    var iTLV1 = a[0];
    var iTLV2 = a[1];
    if (sigHex.substr(iTLV1, 2) != "02")
	throw "1st item of sequene of signature is not ASN.1 integer";
    if (sigHex.substr(iTLV2, 2) != "02")
	throw "2nd item of sequene of signature is not ASN.1 integer";

    // 4. getting value
    var hR = ASN1HEX.getHexOfV_AtObj(sigHex, iTLV1);
    var hS = ASN1HEX.getHexOfV_AtObj(sigHex, iTLV2);
    
    return {'r': hR, 's': hS};
};

/**
 * convert hexadecimal ASN.1 encoded signature to concatinated signature
 * @name asn1SigToConcatSig
 * @memberOf KJUR.crypto.ECDSA
 * @function
 * @static
 * @param {String} asn1Hex hexadecimal string of ASN.1 encoded ECDSA signature value
 * @return {String} r-s concatinated format of ECDSA signature value
 * @since ecdsa-modified 1.0.3
 */
KJUR.crypto.ECDSA.asn1SigToConcatSig = function(asn1Sig) {
    var pSig = KJUR.crypto.ECDSA.parseSigHexInHexRS(asn1Sig);
    var hR = pSig.r;
    var hS = pSig.s;

    if (hR.substr(0, 2) == "00" && (((hR.length / 2) * 8) % (16 * 8)) == 8) 
	hR = hR.substr(2);

    if (hS.substr(0, 2) == "00" && (((hS.length / 2) * 8) % (16 * 8)) == 8) 
	hS = hS.substr(2);

    if ((((hR.length / 2) * 8) % (16 * 8)) != 0)
	throw "unknown ECDSA sig r length error";

    if ((((hS.length / 2) * 8) % (16 * 8)) != 0)
	throw "unknown ECDSA sig s length error";

    return hR + hS;
};

/**
 * convert hexadecimal concatinated signature to ASN.1 encoded signature
 * @name concatSigToASN1Sig
 * @memberOf KJUR.crypto.ECDSA
 * @function
 * @static
 * @param {String} concatSig r-s concatinated format of ECDSA signature value
 * @return {String} hexadecimal string of ASN.1 encoded ECDSA signature value
 * @since ecdsa-modified 1.0.3
 */
KJUR.crypto.ECDSA.concatSigToASN1Sig = function(concatSig) {
    if ((((concatSig.length / 2) * 8) % (16 * 8)) != 0)
	throw "unknown ECDSA concatinated r-s sig  length error";

    var hR = concatSig.substr(0, concatSig.length / 2);
    var hS = concatSig.substr(concatSig.length / 2);
    return KJUR.crypto.ECDSA.hexRSSigToASN1Sig(hR, hS);
};

/**
 * convert hexadecimal R and S value of signature to ASN.1 encoded signature
 * @name hexRSSigToASN1Sig
 * @memberOf KJUR.crypto.ECDSA
 * @function
 * @static
 * @param {String} hR hexadecimal string of R field of ECDSA signature value
 * @param {String} hS hexadecimal string of S field of ECDSA signature value
 * @return {String} hexadecimal string of ASN.1 encoded ECDSA signature value
 * @since ecdsa-modified 1.0.3
 */
KJUR.crypto.ECDSA.hexRSSigToASN1Sig = function(hR, hS) {
    var biR = new BigInteger(hR, 16);
    var biS = new BigInteger(hS, 16);
    return KJUR.crypto.ECDSA.biRSSigToASN1Sig(biR, biS);
};

/**
 * convert R and S BigInteger object of signature to ASN.1 encoded signature
 * @name biRSSigToASN1Sig
 * @memberOf KJUR.crypto.ECDSA
 * @function
 * @static
 * @param {BigInteger} biR BigInteger object of R field of ECDSA signature value
 * @param {BigInteger} biS BIgInteger object of S field of ECDSA signature value
 * @return {String} hexadecimal string of ASN.1 encoded ECDSA signature value
 * @since ecdsa-modified 1.0.3
 */
KJUR.crypto.ECDSA.biRSSigToASN1Sig = function(biR, biS) {
    var derR = new KJUR.asn1.DERInteger({'bigint': biR});
    var derS = new KJUR.asn1.DERInteger({'bigint': biS});
    var derSeq = new KJUR.asn1.DERSequence({'array': [derR, derS]});
    return derSeq.getEncodedHex();
};

/*! asn1hex-1.1.6.js (c) 2012-2015 Kenji Urushima | kjur.github.com/jsrsasign/license
 */
/*
 * asn1hex.js - Hexadecimal represented ASN.1 string library
 *
 * Copyright (c) 2010-2015 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.
 */

/**
 * @fileOverview
 * @name asn1hex-1.1.js
 * @author Kenji Urushima kenji.urushima@gmail.com
 * @version asn1hex 1.1.6 (2015-Jun-11)
 * @license <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
 */

/*
 * MEMO:
 *   f('3082025b02...', 2) ... 82025b ... 3bytes
 *   f('020100', 2) ... 01 ... 1byte
 *   f('0203001...', 2) ... 03 ... 1byte
 *   f('02818003...', 2) ... 8180 ... 2bytes
 *   f('3080....0000', 2) ... 80 ... -1
 *
 *   Requirements:
 *   - ASN.1 type octet length MUST be 1. 
 *     (i.e. ASN.1 primitives like SET, SEQUENCE, INTEGER, OCTETSTRING ...)
 */

/**
 * ASN.1 DER encoded hexadecimal string utility class
 * @name ASN1HEX
 * @class ASN.1 DER encoded hexadecimal string utility class
 * @since jsrsasign 1.1
 */
var intShim = require('jsbn');

var ASN1HEX = new function() {
    /**
     * get byte length for ASN.1 L(length) bytes
     * @name getByteLengthOfL_AtObj
     * @memberOf ASN1HEX
     * @function
     * @param {String} s hexadecimal string of ASN.1 DER encoded data
     * @param {Number} pos string index
     * @return byte length for ASN.1 L(length) bytes
     */
    this.getByteLengthOfL_AtObj = function(s, pos) {
        if (s.substring(pos + 2, pos + 3) != '8') return 1;
        var i = parseInt(s.substring(pos + 3, pos + 4));
        if (i == 0) return -1;          // length octet '80' indefinite length
        if (0 < i && i < 10) return i + 1;      // including '8?' octet;
        return -2;                              // malformed format
    };

    /**
     * get hexadecimal string for ASN.1 L(length) bytes
     * @name getHexOfL_AtObj
     * @memberOf ASN1HEX
     * @function
     * @param {String} s hexadecimal string of ASN.1 DER encoded data
     * @param {Number} pos string index
     * @return {String} hexadecimal string for ASN.1 L(length) bytes
     */
    this.getHexOfL_AtObj = function(s, pos) {
        var len = this.getByteLengthOfL_AtObj(s, pos);
        if (len < 1) return '';
        return s.substring(pos + 2, pos + 2 + len * 2);
    };

    //   getting ASN.1 length value at the position 'idx' of
    //   hexa decimal string 's'.
    //
    //   f('3082025b02...', 0) ... 82025b ... ???
    //   f('020100', 0) ... 01 ... 1
    //   f('0203001...', 0) ... 03 ... 3
    //   f('02818003...', 0) ... 8180 ... 128
    /**
     * get integer value of ASN.1 length for ASN.1 data
     * @name getIntOfL_AtObj
     * @memberOf ASN1HEX
     * @function
     * @param {String} s hexadecimal string of ASN.1 DER encoded data
     * @param {Number} pos string index
     * @return ASN.1 L(length) integer value
     */
    this.getIntOfL_AtObj = function(s, pos) {
        var hLength = this.getHexOfL_AtObj(s, pos);
        if (hLength == '') return -1;
        var bi;
        if (parseInt(hLength.substring(0, 1)) < 8) {
            bi = new BigInteger(hLength, 16);
        } else {
            bi = new BigInteger(hLength.substring(2), 16);
        }
        return bi.intValue();
    };

    /**
     * get ASN.1 value starting string position for ASN.1 object refered by index 'idx'.
     * @name getStartPosOfV_AtObj
     * @memberOf ASN1HEX
     * @function
     * @param {String} s hexadecimal string of ASN.1 DER encoded data
     * @param {Number} pos string index
     */
    this.getStartPosOfV_AtObj = function(s, pos) {
        var l_len = this.getByteLengthOfL_AtObj(s, pos);
        if (l_len < 0) return l_len;
        return pos + (l_len + 1) * 2;
    };

    /**
     * get hexadecimal string of ASN.1 V(value)
     * @name getHexOfV_AtObj
     * @memberOf ASN1HEX
     * @function
     * @param {String} s hexadecimal string of ASN.1 DER encoded data
     * @param {Number} pos string index
     * @return {String} hexadecimal string of ASN.1 value.
     */
    this.getHexOfV_AtObj = function(s, pos) {
        var pos1 = this.getStartPosOfV_AtObj(s, pos);
        var len = this.getIntOfL_AtObj(s, pos);
        return s.substring(pos1, pos1 + len * 2);
    };

    /**
     * get hexadecimal string of ASN.1 TLV at
     * @name getHexOfTLV_AtObj
     * @memberOf ASN1HEX
     * @function
     * @param {String} s hexadecimal string of ASN.1 DER encoded data
     * @param {Number} pos string index
     * @return {String} hexadecimal string of ASN.1 TLV.
     * @since 1.1
     */
    this.getHexOfTLV_AtObj = function(s, pos) {
        var hT = s.substr(pos, 2);
        var hL = this.getHexOfL_AtObj(s, pos);
        var hV = this.getHexOfV_AtObj(s, pos);
        return hT + hL + hV;
    };

    /**
     * get next sibling starting index for ASN.1 object string
     * @name getPosOfNextSibling_AtObj
     * @memberOf ASN1HEX
     * @function
     * @param {String} s hexadecimal string of ASN.1 DER encoded data
     * @param {Number} pos string index
     * @return next sibling starting index for ASN.1 object string
     */
    this.getPosOfNextSibling_AtObj = function(s, pos) {
        var pos1 = this.getStartPosOfV_AtObj(s, pos);
        var len = this.getIntOfL_AtObj(s, pos);
        return pos1 + len * 2;
    };

    /**
     * get array of indexes of child ASN.1 objects
     * @name getPosArrayOfChildren_AtObj
     * @memberOf ASN1HEX
     * @function
     * @param {String} s hexadecimal string of ASN.1 DER encoded data
     * @param {Number} start string index of ASN.1 object
     * @return {Array of Number} array of indexes for childen of ASN.1 objects
     */
    this.getPosArrayOfChildren_AtObj = function(h, pos) {
        var a = new Array();
        var p0 = this.getStartPosOfV_AtObj(h, pos);
        a.push(p0);

        var len = this.getIntOfL_AtObj(h, pos);
        var p = p0;
        var k = 0;
        while (1) {
            var pNext = this.getPosOfNextSibling_AtObj(h, p);
            if (pNext == null || (pNext - p0  >= (len * 2))) break;
            if (k >= 200) break;
            
            a.push(pNext);
            p = pNext;
            
            k++;
        }
        
        return a;
    };

    /**
     * get string index of nth child object of ASN.1 object refered by h, idx
     * @name getNthChildIndex_AtObj
     * @memberOf ASN1HEX
     * @function
     * @param {String} h hexadecimal string of ASN.1 DER encoded data
     * @param {Number} idx start string index of ASN.1 object
     * @param {Number} nth for child
     * @return {Number} string index of nth child.
     * @since 1.1
     */
    this.getNthChildIndex_AtObj = function(h, idx, nth) {
        var a = this.getPosArrayOfChildren_AtObj(h, idx);
        return a[nth];
    };

    // ========== decendant methods ==============================
    /**
     * get string index of nth child object of ASN.1 object refered by h, idx
     * @name getDecendantIndexByNthList
     * @memberOf ASN1HEX
     * @function
     * @param {String} h hexadecimal string of ASN.1 DER encoded data
     * @param {Number} currentIndex start string index of ASN.1 object
     * @param {Array of Number} nthList array list of nth
     * @return {Number} string index refered by nthList
     * @since 1.1
     * @example
     * The "nthList" is a index list of structured ASN.1 object
     * reference. Here is a sample structure and "nthList"s which
     * refers each objects.
     *
     * SQUENCE               - 
     *   SEQUENCE            - [0]
     *     IA5STRING 000     - [0, 0]
     *     UTF8STRING 001    - [0, 1]
     *   SET                 - [1]
     *     IA5STRING 010     - [1, 0]
     *     UTF8STRING 011    - [1, 1]
     */
    this.getDecendantIndexByNthList = function(h, currentIndex, nthList) {
        if (nthList.length == 0) {
            return currentIndex;
        }
        var firstNth = nthList.shift();
        var a = this.getPosArrayOfChildren_AtObj(h, currentIndex);
        return this.getDecendantIndexByNthList(h, a[firstNth], nthList);
    };

    /**
     * get hexadecimal string of ASN.1 TLV refered by current index and nth index list.
     * @name getDecendantHexTLVByNthList
     * @memberOf ASN1HEX
     * @function
     * @param {String} h hexadecimal string of ASN.1 DER encoded data
     * @param {Number} currentIndex start string index of ASN.1 object
     * @param {Array of Number} nthList array list of nth
     * @return {Number} hexadecimal string of ASN.1 TLV refered by nthList
     * @since 1.1
     */
    this.getDecendantHexTLVByNthList = function(h, currentIndex, nthList) {
        var idx = this.getDecendantIndexByNthList(h, currentIndex, nthList);
        return this.getHexOfTLV_AtObj(h, idx);
    };

    /**
     * get hexadecimal string of ASN.1 V refered by current index and nth index list.
     * @name getDecendantHexVByNthList
     * @memberOf ASN1HEX
     * @function
     * @param {String} h hexadecimal string of ASN.1 DER encoded data
     * @param {Number} currentIndex start string index of ASN.1 object
     * @param {Array of Number} nthList array list of nth
     * @return {Number} hexadecimal string of ASN.1 V refered by nthList
     * @since 1.1
     */
    this.getDecendantHexVByNthList = function(h, currentIndex, nthList) {
        var idx = this.getDecendantIndexByNthList(h, currentIndex, nthList);
        return this.getHexOfV_AtObj(h, idx);
    };
};

/*
 * @since asn1hex 1.1.4
 */
ASN1HEX.getVbyList = function(h, currentIndex, nthList, checkingTag) {
    var idx = this.getDecendantIndexByNthList(h, currentIndex, nthList);
    if (idx === undefined) {
        throw "can't find nthList object";
    }
    if (checkingTag !== undefined) {
        if (h.substr(idx, 2) != checkingTag) {
            throw "checking tag doesn't match: " + 
                h.substr(idx,2) + "!=" + checkingTag;
        }
    }
    return this.getHexOfV_AtObj(h, idx);
};

/**
 * get OID string from hexadecimal encoded value
 * @name hextooidstr
 * @memberOf ASN1HEX
 * @function
 * @param {String} hex hexadecmal string of ASN.1 DER encoded OID value
 * @return {String} OID string (ex. '1.2.3.4.567')
 * @since asn1hex 1.1.5
 */
ASN1HEX.hextooidstr = function(hex) {
    var zeroPadding = function(s, len) {
        if (s.length >= len) return s;
        return new Array(len - s.length + 1).join('0') + s;
    };

    var a = [];

    // a[0], a[1]
    var hex0 = hex.substr(0, 2);
    var i0 = parseInt(hex0, 16);
    a[0] = new String(Math.floor(i0 / 40));
    a[1] = new String(i0 % 40);

    // a[2]..a[n]
   var hex1 = hex.substr(2);
    var b = [];
    for (var i = 0; i < hex1.length / 2; i++) {
    b.push(parseInt(hex1.substr(i * 2, 2), 16));
    }
    var c = [];
    var cbin = "";
    for (var i = 0; i < b.length; i++) {
        if (b[i] & 0x80) {
            cbin = cbin + zeroPadding((b[i] & 0x7f).toString(2), 7);
        } else {
            cbin = cbin + zeroPadding((b[i] & 0x7f).toString(2), 7);
            c.push(new String(parseInt(cbin, 2)));
            cbin = "";
        }
    }

    var s = a.join(".");
    if (c.length > 0) s = s + "." + c.join(".");
    return s;
};

/**
 * get string of simple ASN.1 dump from hexadecimal ASN.1 data
 * @name dump
 * @memberOf ASN1HEX
 * @function
 * @param {String} hex hexadecmal string of ASN.1 data
 * @param {Array} associative array of flags for dump (OPTION)
 * @param {Number} idx string index for starting dump (OPTION)
 * @param {String} indent string (OPTION)
 * @return {String} string of simple ASN.1 dump
 * @since jsrsasign 4.8.3 asn1hex 1.1.6
 * @description
 * This method will get an ASN.1 dump from
 * hexadecmal string of ASN.1 DER encoded data.
 * Here are features:
 * <ul>
 * <li>ommit long hexadecimal string</li>
 * <li>dump encapsulated OCTET STRING (good for X.509v3 extensions)</li>
 * <li>structured/primitive context specific tag support (i.e. [0], [3] ...)</li>
 * <li>automatic decode for implicit primitive context specific tag 
 * (good for X.509v3 extension value)
 *   <ul>
 *   <li>if hex starts '68747470'(i.e. http) it is decoded as utf8 encoded string.</li>
 *   <li>if it is in 'subjectAltName' extension value and is '[2]'(dNSName) tag
 *   value will be encoded as utf8 string</li>
 *   <li>otherwise it shows as hexadecimal string</li>
 *   </ul>
 * </li>
 * </ul>
 * @example
 * // ASN.1 INTEGER
 * ASN1HEX.dump('0203012345')
 * &darr;
 * INTEGER 012345
 * // ASN.1 Object Identifier
 * ASN1HEX.dump('06052b0e03021a')
 * &darr;
 * ObjectIdentifier sha1 (1 3 14 3 2 26)
 * // ASN.1 SEQUENCE
 * ASN1HEX.dump('3006020101020102')
 * &darr;
 * SEQUENCE
 *   INTEGER 01
 *   INTEGER 02
 * // ASN.1 DUMP FOR X.509 CERTIFICATE
 * ASN1HEX.dump(X509.pemToHex(certPEM))
 * &darr;
 * SEQUENCE
 *   SEQUENCE
 *     [0]
 *       INTEGER 02
 *     INTEGER 0c009310d206dbe337553580118ddc87
 *     SEQUENCE
 *       ObjectIdentifier SHA256withRSA (1 2 840 113549 1 1 11)
 *       NULL
 *     SEQUENCE
 *       SET
 *         SEQUENCE
 *           ObjectIdentifier countryName (2 5 4 6)
 *           PrintableString 'US'
 *             :
 */
ASN1HEX.dump = function(hex, flags, idx, indent) {
    var _skipLongHex = function(hex, limitNumOctet) {
	if (hex.length <= limitNumOctet * 2) {
	    return hex;
	} else {
	    var s = hex.substr(0, limitNumOctet) + 
		    "..(total " + hex.length / 2 + "bytes).." +
		    hex.substr(hex.length - limitNumOctet, limitNumOctet);
	    return s;
	};
    };

    if (flags === undefined) flags = { "ommit_long_octet": 32 };
    if (idx === undefined) idx = 0;
    if (indent === undefined) indent = "";
    var skipLongHex = flags.ommit_long_octet;

    if (hex.substr(idx, 2) == "01") {
	var v = ASN1HEX.getHexOfV_AtObj(hex, idx);
	if (v == "00") {
	    return indent + "BOOLEAN FALSE\n";
	} else {
	    return indent + "BOOLEAN TRUE\n";
	}
    }
    if (hex.substr(idx, 2) == "02") {
	var v = ASN1HEX.getHexOfV_AtObj(hex, idx);
	return indent + "INTEGER " + _skipLongHex(v, skipLongHex) + "\n";
    }
    if (hex.substr(idx, 2) == "03") {
	var v = ASN1HEX.getHexOfV_AtObj(hex, idx);
	return indent + "BITSTRING " + _skipLongHex(v, skipLongHex) + "\n";
    }
    if (hex.substr(idx, 2) == "04") {
	var v = ASN1HEX.getHexOfV_AtObj(hex, idx);
	if (ASN1HEX.isASN1HEX(v)) {
	    var s = indent + "OCTETSTRING, encapsulates\n";
	    s = s + ASN1HEX.dump(v, flags, 0, indent + "  ");
	    return s;
	} else {
	    return indent + "OCTETSTRING " + _skipLongHex(v, skipLongHex) + "\n";
	}
    }
    if (hex.substr(idx, 2) == "05") {
	return indent + "NULL\n";
    }
    if (hex.substr(idx, 2) == "06") {
	var hV = ASN1HEX.getHexOfV_AtObj(hex, idx);
        var oidDot = KJUR.asn1.ASN1Util.oidHexToInt(hV);
        var oidName = KJUR.asn1.x509.OID.oid2name(oidDot);
	var oidSpc = oidDot.replace(/\./g, ' ');
        if (oidName != '') {
  	    return indent + "ObjectIdentifier " + oidName + " (" + oidSpc + ")\n";
	} else {
  	    return indent + "ObjectIdentifier (" + oidSpc + ")\n";
	}
    }
    if (hex.substr(idx, 2) == "0c") {
	return indent + "UTF8String '" + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "'\n";
    }
    if (hex.substr(idx, 2) == "13") {
	return indent + "PrintableString '" + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "'\n";
    }
    if (hex.substr(idx, 2) == "14") {
	return indent + "TeletexString '" + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "'\n";
    }
    if (hex.substr(idx, 2) == "16") {
	return indent + "IA5String '" + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "'\n";
    }
    if (hex.substr(idx, 2) == "17") {
	return indent + "UTCTime " + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "\n";
    }
    if (hex.substr(idx, 2) == "18") {
	return indent + "GeneralizedTime " + hextoutf8(ASN1HEX.getHexOfV_AtObj(hex, idx)) + "\n";
    }
    if (hex.substr(idx, 2) == "30") {
	if (hex.substr(idx, 4) == "3000") {
	    return indent + "SEQUENCE {}\n";
	}

	var s = indent + "SEQUENCE\n";
	var aIdx = ASN1HEX.getPosArrayOfChildren_AtObj(hex, idx);

	var flagsTemp = flags;
	
	if ((aIdx.length == 2 || aIdx.length == 3) &&
	    hex.substr(aIdx[0], 2) == "06" &&
	    hex.substr(aIdx[aIdx.length - 1], 2) == "04") { // supposed X.509v3 extension
	    var oidHex = ASN1HEX.getHexOfV_AtObj(hex, aIdx[0]);
	    var oidDot = KJUR.asn1.ASN1Util.oidHexToInt(oidHex);
	    var oidName = KJUR.asn1.x509.OID.oid2name(oidDot);

	    var flagsClone = JSON.parse(JSON.stringify(flags));
	    flagsClone.x509ExtName = oidName;
	    flagsTemp = flagsClone;
	}
	
	for (var i = 0; i < aIdx.length; i++) {
	    s = s + ASN1HEX.dump(hex, flagsTemp, aIdx[i], indent + "  ");
	}
	return s;
    }
    if (hex.substr(idx, 2) == "31") {
	var s = indent + "SET\n";
	var aIdx = ASN1HEX.getPosArrayOfChildren_AtObj(hex, idx);
	for (var i = 0; i < aIdx.length; i++) {
	    s = s + ASN1HEX.dump(hex, flags, aIdx[i], indent + "  ");
	}
	return s;
    }
    var tag = parseInt(hex.substr(idx, 2), 16);
    if ((tag & 128) != 0) { // context specific 
	var tagNumber = tag & 31;
	if ((tag & 32) != 0) { // structured tag
	    var s = indent + "[" + tagNumber + "]\n";
	    var aIdx = ASN1HEX.getPosArrayOfChildren_AtObj(hex, idx);
	    for (var i = 0; i < aIdx.length; i++) {
		s = s + ASN1HEX.dump(hex, flags, aIdx[i], indent + "  ");
	    }
	    return s;
	} else { // primitive tag
	    var v = ASN1HEX.getHexOfV_AtObj(hex, idx);
	    if (v.substr(0, 8) == "68747470") { // http
		v = hextoutf8(v);
	    }
	    if (flags.x509ExtName === "subjectAltName" &&
		tagNumber == 2) {
		v = hextoutf8(v);
	    }
	    
	    var s = indent + "[" + tagNumber + "] " + v + "\n";
	    return s;
	}
    }
    return indent + "UNKNOWN(" + hex.substr(idx, 2) + ") " + ASN1HEX.getHexOfV_AtObj(hex, idx) + "\n";
};

/**
 * check wheather the string is ASN.1 hexadecimal string or not
 * @name isASN1HEX
 * @memberOf ASN1HEX
 * @function
 * @param {String} hex string to check whether it is hexadecmal string for ASN.1 DER or not
 * @return {Boolean} true if it is hexadecimal string of ASN.1 data otherwise false
 * @since jsrsasign 4.8.3 asn1hex 1.1.6
 * @description
 * This method checks wheather the argument 'hex' is a hexadecimal string of
 * ASN.1 data or not.
 * @example
 * ASN1HEX.isASN1HEX('0203012345') &rarr; true // PROPER ASN.1 INTEGER
 * ASN1HEX.isASN1HEX('0203012345ff') &rarr; false // TOO LONG VALUE
 * ASN1HEX.isASN1HEX('02030123') &rarr; false // TOO SHORT VALUE
 * ASN1HEX.isASN1HEX('fa3bcd') &rarr; false // WRONG FOR ASN.1
 */
ASN1HEX.isASN1HEX = function(hex) {
    if (hex.length % 2 == 1) return false;

    var intL = ASN1HEX.getIntOfL_AtObj(hex, 0);
    var tV = hex.substr(0, 2);
    var lV = ASN1HEX.getHexOfL_AtObj(hex, 0);
    var hVLength = hex.length - tV.length - lV.length;
    if (hVLength == intL * 2) return true;

    return false;
};

exports.ASN1HEX = ASN1HEX;
module.exports = exports;
/*! x509-1.1.6.js (c) 2012-2015 Kenji Urushima | kjur.github.com/jsrsasign/license
 */
/* 
 * x509.js - X509 class to read subject public key from certificate.
 *
 * Copyright (c) 2010-2015 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.
 */

/**
 * @fileOverview
 * @name x509-1.1.js
 * @author Kenji Urushima kenji.urushima@gmail.com
 * @version x509 1.1.6 (2015-May-20)
 * @since jsrsasign 1.x.x
 * @license <a href="http://kjur.github.io/jsrsasign/license/">MIT License</a>
 */

/*
 * Depends:
 *   base64.js
 *   rsa.js
 *   asn1hex.js
 */

/**
 * 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>
 */

var b64tohex = require('./base64.js').b64tohex;
var RSAKey = require('./rsa.js').RSAKey;
var ASN1HEX = require('./asn1hex-1.1.js').ASN1HEX;

function X509() {
    this.subjectPublicKeyRSA = null;
    this.subjectPublicKeyRSA_hN = null;
    this.subjectPublicKeyRSA_hE = null;
    this.hex = null;

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

    /**
     * get hexadecimal string of serialNumber field of certificate.<br/>
     * @name getSerialNumberHex
     * @memberOf X509#
     * @function
     */
    this.getSerialNumberHex = function() {
        return ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 1]);
    };

    /**
     * get hexadecimal string of issuer field TLV of certificate.<br/>
     * @name getIssuerHex
     * @memberOf X509#
     * @function
     */
    this.getIssuerHex = function() {
        return ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 3]);
    };

    /**
     * get string of issuer field of certificate.<br/>
     * @name getIssuerString
     * @memberOf X509#
     * @function
     */
    this.getIssuerString = function() {
        return X509.hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 3]));
    };

    /**
     * get hexadecimal string of subject field of certificate.<br/>
     * @name getSubjectHex
     * @memberOf X509#
     * @function
     */
    this.getSubjectHex = function() {
        return ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 5]);
    };

    /**
     * get string of subject field of certificate.<br/>
     * @name getSubjectString
     * @memberOf X509#
     * @function
     */
    this.getSubjectString = function() {
        return X509.hex2dn(ASN1HEX.getDecendantHexTLVByNthList(this.hex, 0, [0, 5]));
    };

    /**
     * get notBefore field string of certificate.<br/>
     * @name getNotBefore
     * @memberOf X509#
     * @function
     */
    this.getNotBefore = function() {
        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
     */
    this.getNotAfter = function() {
        var s = ASN1HEX.getDecendantHexVByNthList(this.hex, 0, [0, 4, 1]);
        s = s.replace(/(..)/g, "%$1");
        s = decodeURIComponent(s);
        return s;
    };

    // ===== read certificate public key ==========================

    // ===== 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
     */
    this.readCertPEM = function(sCertPEM) {
        var hCert = X509.pemToHex(sCertPEM);
        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;
    };

    this.readCertPEMWithoutRSAInit = function(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;
    };
};

X509.pemToBase64 = function(sCertPEM) {
    var s = sCertPEM;
    s = s.replace("-----BEGIN CERTIFICATE-----", "");
    s = s.replace("-----END CERTIFICATE-----", "");
    s = s.replace(/[ \n]+/g, "");
    return s;
};

X509.pemToHex = function(sCertPEM) {
    var b64Cert = X509.pemToBase64(sCertPEM);
    var hCert = b64tohex(b64Cert);
    return hCert;
};

// NOTE: Without BITSTRING encapsulation.
X509.getSubjectPublicKeyPosFromCertHex = function(hCert) {
    var 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;
};

// NOTE: privateKeyUsagePeriod field of X509v2 not supported.
// NOTE: v1 and v3 supported
X509.getSubjectPublicKeyInfoPosFromCertHex = function(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];
    }
};

X509.getPublicKeyHexArrayFromCertHex = function(hCert) {
    var p = X509.getSubjectPublicKeyPosFromCertHex(hCert);
    var a = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, p); 
    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 [];
    }
};

X509.getHexTbsCertificateFromCert = function(hCert) {
    var pTbsCert = ASN1HEX.getStartPosOfV_AtObj(hCert, 0);
    return pTbsCert;
};

X509.getPublicKeyHexArrayFromCertPEM = function(sCertPEM) {
    var hCert = X509.pemToHex(sCertPEM);
    var a = X509.getPublicKeyHexArrayFromCertHex(hCert);
    return a;
};

X509.hex2dn = function(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;
};

X509.hex2rdn = function(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;
};

X509.DN_ATTRHEX = {
    "0603550406": "C",
    "060355040a": "O",
    "060355040b": "OU",
    "0603550403": "CN",
    "0603550405": "SN",
    "0603550408": "ST",
    "0603550407": "L"
};

/**
 * get RSAKey/ECDSA public key object from PEM certificate string
 * @name getPublicKeyFromCertPEM
 * @memberOf X509
 * @function
 * @param {String} sCertPEM PEM formatted RSA/ECDSA/DSA X.509 certificate
 * @return returns RSAKey/KJUR.crypto.{ECDSA,DSA} object of public key
 * @since x509 1.1.1
 * @description
 * NOTE: DSA is also supported since x509 1.1.2.
 */
X509.getPublicKeyFromCertPEM = function(sCertPEM) {
    var info = X509.getPublicKeyInfoPropOfCertPEM(sCertPEM);

    if (info.algoid == "2a864886f70d010101") { // RSA
        var aRSA = KEYUTIL.parsePublicRawRSAKeyHex(info.keyhex);
        var key = new RSAKey();
        key.setPublic(aRSA.n, aRSA.e);
        return key;
    } else if (info.algoid == "2a8648ce3d0201") { // ECC
        var curveName = KJUR.crypto.OID.oidhex2name[info.algparam];
        var key = new KJUR.crypto.ECDSA({'curve': curveName, 'info': info.keyhex});
        key.setPublicKeyHex(info.keyhex);
        return key;
    } else if (info.algoid == "2a8648ce380401") { // DSA 1.2.840.10040.4.1
        var p = ASN1HEX.getVbyList(info.algparam, 0, [0], "02");
        var q = ASN1HEX.getVbyList(info.algparam, 0, [1], "02");
        var g = ASN1HEX.getVbyList(info.algparam, 0, [2], "02");
        var y = ASN1HEX.getHexOfV_AtObj(info.keyhex, 0);
        y = y.substr(2);
        var key = new KJUR.crypto.DSA();
        key.setPublic(new BigInteger(p, 16),
                      new BigInteger(q, 16),
                      new BigInteger(g, 16),
                      new BigInteger(y, 16));
        return key;
    } else {
        throw "unsupported key";
    }
};

/**
 * get public key information from PEM certificate
 * @name getPublicKeyInfoPropOfCertPEM
 * @memberOf X509
 * @function
 * @param {String} sCertPEM string of PEM formatted certificate
 * @return {Hash} hash of information for public key
 * @since x509 1.1.1
 * @description
 * Resulted associative array has following properties:
 * <ul>
 * <li>algoid - hexadecimal string of OID of asymmetric key algorithm</li>
 * <li>algparam - hexadecimal string of OID of ECC curve name or null</li>
 * <li>keyhex - hexadecimal string of key in the certificate</li>
 * </ul>
 * @since x509 1.1.1
 */
X509.getPublicKeyInfoPropOfCertPEM = function(sCertPEM) {
    var result = {};
    result.algparam = null;
    var hCert = X509.pemToHex(sCertPEM);

    // 1. Certificate ASN.1
    var a1 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, 0); 
    if (a1.length != 3)
        throw "malformed X.509 certificate PEM (code:001)"; // not 3 item of seq Cert

    // 2. tbsCertificate
    if (hCert.substr(a1[0], 2) != "30")
        throw "malformed X.509 certificate PEM (code:002)"; // tbsCert not seq 

    var a2 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a1[0]); 

    // 3. subjectPublicKeyInfo
    if (a2.length < 7)
        throw "malformed X.509 certificate PEM (code:003)"; // no subjPubKeyInfo

    var a3 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a2[6]); 

    if (a3.length != 2)
        throw "malformed X.509 certificate PEM (code:004)"; // not AlgId and PubKey

    // 4. AlgId
    var a4 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a3[0]); 

    if (a4.length != 2)
        throw "malformed X.509 certificate PEM (code:005)"; // not 2 item in AlgId

    result.algoid = ASN1HEX.getHexOfV_AtObj(hCert, a4[0]);

    if (hCert.substr(a4[1], 2) == "06") { // EC
        result.algparam = ASN1HEX.getHexOfV_AtObj(hCert, a4[1]);
    } else if (hCert.substr(a4[1], 2) == "30") { // DSA
        result.algparam = ASN1HEX.getHexOfTLV_AtObj(hCert, a4[1]);
    }

    // 5. Public Key Hex
    if (hCert.substr(a3[1], 2) != "03")
        throw "malformed X.509 certificate PEM (code:006)"; // not bitstring

    var unusedBitAndKeyHex = ASN1HEX.getHexOfV_AtObj(hCert, a3[1]);
    result.keyhex = unusedBitAndKeyHex.substr(2);

    return result;
};

/**
 * get position of subjectPublicKeyInfo field from HEX certificate
 * @name getPublicKeyInfoPosOfCertHEX
 * @memberOf X509
 * @function
 * @param {String} hCert hexadecimal string of certificate
 * @return {Integer} position in hexadecimal string
 * @since x509 1.1.4
 * @description
 * get position for SubjectPublicKeyInfo field in the hexadecimal string of
 * certificate.
 */
X509.getPublicKeyInfoPosOfCertHEX = function(hCert) {
    // 1. Certificate ASN.1
    var a1 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, 0); 
    if (a1.length != 3)
        throw "malformed X.509 certificate PEM (code:001)"; // not 3 item of seq Cert

    // 2. tbsCertificate
    if (hCert.substr(a1[0], 2) != "30")
        throw "malformed X.509 certificate PEM (code:002)"; // tbsCert not seq 

    var a2 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a1[0]); 

    // 3. subjectPublicKeyInfo
    if (a2.length < 7)
        throw "malformed X.509 certificate PEM (code:003)"; // no subjPubKeyInfo
    
    return a2[6];
};

/**
 * get array of X.509 V3 extension value information in hex string of certificate
 * @name getV3ExtInfoListOfCertHex
 * @memberOf X509
 * @function
 * @param {String} hCert hexadecimal string of X.509 certificate binary
 * @return {Array} array of result object by {@link X509.getV3ExtInfoListOfCertHex}
 * @since x509 1.1.5
 * @description
 * This method will get all extension information of a X.509 certificate.
 * Items of resulting array has following properties:
 * <ul>
 * <li>posTLV - index of ASN.1 TLV for the extension. same as 'pos' argument.</li>
 * <li>oid - dot noted string of extension oid (ex. 2.5.29.14)</li>
 * <li>critical - critical flag value for this extension</li>
 * <li>posV - index of ASN.1 TLV for the extension value.
 * This is a position of a content of ENCAPSULATED OCTET STRING.</li>
 * </ul>
 * @example
 * hCert = X509.pemToHex(certGithubPEM);
 * a = X509.getV3ExtInfoListOfCertHex(hCert);
 * // Then a will be an array of like following:
 * [{posTLV: 1952, oid: "2.5.29.35", critical: false, posV: 1968},
 *  {posTLV: 1974, oid: "2.5.29.19", critical: true, posV: 1986}, ...]
 */
X509.getV3ExtInfoListOfCertHex = function(hCert) {
    // 1. Certificate ASN.1
    var a1 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, 0); 
    if (a1.length != 3)
        throw "malformed X.509 certificate PEM (code:001)"; // not 3 item of seq Cert

    // 2. tbsCertificate
    if (hCert.substr(a1[0], 2) != "30")
        throw "malformed X.509 certificate PEM (code:002)"; // tbsCert not seq 

    var a2 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a1[0]); 

    // 3. v3Extension EXPLICIT Tag [3]
    // ver, seri, alg, iss, validity, subj, spki, (iui,) (sui,) ext
    if (a2.length < 8)
        throw "malformed X.509 certificate PEM (code:003)"; // tbsCert num field too short

    if (hCert.substr(a2[7], 2) != "a3")
        throw "malformed X.509 certificate PEM (code:004)"; // not [3] tag

    var a3 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a2[7]);
    if (a3.length != 1)
        throw "malformed X.509 certificate PEM (code:005)"; // [3]tag numChild!=1

    // 4. v3Extension SEQUENCE
    if (hCert.substr(a3[0], 2) != "30")
        throw "malformed X.509 certificate PEM (code:006)"; // not SEQ

    var a4 = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, a3[0]);

    // 5. v3Extension item position
    var numExt = a4.length;
    var aInfo = new Array(numExt);
    for (var i = 0; i < numExt; i++) {
	aInfo[i] = X509.getV3ExtItemInfo_AtObj(hCert, a4[i]);
    }
    return aInfo;
};

/**
 * get X.509 V3 extension value information at the specified position
 * @name getV3ExtItemInfo_AtObj
 * @memberOf X509
 * @function
 * @param {String} hCert hexadecimal string of X.509 certificate binary
 * @param {Integer} pos index of hexadecimal string for the extension
 * @return {Object} properties for the extension
 * @since x509 1.1.5
 * @description
 * This method will get some information of a X.509 V extension 
 * which is referred by an index of hexadecimal string of X.509 
 * certificate. 
 * Resulting object has following properties:
 * <ul>
 * <li>posTLV - index of ASN.1 TLV for the extension. same as 'pos' argument.</li>
 * <li>oid - dot noted string of extension oid (ex. 2.5.29.14)</li>
 * <li>critical - critical flag value for this extension</li>
 * <li>posV - index of ASN.1 TLV for the extension value.
 * This is a position of a content of ENCAPSULATED OCTET STRING.</li>
 * </ul>
 * This method is used by {@link X509.getV3ExtInfoListOfCertHex} internally.
 */
X509.getV3ExtItemInfo_AtObj = function(hCert, pos) {
    var info = {};

    // posTLV - extension TLV
    info.posTLV = pos;

    var a  = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pos);
    if (a.length != 2 && a.length != 3)
        throw "malformed X.509v3 Ext (code:001)"; // oid,(critical,)val

    // oid - extension OID
    if (hCert.substr(a[0], 2) != "06")
        throw "malformed X.509v3 Ext (code:002)"; // not OID "06"
    var valueHex = ASN1HEX.getHexOfV_AtObj(hCert, a[0]);
    info.oid = ASN1HEX.hextooidstr(valueHex); 

    // critical - extension critical flag
    info.critical = false; // critical false by default
    if (a.length == 3) info.critical = true;

    // posV - content TLV position of encapsulated
    //        octet string of V3 extension value.
    var posExtV = a[a.length - 1];
    if (hCert.substr(posExtV, 2) != "04")
        throw "malformed X.509v3 Ext (code:003)"; // not EncapOctet "04"
    info.posV = ASN1HEX.getStartPosOfV_AtObj(hCert, posExtV);
    
    return info;
};

/**
 * get X.509 V3 extension value ASN.1 TLV for specified oid or name
 * @name getHexOfTLV_V3ExtValue
 * @memberOf X509
 * @function
 * @param {String} hCert hexadecimal string of X.509 certificate binary
 * @param {String} oidOrName oid or name for extension (ex. 'keyUsage' or '2.5.29.15')
 * @return {String} hexadecimal string of extension ASN.1 TLV
 * @since x509 1.1.6
 * @description
 * This method will get X.509v3 extension value of ASN.1 TLV
 * which is specifyed by extension name or oid. 
 * @example
 * hExtValue = X509.getHexOfTLV_V3ExtValue(hCert, "keyUsage");
 * // hExtValue will be such like '030205a0'.
 */
X509.getHexOfTLV_V3ExtValue = function(hCert, oidOrName) {
    var pos = X509.getPosOfTLV_V3ExtValue(hCert, oidOrName);
    if (pos == -1) return '';
    return ASN1HEX.getHexOfTLV_AtObj(hCert, pos);
};

/**
 * get X.509 V3 extension value ASN.1 V for specified oid or name
 * @name getHexOfV_V3ExtValue
 * @memberOf X509
 * @function
 * @param {String} hCert hexadecimal string of X.509 certificate binary
 * @param {String} oidOrName oid or name for extension (ex. 'keyUsage' or '2.5.29.15')
 * @return {String} hexadecimal string of extension ASN.1 TLV
 * @since x509 1.1.6
 * @description
 * This method will get X.509v3 extension value of ASN.1 value
 * which is specifyed by extension name or oid. 
 * If there is no such extension in the certificate,
 * it returns empty string (i.e. '').
 * Available extension names and oids are defined
 * in the {@link KJUR.asn1.x509.OID} class.
 * @example
 * hExtValue = X509.getHexOfV_V3ExtValue(hCert, "keyUsage");
 * // hExtValue will be such like '05a0'.
 */
X509.getHexOfV_V3ExtValue = function(hCert, oidOrName) {
    var pos = X509.getPosOfTLV_V3ExtValue(hCert, oidOrName);
    if (pos == -1) return '';
    return ASN1HEX.getHexOfV_AtObj(hCert, pos);
};

/**
 * get index in the certificate hexa string for specified oid or name specified extension
 * @name getPosOfTLV_V3ExtValue
 * @memberOf X509
 * @function
 * @param {String} hCert hexadecimal string of X.509 certificate binary
 * @param {String} oidOrName oid or name for extension (ex. 'keyUsage' or '2.5.29.15')
 * @return {Integer} index in the hexadecimal string of certficate for specified extension
 * @since x509 1.1.6
 * @description
 * This method will get X.509v3 extension value of ASN.1 V(value)
 * which is specifyed by extension name or oid. 
 * If there is no such extension in the certificate,
 * it returns empty string (i.e. '').
 * Available extension names and oids are defined
 * in the {@link KJUR.asn1.x509.OID} class.
 * @example
 * idx = X509.getPosOfV_V3ExtValue(hCert, "keyUsage");
 * // The 'idx' will be index in the string for keyUsage value ASN.1 TLV.
 */
X509.getPosOfTLV_V3ExtValue = function(hCert, oidOrName) {
    var oid = oidOrName;
    if (! oidOrName.match(/^[0-9.]+$/)) oid = KJUR.asn1.x509.OID.name2oid(oidOrName);
    if (oid == '') return -1;

    var infoList = X509.getV3ExtInfoListOfCertHex(hCert);
    for (var i = 0; i < infoList.length; i++) {
	var info = infoList[i];
	if (info.oid == oid) return info.posV;
    }
    return -1;
};

X509.KEYUSAGE_NAME = [
    "digitalSignature",
    "nonRepudiation",
    "keyEncipherment",
    "dataEncipherment",
    "keyAgreement",
    "keyCertSign",
    "cRLSign",
    "encipherOnly",
    "decipherOnly"
];

/**
 * get KeyUsage extension value as binary string in the certificate
 * @name getExtKeyUsageBin
 * @memberOf X509
 * @function
 * @param {String} hCert hexadecimal string of X.509 certificate binary
 * @return {String} binary string of key usage bits (ex. '101')
 * @since x509 1.1.6
 * @description
 * This method will get key usage extension value
 * as binary string such like '101'.
 * Key usage bits definition is in the RFC 5280.
 * If there is no key usage extension in the certificate,
 * it returns empty string (i.e. '').
 * @example
 * bKeyUsage = X509.getExtKeyUsageBin(hCert);
 * // bKeyUsage will be such like '101'.
 * // 1 - digitalSignature 
 * // 0 - nonRepudiation
 * // 1 - keyEncipherment
 */
X509.getExtKeyUsageBin = function(hCert) {
    var hKeyUsage = X509.getHexOfV_V3ExtValue(hCert, "keyUsage");
    if (hKeyUsage == '') return '';
    if (hKeyUsage.length % 2 != 0 || hKeyUsage.length <= 2)
	throw "malformed key usage value";
    var unusedBits = parseInt(hKeyUsage.substr(0, 2));
    var bKeyUsage = parseInt(hKeyUsage.substr(2), 16).toString(2);
    return bKeyUsage.substr(0, bKeyUsage.length - unusedBits);
};

/**
 * get KeyUsage extension value as names in the certificate
 * @name getExtKeyUsageString
 * @memberOf X509
 * @function
 * @param {String} hCert hexadecimal string of X.509 certificate binary
 * @return {String} comma separated string of key usage
 * @since x509 1.1.6
 * @description
 * This method will get key usage extension value
 * as comma separated string of usage names.
 * If there is no key usage extension in the certificate,
 * it returns empty string (i.e. '').
 * @example
 * sKeyUsage = X509.getExtKeyUsageString(hCert);
 * // sKeyUsage will be such like 'digitalSignature,keyEncipherment'.
 */
X509.getExtKeyUsageString = function(hCert) {
    var bKeyUsage = X509.getExtKeyUsageBin(hCert);
    var a = new Array();
    for (var i = 0; i < bKeyUsage.length; i++) {
	if (bKeyUsage.substr(i, 1) == "1") a.push(X509.KEYUSAGE_NAME[i]);
    }
    return a.join(",");
};

/**
 * get AuthorityInfoAccess extension value in the certificate as associative array
 * @name getExtAIAInfo
 * @memberOf X509
 * @function
 * @param {String} hCert hexadecimal string of X.509 certificate binary
 * @return {Object} associative array of AIA extension properties
 * @since x509 1.1.6
 * @description
 * This method will get authority info access value
 * as associate array which has following properties:
 * <ul>
 * <li>ocsp - array of string for OCSP responder URL</li>
 * <li>caissuer - array of string for caIssuer value (i.e. CA certificates URL)</li>
 * </ul>
 * If there is no key usage extension in the certificate,
 * it returns null;
 * @example
 * oAIA = X509.getExtAIAInfo(hCert);
 * // result will be such like:
 * // oAIA.ocsp = ["http://ocsp.foo.com"];
 * // oAIA.caissuer = ["http://rep.foo.com/aaa.p8m"];
 */
X509.getExtAIAInfo = function(hCert) {
    var result = {};
    result.ocsp = [];
    result.caissuer = [];
    var pos1 = X509.getPosOfTLV_V3ExtValue(hCert, "authorityInfoAccess");
    if (pos1 == -1) return null;
    if (hCert.substr(pos1, 2) != "30") // extnValue SEQUENCE
	throw "malformed AIA Extn Value";
    
    var posAccDescList = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, pos1);
    for (var i = 0; i < posAccDescList.length; i++) {
	var p = posAccDescList[i];
	var posAccDescChild = ASN1HEX.getPosArrayOfChildren_AtObj(hCert, p);
	if (posAccDescChild.length != 2)
	    throw "malformed AccessDescription of AIA Extn";
	var pOID = posAccDescChild[0];
	var pName = posAccDescChild[1];
	if (ASN1HEX.getHexOfV_AtObj(hCert, pOID) == "2b06010505073001") {
	    if (hCert.substr(pName, 2) == "86") {
		result.ocsp.push(hextoutf8(ASN1HEX.getHexOfV_AtObj(hCert, pName)));
	    }
	}
	if (ASN1HEX.getHexOfV_AtObj(hCert, pOID) == "2b06010505073002") {
	    if (hCert.substr(pName, 2) == "86") {
		result.caissuer.push(hextoutf8(ASN1HEX.getHexOfV_AtObj(hCert, pName)));
	    }
	}
    }
    return result;
};

/*
  X509.prototype.readCertPEM = _x509_readCertPEM;
  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;
*/

exports.X509 = X509;
module.exports = exports;
/*! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
 */
// Copyright (c) 2005  Tom Wu
// All Rights Reserved.
// See "LICENSE" for details.

// Basic JavaScript BN library - subset useful for RSA encryption.

// Bits per digit
var dbits;

// JavaScript engine analysis
var canary = 0xdeadbeefcafe;
var j_lm = ((canary&0xffffff)==0xefcafe);

// (public) Constructor
var BigInteger = function BigInteger(a,b,c) {
  if(a != null)
    if("number" == typeof a) this.fromNumber(a,b,c);
    else if(b == null && "string" != typeof a) this.fromString(a,256);
    else this.fromString(a,b);
}

// return new, unset BigInteger
function nbi() { return new BigInteger(null); }

// am: Compute w_j += (x*this_i), propagate carries,
// c is initial carry, returns final carry.
// c < 3*dvalue, x < 2*dvalue, this_i < dvalue
// We need to select the fastest one that works in this environment.

// am1: use a single mult and divide to get the high bits,
// max digit bits should be 26 because
// max internal value = 2*dvalue^2-2*dvalue (< 2^53)
function am1(i,x,w,j,c,n) {
  while(--n >= 0) {
    var v = x*this[i++]+w[j]+c;
    c = Math.floor(v/0x4000000);
    w[j++] = v&0x3ffffff;
  }
  return c;
}
// am2 avoids a big mult-and-extract completely.
// Max digit bits should be <= 30 because we do bitwise ops
// on values up to 2*hdvalue^2-hdvalue-1 (< 2^31)
function am2(i,x,w,j,c,n) {
  var xl = x&0x7fff, xh = x>>15;
  while(--n >= 0) {
    var l = this[i]&0x7fff;
    var h = this[i++]>>15;
    var m = xh*l+h*xl;
    l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff);
    c = (l>>>30)+(m>>>15)+xh*h+(c>>>30);
    w[j++] = l&0x3fffffff;
  }
  return c;
}
// Alternately, set max digit bits to 28 since some
// browsers slow down when dealing with 32-bit numbers.
function am3(i,x,w,j,c,n) {
  var xl = x&0x3fff, xh = x>>14;
  while(--n >= 0) {
    var l = this[i]&0x3fff;
    var h = this[i++]>>14;
    var m = xh*l+h*xl;
    l = xl*l+((m&0x3fff)<<14)+w[j]+c;
    c = (l>>28)+(m>>14)+xh*h;
    w[j++] = l&0xfffffff;
  }
  return c;
}
if(j_lm && (navigator.appName == "Microsoft Internet Explorer")) {
  BigInteger.prototype.am = am2;
  dbits = 30;
}
else if(j_lm && (navigator.appName != "Netscape")) {
  BigInteger.prototype.am = am1;
  dbits = 26;
}
else { // Mozilla/Netscape seems to prefer am3
  BigInteger.prototype.am = am3;
  dbits = 28;
}

BigInteger.prototype.DB = dbits;
BigInteger.prototype.DM = ((1<<dbits)-1);
BigInteger.prototype.DV = (1<<dbits);

var BI_FP = 52;
BigInteger.prototype.FV = Math.pow(2,BI_FP);
BigInteger.prototype.F1 = BI_FP-dbits;
BigInteger.prototype.F2 = 2*dbits-BI_FP;

// Digit conversions
var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
var BI_RC = new Array();
var rr,vv;
rr = "0".charCodeAt(0);
for(vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv;
rr = "a".charCodeAt(0);
for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
rr = "A".charCodeAt(0);
for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;

function int2char(n) { return BI_RM.charAt(n); }
function intAt(s,i) {
  var c = BI_RC[s.charCodeAt(i)];
  return (c==null)?-1:c;
}

// (protected) copy this to r
function bnpCopyTo(r) {
  for(var i = this.t-1; i >= 0; --i) r[i] = this[i];
  r.t = this.t;
  r.s = this.s;
}

// (protected) set from integer value x, -DV <= x < DV
function bnpFromInt(x) {
  this.t = 1;
  this.s = (x<0)?-1:0;
  if(x > 0) this[0] = x;
  else if(x < -1) this[0] = x+this.DV;
  else this.t = 0;
}

// return bigint initialized to value
function nbv(i) { var r = nbi(); r.fromInt(i); return r; }

// (protected) set from string and radix
function bnpFromString(s,b) {
  var k;
  if(b == 16) k = 4;
  else if(b == 8) k = 3;
  else if(b == 256) k = 8; // byte array
  else if(b == 2) k = 1;
  else if(b == 32) k = 5;
  else if(b == 4) k = 2;
  else { this.fromRadix(s,b); return; }
  this.t = 0;
  this.s = 0;
  var i = s.length, mi = false, sh = 0;
  while(--i >= 0) {
    var x = (k==8)?s[i]&0xff:intAt(s,i);
    if(x < 0) {
      if(s.charAt(i) == "-") mi = true;
      continue;
    }
    mi = false;
    if(sh == 0)
      this[this.t++] = x;
    else if(sh+k > this.DB) {
      this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<<sh;
      this[this.t++] = (x>>(this.DB-sh));
    }
    else
      this[this.t-1] |= x<<sh;
    sh += k;
    if(sh >= this.DB) sh -= this.DB;
  }
  if(k == 8 && (s[0]&0x80) != 0) {
    this.s = -1;
    if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)<<sh;
  }
  this.clamp();
  if(mi) BigInteger.ZERO.subTo(this,this);
}

// (protected) clamp off excess high words
function bnpClamp() {
  var c = this.s&this.DM;
  while(this.t > 0 && this[this.t-1] == c) --this.t;
}

// (public) return string representation in given radix
function bnToString(b) {
  if(this.s < 0) return "-"+this.negate().toString(b);
  var k;
  if(b == 16) k = 4;
  else if(b == 8) k = 3;
  else if(b == 2) k = 1;
  else if(b == 32) k = 5;
  else if(b == 4) k = 2;
  else return this.toRadix(b);
  var km = (1<<k)-1, d, m = false, r = "", i = this.t;
  var p = this.DB-(i*this.DB)%k;
  if(i-- > 0) {
    if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); }
    while(i >= 0) {
      if(p < k) {
        d = (this[i]&((1<<p)-1))<<(k-p);
        d |= this[--i]>>(p+=this.DB-k);
      }
      else {
        d = (this[i]>>(p-=k))&km;
        if(p <= 0) { p += this.DB; --i; }
      }
      if(d > 0) m = true;
      if(m) r += int2char(d);
    }
  }
  return m?r:"0";
}

// (public) -this
function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; }

// (public) |this|
function bnAbs() { return (this.s<0)?this.negate():this; }

// (public) return + if this > a, - if this < a, 0 if equal
function bnCompareTo(a) {
  var r = this.s-a.s;
  if(r != 0) return r;
  var i = this.t;
  r = i-a.t;
  if(r != 0) return (this.s<0)?-r:r;
  while(--i >= 0) if((r=this[i]-a[i]) != 0) return r;
  return 0;
}

// returns bit length of the integer x
function nbits(x) {
  var r = 1, t;
  if((t=x>>>16) != 0) { x = t; r += 16; }
  if((t=x>>8) != 0) { x = t; r += 8; }
  if((t=x>>4) != 0) { x = t; r += 4; }
  if((t=x>>2) != 0) { x = t; r += 2; }
  if((t=x>>1) != 0) { x = t; r += 1; }
  return r;
}

// (public) return the number of bits in "this"
function bnBitLength() {
  if(this.t <= 0) return 0;
  return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM));
}

// (protected) r = this << n*DB
function bnpDLShiftTo(n,r) {
  var i;
  for(i = this.t-1; i >= 0; --i) r[i+n] = this[i];
  for(i = n-1; i >= 0; --i) r[i] = 0;
  r.t = this.t+n;
  r.s = this.s;
}

// (protected) r = this >> n*DB
function bnpDRShiftTo(n,r) {
  for(var i = n; i < this.t; ++i) r[i-n] = this[i];
  r.t = Math.max(this.t-n,0);
  r.s = this.s;
}

// (protected) r = this << n
function bnpLShiftTo(n,r) {
  var bs = n%this.DB;
  var cbs = this.DB-bs;
  var bm = (1<<cbs)-1;
  var ds = Math.floor(n/this.DB), c = (this.s<<bs)&this.DM, i;
  for(i = this.t-1; i >= 0; --i) {
    r[i+ds+1] = (this[i]>>cbs)|c;
    c = (this[i]&bm)<<bs;
  }
  for(i = ds-1; i >= 0; --i) r[i] = 0;
  r[ds] = c;
  r.t = this.t+ds+1;
  r.s = this.s;
  r.clamp();
}

// (protected) r = this >> n
function bnpRShiftTo(n,r) {
  r.s = this.s;
  var ds = Math.floor(n/this.DB);
  if(ds >= this.t) { r.t = 0; return; }
  var bs = n%this.DB;
  var cbs = this.DB-bs;
  var bm = (1<<bs)-1;
  r[0] = this[ds]>>bs;
  for(var i = ds+1; i < this.t; ++i) {
    r[i-ds-1] |= (this[i]&bm)<<cbs;
    r[i-ds] = this[i]>>bs;
  }
  if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<<cbs;
  r.t = this.t-ds;
  r.clamp();
}

// (protected) r = this - a
function bnpSubTo(a,r) {
  var i = 0, c = 0, m = Math.min(a.t,this.t);
  while(i < m) {
    c += this[i]-a[i];
    r[i++] = c&this.DM;
    c >>= this.DB;
  }
  if(a.t < this.t) {
    c -= a.s;
    while(i < this.t) {
      c += this[i];
      r[i++] = c&this.DM;
      c >>= this.DB;
    }
    c += this.s;
  }
  else {
    c += this.s;
    while(i < a.t) {
      c -= a[i];
      r[i++] = c&this.DM;
      c >>= this.DB;
    }
    c -= a.s;
  }
  r.s = (c<0)?-1:0;
  if(c < -1) r[i++] = this.DV+c;
  else if(c > 0) r[i++] = c;
  r.t = i;
  r.clamp();
}

// (protected) r = this * a, r != this,a (HAC 14.12)
// "this" should be the larger one if appropriate.
function bnpMultiplyTo(a,r) {
  var x = this.abs(), y = a.abs();
  var i = x.t;
  r.t = i+y.t;
  while(--i >= 0) r[i] = 0;
  for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t);
  r.s = 0;
  r.clamp();
  if(this.s != a.s) BigInteger.ZERO.subTo(r,r);
}

// (protected) r = this^2, r != this (HAC 14.16)
function bnpSquareTo(r) {
  var x = this.abs();
  var i = r.t = 2*x.t;
  while(--i >= 0) r[i] = 0;
  for(i = 0; i < x.t-1; ++i) {
    var c = x.am(i,x[i],r,2*i,0,1);
    if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) {
      r[i+x.t] -= x.DV;
      r[i+x.t+1] = 1;
    }
  }
  if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1);
  r.s = 0;
  r.clamp();
}

// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)
// r != q, this != m.  q or r may be null.
function bnpDivRemTo(m,q,r) {
  var pm = m.abs();
  if(pm.t <= 0) return;
  var pt = this.abs();
  if(pt.t < pm.t) {
    if(q != null) q.fromInt(0);
    if(r != null) this.copyTo(r);
    return;
  }
  if(r == null) r = nbi();
  var y = nbi(), ts = this.s, ms = m.s;
  var nsh = this.DB-nbits(pm[pm.t-1]);	// normalize modulus
  if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); }
  else { pm.copyTo(y); pt.copyTo(r); }
  var ys = y.t;
  var y0 = y[ys-1];
  if(y0 == 0) return;
  var yt = y0*(1<<this.F1)+((ys>1)?y[ys-2]>>this.F2:0);
  var d1 = this.FV/yt, d2 = (1<<this.F1)/yt, e = 1<<this.F2;
  var i = r.t, j = i-ys, t = (q==null)?nbi():q;
  y.dlShiftTo(j,t);
  if(r.compareTo(t) >= 0) {
    r[r.t++] = 1;
    r.subTo(t,r);
  }
  BigInteger.ONE.dlShiftTo(ys,t);
  t.subTo(y,y);	// "negative" y so we can replace sub with am later
  while(y.t < ys) y[y.t++] = 0;
  while(--j >= 0) {
    // Estimate quotient digit
    var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);
    if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) {	// Try it out
      y.dlShiftTo(j,t);
      r.subTo(t,r);
      while(r[i] < --qd) r.subTo(t,r);
    }
  }
  if(q != null) {
    r.drShiftTo(ys,q);
    if(ts != ms) BigInteger.ZERO.subTo(q,q);
  }
  r.t = ys;
  r.clamp();
  if(nsh > 0) r.rShiftTo(nsh,r);	// Denormalize remainder
  if(ts < 0) BigInteger.ZERO.subTo(r,r);
}

// (public) this mod a
function bnMod(a) {
  var r = nbi();
  this.abs().divRemTo(a,null,r);
  if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r);
  return r;
}

// Modular reduction using "classic" algorithm
function Classic(m) { this.m = m; }
function cConvert(x) {
  if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m);
  else return x;
}
function cRevert(x) { return x; }
function cReduce(x) { x.divRemTo(this.m,null,x); }
function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); }

Classic.prototype.convert = cConvert;
Classic.prototype.revert = cRevert;
Classic.prototype.reduce = cReduce;
Classic.prototype.mulTo = cMulTo;
Classic.prototype.sqrTo = cSqrTo;

// (protected) return "-1/this % 2^DB"; useful for Mont. reduction
// justification:
//         xy == 1 (mod m)
//         xy =  1+km
//   xy(2-xy) = (1+km)(1-km)
// x[y(2-xy)] = 1-k^2m^2
// x[y(2-xy)] == 1 (mod m^2)
// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
// should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
// JS multiply "overflows" differently from C/C++, so care is needed here.
function bnpInvDigit() {
  if(this.t < 1) return 0;
  var x = this[0];
  if((x&1) == 0) return 0;
  var y = x&3;		// y == 1/x mod 2^2
  y = (y*(2-(x&0xf)*y))&0xf;	// y == 1/x mod 2^4
  y = (y*(2-(x&0xff)*y))&0xff;	// y == 1/x mod 2^8
  y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff;	// y == 1/x mod 2^16
  // last step - calculate inverse mod DV directly;
  // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
  y = (y*(2-x*y%this.DV))%this.DV;		// y == 1/x mod 2^dbits
  // we really want the negative inverse, and -DV < y < DV
  return (y>0)?this.DV-y:-y;
}

// Montgomery reduction
function Montgomery(m) {
  this.m = m;
  this.mp = m.invDigit();
  this.mpl = this.mp&0x7fff;
  this.mph = this.mp>>15;
  this.um = (1<<(m.DB-15))-1;
  this.mt2 = 2*m.t;
}

// xR mod m
function montConvert(x) {
  var r = nbi();
  x.abs().dlShiftTo(this.m.t,r);
  r.divRemTo(this.m,null,r);
  if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r);
  return r;
}

// x/R mod m
function montRevert(x) {
  var r = nbi();
  x.copyTo(r);
  this.reduce(r);
  return r;
}

// x = x/R mod m (HAC 14.32)
function montReduce(x) {
  while(x.t <= this.mt2)	// pad x so am has enough room later
    x[x.t++] = 0;
  for(var i = 0; i < this.m.t; ++i) {
    // faster way of calculating u0 = x[i]*mp mod DV
    var j = x[i]&0x7fff;
    var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM;
    // use am to combine the multiply-shift-add into one call
    j = i+this.m.t;
    x[j] += this.m.am(0,u0,x,i,0,this.m.t);
    // propagate carry
    while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; }
  }
  x.clamp();
  x.drShiftTo(this.m.t,x);
  if(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
}

// r = "x^2/R mod m"; x != r
function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); }

// r = "xy/R mod m"; x,y != r
function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }

Montgomery.prototype.convert = montConvert;
Montgomery.prototype.revert = montRevert;
Montgomery.prototype.reduce = montReduce;
Montgomery.prototype.mulTo = montMulTo;
Montgomery.prototype.sqrTo = montSqrTo;

// (protected) true iff this is even
function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; }

// (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79)
function bnpExp(e,z) {
  if(e > 0xffffffff || e < 1) return BigInteger.ONE;
  var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1;
  g.copyTo(r);
  while(--i >= 0) {
    z.sqrTo(r,r2);
    if((e&(1<<i)) > 0) z.mulTo(r2,g,r);
    else { var t = r; r = r2; r2 = t; }
  }
  return z.revert(r);
}

// (public) this^e % m, 0 <= e < 2^32
function bnModPowInt(e,m) {
  var z;
  if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m);
  return this.exp(e,z);
}

// protected
BigInteger.prototype.copyTo = bnpCopyTo;
BigInteger.prototype.fromInt = bnpFromInt;
BigInteger.prototype.fromString = bnpFromString;
BigInteger.prototype.clamp = bnpClamp;
BigInteger.prototype.dlShiftTo = bnpDLShiftTo;
BigInteger.prototype.drShiftTo = bnpDRShiftTo;
BigInteger.prototype.lShiftTo = bnpLShiftTo;
BigInteger.prototype.rShiftTo = bnpRShiftTo;
BigInteger.prototype.subTo = bnpSubTo;
BigInteger.prototype.multiplyTo = bnpMultiplyTo;
BigInteger.prototype.squareTo = bnpSquareTo;
BigInteger.prototype.divRemTo = bnpDivRemTo;
BigInteger.prototype.invDigit = bnpInvDigit;
BigInteger.prototype.isEven = bnpIsEven;
BigInteger.prototype.exp = bnpExp;

// public
BigInteger.prototype.toString = bnToString;
BigInteger.prototype.negate = bnNegate;
BigInteger.prototype.abs = bnAbs;
BigInteger.prototype.compareTo = bnCompareTo;
BigInteger.prototype.bitLength = bnBitLength;
BigInteger.prototype.mod = bnMod;
BigInteger.prototype.modPowInt = bnModPowInt;

// "constants"
BigInteger.ZERO = nbv(0);
BigInteger.ONE = nbv(1);
/*! (c) Tom Wu | http://www-cs-students.stanford.edu/~tjw/jsbn/
 */
// Copyright (c) 2005-2009  Tom Wu
// All Rights Reserved.
// See "LICENSE" for details.

// Extended JavaScript BN functions, required for RSA private ops.

// Version 1.1: new BigInteger("0", 10) returns "proper" zero
// Version 1.2: square() API, isProbablePrime fix

// (public)
function bnClone() { var r = nbi(); this.copyTo(r); return r; }

// (public) return value as integer
function bnIntValue() {
  if(this.s < 0) {
    if(this.t == 1) return this[0]-this.DV;
    else if(this.t == 0) return -1;
  }
  else if(this.t == 1) return this[0];
  else if(this.t == 0) return 0;
  // assumes 16 < DB < 32
  return ((this[1]&((1<<(32-this.DB))-1))<<this.DB)|this[0];
}

// (public) return value as byte
function bnByteValue() { return (this.t==0)?this.s:(this[0]<<24)>>24; }

// (public) return value as short (assumes DB>=16)
function bnShortValue() { return (this.t==0)?this.s:(this[0]<<16)>>16; }

// (protected) return x s.t. r^x < DV
function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); }

// (public) 0 if this == 0, 1 if this > 0
function bnSigNum() {
  if(this.s < 0) return -1;
  else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0;
  else return 1;
}

// (protected) convert to radix string
function bnpToRadix(b) {
  if(b == null) b = 10;
  if(this.signum() == 0 || b < 2 || b > 36) return "0";
  var cs = this.chunkSize(b);
  var a = Math.pow(b,cs);
  var d = nbv(a), y = nbi(), z = nbi(), r = "";
  this.divRemTo(d,y,z);
  while(y.signum() > 0) {
    r = (a+z.intValue()).toString(b).substr(1) + r;
    y.divRemTo(d,y,z);
  }
  return z.intValue().toString(b) + r;
}

// (protected) convert from radix string
function bnpFromRadix(s,b) {
  this.fromInt(0);
  if(b == null) b = 10;
  var cs = this.chunkSize(b);
  var d = Math.pow(b,cs), mi = false, j = 0, w = 0;
  for(var i = 0; i < s.length; ++i) {
    var x = intAt(s,i);
    if(x < 0) {
      if(s.charAt(i) == "-" && this.signum() == 0) mi = true;
      continue;
    }
    w = b*w+x;
    if(++j >= cs) {
      this.dMultiply(d);
      this.dAddOffset(w,0);
      j = 0;
      w = 0;
    }
  }
  if(j > 0) {
    this.dMultiply(Math.pow(b,j));
    this.dAddOffset(w,0);
  }
  if(mi) BigInteger.ZERO.subTo(this,this);
}

// (protected) alternate constructor
function bnpFromNumber(a,b,c) {
  if("number" == typeof b) {
    // new BigInteger(int,int,RNG)
    if(a < 2) this.fromInt(1);
    else {
      this.fromNumber(a,c);
      if(!this.testBit(a-1))	// force MSB set
        this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this);
      if(this.isEven()) this.dAddOffset(1,0); // force odd
      while(!this.isProbablePrime(b)) {
        this.dAddOffset(2,0);
        if(this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a-1),this);
      }
    }
  }
  else {
    // new BigInteger(int,RNG)
    var x = new Array(), t = a&7;
    x.length = (a>>3)+1;
    b.nextBytes(x);
    if(t > 0) x[0] &= ((1<<t)-1); else x[0] = 0;
    this.fromString(x,256);
  }
}

// (public) convert to bigendian byte array
function bnToByteArray() {
  var i = this.t, r = new Array();
  r[0] = this.s;
  var p = this.DB-(i*this.DB)%8, d, k = 0;
  if(i-- > 0) {
    if(p < this.DB && (d = this[i]>>p) != (this.s&this.DM)>>p)
      r[k++] = d|(this.s<<(this.DB-p));
    while(i >= 0) {
      if(p < 8) {
        d = (this[i]&((1<<p)-1))<<(8-p);
        d |= this[--i]>>(p+=this.DB-8);
      }
      else {
        d = (this[i]>>(p-=8))&0xff;
        if(p <= 0) { p += this.DB; --i; }
      }
      if((d&0x80) != 0) d |= -256;
      if(k == 0 && (this.s&0x80) != (d&0x80)) ++k;
      if(k > 0 || d != this.s) r[k++] = d;
    }
  }
  return r;
}

function bnEquals(a) { return(this.compareTo(a)==0); }
function bnMin(a) { return(this.compareTo(a)<0)?this:a; }
function bnMax(a) { return(this.compareTo(a)>0)?this:a; }

// (protected) r = this op a (bitwise)
function bnpBitwiseTo(a,op,r) {
  var i, f, m = Math.min(a.t,this.t);
  for(i = 0; i < m; ++i) r[i] = op(this[i],a[i]);
  if(a.t < this.t) {
    f = a.s&this.DM;
    for(i = m; i < this.t; ++i) r[i] = op(this[i],f);
    r.t = this.t;
  }
  else {
    f = this.s&this.DM;
    for(i = m; i < a.t; ++i) r[i] = op(f,a[i]);
    r.t = a.t;
  }
  r.s = op(this.s,a.s);
  r.clamp();
}

// (public) this & a
function op_and(x,y) { return x&y; }
function bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; }

// (public) this | a
function op_or(x,y) { return x|y; }
function bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; }

// (public) this ^ a
function op_xor(x,y) { return x^y; }
function bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; }

// (public) this & ~a
function op_andnot(x,y) { return x&~y; }
function bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; }

// (public) ~this
function bnNot() {
  var r = nbi();
  for(var i = 0; i < this.t; ++i) r[i] = this.DM&~this[i];
  r.t = this.t;
  r.s = ~this.s;
  return r;
}

// (public) this << n
function bnShiftLeft(n) {
  var r = nbi();
  if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r);
  return r;
}

// (public) this >> n
function bnShiftRight(n) {
  var r = nbi();
  if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r);
  return r;
}

// return index of lowest 1-bit in x, x < 2^31
function lbit(x) {
  if(x == 0) return -1;
  var r = 0;
  if((x&0xffff) == 0) { x >>= 16; r += 16; }
  if((x&0xff) == 0) { x >>= 8; r += 8; }
  if((x&0xf) == 0) { x >>= 4; r += 4; }
  if((x&3) == 0) { x >>= 2; r += 2; }
  if((x&1) == 0) ++r;
  return r;
}

// (public) returns index of lowest 1-bit (or -1 if none)
function bnGetLowestSetBit() {
  for(var i = 0; i < this.t; ++i)
    if(this[i] != 0) return i*this.DB+lbit(this[i]);
  if(this.s < 0) return this.t*this.DB;
  return -1;
}

// return number of 1 bits in x
function cbit(x) {
  var r = 0;
  while(x != 0) { x &= x-1; ++r; }
  return r;
}

// (public) return number of set bits
function bnBitCount() {
  var r = 0, x = this.s&this.DM;
  for(var i = 0; i < this.t; ++i) r += cbit(this[i]^x);
  return r;
}

// (public) true iff nth bit is set
function bnTestBit(n) {
  var j = Math.floor(n/this.DB);
  if(j >= this.t) return(this.s!=0);
  return((this[j]&(1<<(n%this.DB)))!=0);
}

// (protected) this op (1<<n)
function bnpChangeBit(n,op) {
  var r = BigInteger.ONE.shiftLeft(n);
  this.bitwiseTo(r,op,r);
  return r;
}

// (public) this | (1<<n)
function bnSetBit(n) { return this.changeBit(n,op_or); }

// (public) this & ~(1<<n)
function bnClearBit(n) { return this.changeBit(n,op_andnot); }

// (public) this ^ (1<<n)
function bnFlipBit(n) { return this.changeBit(n,op_xor); }

// (protected) r = this + a
function bnpAddTo(a,r) {
  var i = 0, c = 0, m = Math.min(a.t,this.t);
  while(i < m) {
    c += this[i]+a[i];
    r[i++] = c&this.DM;
    c >>= this.DB;
  }
  if(a.t < this.t) {
    c += a.s;
    while(i < this.t) {
      c += this[i];
      r[i++] = c&this.DM;
      c >>= this.DB;
    }
    c += this.s;
  }
  else {
    c += this.s;
    while(i < a.t) {
      c += a[i];
      r[i++] = c&this.DM;
      c >>= this.DB;
    }
    c += a.s;
  }
  r.s = (c<0)?-1:0;
  if(c > 0) r[i++] = c;
  else if(c < -1) r[i++] = this.DV+c;
  r.t = i;
  r.clamp();
}

// (public) this + a
function bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; }

// (public) this - a
function bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; }

// (public) this * a
function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; }

// (public) this^2
function bnSquare() { var r = nbi(); this.squareTo(r); return r; }

// (public) this / a
function bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; }

// (public) this % a
function bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; }

// (public) [this/a,this%a]
function bnDivideAndRemainder(a) {
  var q = nbi(), r = nbi();
  this.divRemTo(a,q,r);
  return new Array(q,r);
}

// (protected) this *= n, this >= 0, 1 < n < DV
function bnpDMultiply(n) {
  this[this.t] = this.am(0,n-1,this,0,0,this.t);
  ++this.t;
  this.clamp();
}

// (protected) this += n << w words, this >= 0
function bnpDAddOffset(n,w) {
  if(n == 0) return;
  while(this.t <= w) this[this.t++] = 0;
  this[w] += n;
  while(this[w] >= this.DV) {
    this[w] -= this.DV;
    if(++w >= this.t) this[this.t++] = 0;
    ++this[w];
  }
}

// A "null" reducer
function NullExp() {}
function nNop(x) { return x; }
function nMulTo(x,y,r) { x.multiplyTo(y,r); }
function nSqrTo(x,r) { x.squareTo(r); }

NullExp.prototype.convert = nNop;
NullExp.prototype.revert = nNop;
NullExp.prototype.mulTo = nMulTo;
NullExp.prototype.sqrTo = nSqrTo;

// (public) this^e
function bnPow(e) { return this.exp(e,new NullExp()); }

// (protected) r = lower n words of "this * a", a.t <= n
// "this" should be the larger one if appropriate.
function bnpMultiplyLowerTo(a,n,r) {
  var i = Math.min(this.t+a.t,n);
  r.s = 0; // assumes a,this >= 0
  r.t = i;
  while(i > 0) r[--i] = 0;
  var j;
  for(j = r.t-this.t; i < j; ++i) r[i+this.t] = this.am(0,a[i],r,i,0,this.t);
  for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a[i],r,i,0,n-i);
  r.clamp();
}

// (protected) r = "this * a" without lower n words, n > 0
// "this" should be the larger one if appropriate.
function bnpMultiplyUpperTo(a,n,r) {
  --n;
  var i = r.t = this.t+a.t-n;
  r.s = 0; // assumes a,this >= 0
  while(--i >= 0) r[i] = 0;
  for(i = Math.max(n-this.t,0); i < a.t; ++i)
    r[this.t+i-n] = this.am(n-i,a[i],r,0,0,this.t+i-n);
  r.clamp();
  r.drShiftTo(1,r);
}

// Barrett modular reduction
function Barrett(m) {
  // setup Barrett
  this.r2 = nbi();
  this.q3 = nbi();
  BigInteger.ONE.dlShiftTo(2*m.t,this.r2);
  this.mu = this.r2.divide(m);
  this.m = m;
}

function barrettConvert(x) {
  if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m);
  else if(x.compareTo(this.m) < 0) return x;
  else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; }
}

function barrettRevert(x) { return x; }

// x = x mod m (HAC 14.42)
function barrettReduce(x) {
  x.drShiftTo(this.m.t-1,this.r2);
  if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); }
  this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3);
  this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);
  while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1);
  x.subTo(this.r2,x);
  while(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
}

// r = x^2 mod m; x != r
function barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); }

// r = x*y mod m; x,y != r
function barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }

Barrett.prototype.convert = barrettConvert;
Barrett.prototype.revert = barrettRevert;
Barrett.prototype.reduce = barrettReduce;
Barrett.prototype.mulTo = barrettMulTo;
Barrett.prototype.sqrTo = barrettSqrTo;

// (public) this^e % m (HAC 14.85)
function bnModPow(e,m) {
  var i = e.bitLength(), k, r = nbv(1), z;
  if(i <= 0) return r;
  else if(i < 18) k = 1;
  else if(i < 48) k = 3;
  else if(i < 144) k = 4;
  else if(i < 768) k = 5;
  else k = 6;
  if(i < 8)
    z = new Classic(m);
  else if(m.isEven())
    z = new Barrett(m);
  else
    z = new Montgomery(m);

  // precomputation
  var g = new Array(), n = 3, k1 = k-1, km = (1<<k)-1;
  g[1] = z.convert(this);
  if(k > 1) {
    var g2 = nbi();
    z.sqrTo(g[1],g2);
    while(n <= km) {
      g[n] = nbi();
      z.mulTo(g2,g[n-2],g[n]);
      n += 2;
    }
  }

  var j = e.t-1, w, is1 = true, r2 = nbi(), t;
  i = nbits(e[j])-1;
  while(j >= 0) {
    if(i >= k1) w = (e[j]>>(i-k1))&km;
    else {
      w = (e[j]&((1<<(i+1))-1))<<(k1-i);
      if(j > 0) w |= e[j-1]>>(this.DB+i-k1);
    }

    n = k;
    while((w&1) == 0) { w >>= 1; --n; }
    if((i -= n) < 0) { i += this.DB; --j; }
    if(is1) {	// ret == 1, don't bother squaring or multiplying it
      g[w].copyTo(r);
      is1 = false;
    }
    else {
      while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; }
      if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; }
      z.mulTo(r2,g[w],r);
    }

    while(j >= 0 && (e[j]&(1<<i)) == 0) {
      z.sqrTo(r,r2); t = r; r = r2; r2 = t;
      if(--i < 0) { i = this.DB-1; --j; }
    }
  }
  return z.revert(r);
}

// (public) gcd(this,a) (HAC 14.54)
function bnGCD(a) {
  var x = (this.s<0)?this.negate():this.clone();
  var y = (a.s<0)?a.negate():a.clone();
  if(x.compareTo(y) < 0) { var t = x; x = y; y = t; }
  var i = x.getLowestSetBit(), g = y.getLowestSetBit();
  if(g < 0) return x;
  if(i < g) g = i;
  if(g > 0) {
    x.rShiftTo(g,x);
    y.rShiftTo(g,y);
  }
  while(x.signum() > 0) {
    if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x);
    if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y);
    if(x.compareTo(y) >= 0) {
      x.subTo(y,x);
      x.rShiftTo(1,x);
    }
    else {
      y.subTo(x,y);
      y.rShiftTo(1,y);
    }
  }
  if(g > 0) y.lShiftTo(g,y);
  return y;
}

// (protected) this % n, n < 2^26
function bnpModInt(n) {
  if(n <= 0) return 0;
  var d = this.DV%n, r = (this.s<0)?n-1:0;
  if(this.t > 0)
    if(d == 0) r = this[0]%n;
    else for(var i = this.t-1; i >= 0; --i) r = (d*r+this[i])%n;
  return r;
}

// (public) 1/this % m (HAC 14.61)
function bnModInverse(m) {
  var ac = m.isEven();
  if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO;
  var u = m.clone(), v = this.clone();
  var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1);
  while(u.signum() != 0) {
    while(u.isEven()) {
      u.rShiftTo(1,u);
      if(ac) {
        if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); }
        a.rShiftTo(1,a);
      }
      else if(!b.isEven()) b.subTo(m,b);
      b.rShiftTo(1,b);
    }
    while(v.isEven()) {
      v.rShiftTo(1,v);
      if(ac) {
        if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); }
        c.rShiftTo(1,c);
      }
      else if(!d.isEven()) d.subTo(m,d);
      d.rShiftTo(1,d);
    }
    if(u.compareTo(v) >= 0) {
      u.subTo(v,u);
      if(ac) a.subTo(c,a);
      b.subTo(d,b);
    }
    else {
      v.subTo(u,v);
      if(ac) c.subTo(a,c);
      d.subTo(b,d);
    }
  }
  if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO;
  if(d.compareTo(m) >= 0) return d.subtract(m);
  if(d.signum() < 0) d.addTo(m,d); else return d;
  if(d.signum() < 0) return d.add(m); else return d;
}

var lowprimes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997];
var lplim = (1<<26)/lowprimes[lowprimes.length-1];

// (public) test primality with certainty >= 1-.5^t
function bnIsProbablePrime(t) {
  var i, x = this.abs();
  if(x.t == 1 && x[0] <= lowprimes[lowprimes.length-1]) {
    for(i = 0; i < lowprimes.length; ++i)
      if(x[0] == lowprimes[i]) return true;
    return false;
  }
  if(x.isEven()) return false;
  i = 1;
  while(i < lowprimes.length) {
    var m = lowprimes[i], j = i+1;
    while(j < lowprimes.length && m < lplim) m *= lowprimes[j++];
    m = x.modInt(m);
    while(i < j) if(m%lowprimes[i++] == 0) return false;
  }
  return x.millerRabin(t);
}

// (protected) true if probably prime (HAC 4.24, Miller-Rabin)
function bnpMillerRabin(t) {
  var n1 = this.subtract(BigInteger.ONE);
  var k = n1.getLowestSetBit();
  if(k <= 0) return false;
  var r = n1.shiftRight(k);
  t = (t+1)>>1;
  if(t > lowprimes.length) t = lowprimes.length;
  var a = nbi();
  for(var i = 0; i < t; ++i) {
    //Pick bases at random, instead of starting at 2
    a.fromInt(lowprimes[Math.floor(Math.random()*lowprimes.length)]);
    var y = a.modPow(r,this);
    if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) {
      var j = 1;
      while(j++ < k && y.compareTo(n1) != 0) {
        y = y.modPowInt(2,this);
        if(y.compareTo(BigInteger.ONE) == 0) return false;
      }
      if(y.compareTo(n1) != 0) return false;
    }
  }
  return true;
}

// protected
BigInteger.prototype.chunkSize = bnpChunkSize;
BigInteger.prototype.toRadix = bnpToRadix;
BigInteger.prototype.fromRadix = bnpFromRadix;
BigInteger.prototype.fromNumber = bnpFromNumber;
BigInteger.prototype.bitwiseTo = bnpBitwiseTo;
BigInteger.prototype.changeBit = bnpChangeBit;
BigInteger.prototype.addTo = bnpAddTo;
BigInteger.prototype.dMultiply = bnpDMultiply;
BigInteger.prototype.dAddOffset = bnpDAddOffset;
BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo;
BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo;
BigInteger.prototype.modInt = bnpModInt;
BigInteger.prototype.millerRabin = bnpMillerRabin;

// public
BigInteger.prototype.clone = bnClone;
BigInteger.prototype.intValue = bnIntValue;
BigInteger.prototype.byteValue = bnByteValue;
BigInteger.prototype.shortValue = bnShortValue;
BigInteger.prototype.signum = bnSigNum;
BigInteger.prototype.toByteArray = bnToByteArray;
BigInteger.prototype.equals = bnEquals;
BigInteger.prototype.min = bnMin;
BigInteger.prototype.max = bnMax;
BigInteger.prototype.and = bnAnd;
BigInteger.prototype.or = bnOr;
BigInteger.prototype.xor = bnXor;
BigInteger.prototype.andNot = bnAndNot;
BigInteger.prototype.not = bnNot;
BigInteger.prototype.shiftLeft = bnShiftLeft;
BigInteger.prototype.shiftRight = bnShiftRight;
BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit;
BigInteger.prototype.bitCount = bnBitCount;
BigInteger.prototype.testBit = bnTestBit;
BigInteger.prototype.setBit = bnSetBit;
BigInteger.prototype.clearBit = bnClearBit;
BigInteger.prototype.flipBit = bnFlipBit;
BigInteger.prototype.add = bnAdd;
BigInteger.prototype.subtract = bnSubtract;
BigInteger.prototype.multiply = bnMultiply;
BigInteger.prototype.divide = bnDivide;
BigInteger.prototype.remainder = bnRemainder;
BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder;
BigInteger.prototype.modPow = bnModPow;
BigInteger.prototype.modInverse = bnModInverse;
BigInteger.prototype.pow = bnPow;
BigInteger.prototype.gcd = bnGCD;
BigInteger.prototype.isProbablePrime = bnIsProbablePrime;

// JSBN-specific extension
BigInteger.prototype.square = bnSquare;

// BigInteger interfaces not implemented in jsbn:

// BigInteger(int signum, byte[] magnitude)
// double doubleValue()
// float floatValue()
// int hashCode()
// long longValue()
// static BigInteger valueOf(long val)

exports.BigInteger = BigInteger;
module.exports = exports;
/**
 * Copyright (C) 2013-2016 Regents of the University of California.
 * @author: Wentao Shang
 *
 * 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.
 */

/** @ignore */
var ASN1HEX = require('../contrib/securityLib/asn1hex-1.1.js').ASN1HEX /** @ignore */
var KJUR = require('../contrib/securityLib/crypto-1.0.js').KJUR /** @ignore */
var RSAKey = require('../contrib/securityLib/rsasign-1.2.js').RSAKey /** @ignore */
var b64tohex = require('../contrib/securityLib/base64.js').b64tohex

// Library namespace
/** @ignore */
var ndn = ndn || {};

/** @ignore */
var exports = ndn;

// Factory method to create hasher objects
exports.createHash = function(alg)
{
  if (alg != 'sha256')
    throw new Error('createHash: unsupported algorithm.');

  var obj = {};

  obj.md = new KJUR.crypto.MessageDigest({alg: "sha256", prov: "cryptojs"});

  obj.update = function(buf) {
    this.md.updateHex(buf.toString('hex'));
  };

  obj.digest = function(encoding) {
    var hexDigest = this.md.digest();
    if (encoding == 'hex')
      return hexDigest;
    else if (encoding == 'base64')
      return new Buffer(hexDigest, 'hex').toString('base64');
    else
      return new Buffer(hexDigest, 'hex');
  };

  return obj;
};

// Factory method to create HMAC objects.
exports.createHmac = function(algorithm, key)
{
  if (algorithm !== 'sha256')
    throw new Error('createHmac: unsupported algorithm.');

  var obj = {};

  obj.md = new KJUR.crypto.Mac({alg: "HmacSHA256", pass: {hex: key.toString('hex')}});

  obj.update = function(buf) {
    this.md.updateHex(buf.toString('hex'));
  };

  obj.digest = function(encoding) {
    var hexDigest = this.md.doFinal();
    if (encoding == 'hex')
      return hexDigest;
    else if (encoding == 'base64')
      return new Buffer(hexDigest, 'hex').toString('base64');
    else
      return new Buffer(hexDigest, 'hex');
  };

  return obj;
};

// Factory method to create RSA signer objects
exports.createSign = function(alg)
{
  if (alg != 'RSA-SHA256')
    throw new Error('createSign: unsupported algorithm.');

  var obj = {};

  obj.arr = [];

  obj.update = function(buf) {
    this.arr.push(buf);
  };

  obj.sign = function(keypem) {
    var rsa = new RSAKey();
    rsa.readPrivateKeyFromPEMString(keypem);
    var signer = new KJUR.crypto.Signature({alg: "SHA256withRSA", prov: "cryptojs/jsrsa"});
    signer.initSign(rsa);
    for (var i = 0; i < this.arr.length; ++i)
      signer.updateHex(this.arr[i].toString('hex'));

    return new Buffer(signer.sign(), 'hex');
  };

  return obj;
};

// Factory method to create RSA verifier objects
exports.createVerify = function(alg)
{
  if (alg != 'RSA-SHA256')
    throw new Error('createSign: unsupported algorithm.');

  var obj = {};

  obj.arr = [];

  obj.update = function(buf) {
    this.arr.push(buf);
  };

  var getSubjectPublicKeyPosFromHex = function(hPub) {
    var a = ASN1HEX.getPosArrayOfChildren_AtObj(hPub, 0);
    if (a.length != 2)
      return -1;
    var pBitString = a[1];
    if (hPub.substring(pBitString, pBitString + 2) != '03')
      return -1;
    var pBitStringV = ASN1HEX.getStartPosOfV_AtObj(hPub, pBitString);
    if (hPub.substring(pBitStringV, pBitStringV + 2) != '00')
      return -1;
    return pBitStringV + 2;
  };

  var publicKeyPemToDer = function(publicKeyPem) {
    // Remove the '-----XXX-----' from the beginning and the end of the public
    // key and also remove any \n in the public key string.
    var lines = publicKeyPem.split('\n');
    var pub = "";
    for (var i = 1; i < lines.length - 1; i++)
      pub += lines[i];
    return new Buffer(pub, 'base64');
  }

  var readPublicDER = function(pub_der) {
    var hex = pub_der.toString('hex');
    var p = getSubjectPublicKeyPosFromHex(hex);
    var a = ASN1HEX.getPosArrayOfChildren_AtObj(hex, p);
    if (a.length != 2)
      return null;
    var hN = ASN1HEX.getHexOfV_AtObj(hex, a[0]);
    var hE = ASN1HEX.getHexOfV_AtObj(hex, a[1]);
    var rsaKey = new RSAKey();
    rsaKey.setPublic(hN, hE);
    return rsaKey;
  };

  obj.verify = function(keypem, sig) {
    var rsa = readPublicDER(publicKeyPemToDer(keypem));
    var signer = new KJUR.crypto.Signature({alg: "SHA256withRSA", prov: "cryptojs/jsrsa"});
    signer.initVerifyByPublicKey(rsa);
    for (var i = 0; i < this.arr.length; i++)
      signer.updateHex(this.arr[i].toString('hex'));
    var hSig = sig.toString('hex');
    return signer.verify(hSig);
  };

  return obj;
};

exports.randomBytes = function(size)
{
  // TODO: Use a cryptographic random number generator.
  var result = new Buffer(size);
  for (var i = 0; i < size; ++i)
    result[i] = Math.floor(Math.random() * 256);
  return result;
};

// contrib/feross/buffer.js needs base64.toByteArray. Define it here so that
// we don't have to include the entire base64 module.
exports.toByteArray = function(str) {
  var hex = b64tohex(str);
  var result = [];
  hex.replace(/(..)/g, function(ss) {
    result.push(parseInt(ss, 16));
  });
  return result;
};

module.exports = exports
// After this we include contrib/feross/buffer.js to define the Buffer class.
var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
var base64js = {};

;(function (exports) {
	'use strict';

  var Arr = (typeof Uint8Array !== 'undefined')
    ? Uint8Array
    : Array

	var PLUS   = '+'.charCodeAt(0)
	var SLASH  = '/'.charCodeAt(0)
	var NUMBER = '0'.charCodeAt(0)
	var LOWER  = 'a'.charCodeAt(0)
	var UPPER  = 'A'.charCodeAt(0)

	function decode (elt) {
		var code = elt.charCodeAt(0)
		if (code === PLUS)
			return 62 // '+'
		if (code === SLASH)
			return 63 // '/'
		if (code < NUMBER)
			return -1 //no match
		if (code < NUMBER + 10)
			return code - NUMBER + 26 + 26
		if (code < UPPER + 26)
			return code - UPPER
		if (code < LOWER + 26)
			return code - LOWER + 26
	}

	function b64ToByteArray (b64) {
		var i, j, l, tmp, placeHolders, arr

		if (b64.length % 4 > 0) {
			throw new Error('Invalid string. Length must be a multiple of 4')
		}

		// the number of equal signs (place holders)
		// if there are two placeholders, than the two characters before it
		// represent one byte
		// if there is only one, then the three characters before it represent 2 bytes
		// this is just a cheap hack to not do indexOf twice
		var len = b64.length
		placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0

		// base64 is 4/3 + up to two characters of the original data
		arr = new Arr(b64.length * 3 / 4 - placeHolders)

		// if there are placeholders, only get up to the last complete 4 chars
		l = placeHolders > 0 ? b64.length - 4 : b64.length

		var L = 0

		function push (v) {
			arr[L++] = v
		}

		for (i = 0, j = 0; i < l; i += 4, j += 3) {
			tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))
			push((tmp & 0xFF0000) >> 16)
			push((tmp & 0xFF00) >> 8)
			push(tmp & 0xFF)
		}

		if (placeHolders === 2) {
			tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)
			push(tmp & 0xFF)
		} else if (placeHolders === 1) {
			tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)
			push((tmp >> 8) & 0xFF)
			push(tmp & 0xFF)
		}

		return arr
	}

	function uint8ToBase64 (uint8) {
		var i,
			extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
			output = "",
			temp, length

		function encode (num) {
			return lookup.charAt(num)
		}

		function tripletToBase64 (num) {
			return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)
		}

		// go through the array every three bytes, we'll deal with trailing stuff later
		for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
			temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
			output += tripletToBase64(temp)
		}

		// pad the end with zeros, but make sure to not forget the extra bytes
		switch (extraBytes) {
			case 1:
				temp = uint8[uint8.length - 1]
				output += encode(temp >> 2)
				output += encode((temp << 4) & 0x3F)
				output += '=='
				break
			case 2:
				temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])
				output += encode(temp >> 10)
				output += encode((temp >> 4) & 0x3F)
				output += encode((temp << 2) & 0x3F)
				output += '='
				break
		}

		return output
	}

	exports.toByteArray = b64ToByteArray
	exports.fromByteArray = uint8ToBase64
})(base64js);
var ieee = {};

ieee.read = function(buffer, offset, isLE, mLen, nBytes) {
  var e, m,
      eLen = nBytes * 8 - mLen - 1,
      eMax = (1 << eLen) - 1,
      eBias = eMax >> 1,
      nBits = -7,
      i = isLE ? (nBytes - 1) : 0,
      d = isLE ? -1 : 1,
      s = buffer[offset + i];

  i += d;

  e = s & ((1 << (-nBits)) - 1);
  s >>= (-nBits);
  nBits += eLen;
  for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8);

  m = e & ((1 << (-nBits)) - 1);
  e >>= (-nBits);
  nBits += mLen;
  for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8);

  if (e === 0) {
    e = 1 - eBias;
  } else if (e === eMax) {
    return m ? NaN : ((s ? -1 : 1) * Infinity);
  } else {
    m = m + Math.pow(2, mLen);
    e = e - eBias;
  }
  return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
};

ieee.write = function(buffer, value, offset, isLE, mLen, nBytes) {
  var e, m, c,
      eLen = nBytes * 8 - mLen - 1,
      eMax = (1 << eLen) - 1,
      eBias = eMax >> 1,
      rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),
      i = isLE ? 0 : (nBytes - 1),
      d = isLE ? 1 : -1,
      s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;

  value = Math.abs(value);

  if (isNaN(value) || value === Infinity) {
    m = isNaN(value) ? 1 : 0;
    e = eMax;
  } else {
    e = Math.floor(Math.log(value) / Math.LN2);
    if (value * (c = Math.pow(2, -e)) < 1) {
      e--;
      c *= 2;
    }
    if (e + eBias >= 1) {
      value += rt / c;
    } else {
      value += rt * Math.pow(2, 1 - eBias);
    }
    if (value * c >= 2) {
      e++;
      c /= 2;
    }

    if (e + eBias >= eMax) {
      m = 0;
      e = eMax;
    } else if (e + eBias >= 1) {
      m = (value * c - 1) * Math.pow(2, mLen);
      e = e + eBias;
    } else {
      m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
      e = 0;
    }
  }

  for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8);

  e = (e << mLen) | m;
  eLen += mLen;
  for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8);

  buffer[offset + i - d] |= s * 128;
};

exports.ieee = ieee;
/**
 * The buffer module from node.js, for the browser.
 * @author   Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
 *
 * Copyright (C) 2013 Feross Aboukhadijeh, and other contributors.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * @license  MIT
 */

var base64 = base64js;
var ieee754 = require('./ieee754.js').ieee

exports.Buffer = Buffer
exports.SlowBuffer = Buffer
exports.INSPECT_MAX_BYTES = 50
Buffer.poolSize = 8192

/**
 * If `Buffer._useTypedArrays`:
 *   === true    Use Uint8Array implementation (fastest)
 *   === false   Use Object implementation (compatible down to IE6)
 */
Buffer._useTypedArrays = (function () {
  // Detect if browser supports Typed Arrays. Supported browsers are IE 10+, Firefox 4+,
  // Chrome 7+, Safari 5.1+, Opera 11.6+, iOS 4.2+. If the browser does not support adding
  // properties to `Uint8Array` instances, then that's the same as no `Uint8Array` support
  // because we need to be able to add all the node Buffer API methods. This is an issue
  // in Firefox 4-29. Now fixed: https://bugzilla.mozilla.org/show_bug.cgi?id=695438
  try {
    var buf = new ArrayBuffer(0)
    var arr = new Uint8Array(buf)
    arr.foo = function () { return 42 }
    return 42 === arr.foo() &&
        typeof arr.subarray === 'function' // Chrome 9-10 lack `subarray`
  } catch (e) {
    return false
  }
})()

/**
 * Class: Buffer
 * =============
 *
 * The Buffer constructor returns instances of `Uint8Array` that are augmented
 * with function properties for all the node `Buffer` API functions. We use
 * `Uint8Array` so that square bracket notation works as expected -- it returns
 * a single octet.
 *
 * By augmenting the instances, we can avoid modifying the `Uint8Array`
 * prototype.
 */
function Buffer (subject, encoding, noZero) {
  if (!(this instanceof Buffer))
    return new Buffer(subject, encoding, noZero)

  var type = typeof subject

  // Workaround: node's base64 implementation allows for non-padded strings
  // while base64-js does not.
  if (encoding === 'base64' && type === 'string') {
    subject = Buffer.stringtrim(subject)
    while (subject.length % 4 !== 0) {
      subject = subject + '='
    }
  }

  // Find the length
  var length
  if (type === 'number')
    length = Buffer.coerce(subject)
  else if (type === 'string')
    length = Buffer.byteLength(subject, encoding)
  else if (type === 'object')
    length = Buffer.coerce(subject.length) // assume that object is array-like
  else
    throw new Error('First argument needs to be a number, array or string.')

  var buf
  if (Buffer._useTypedArrays) {
    // Preferred: Return an augmented `Uint8Array` instance for best performance
    buf = Buffer._augment(new Uint8Array(length))
  } else {
    // Fallback: Return THIS instance of Buffer (created by `new`)
    buf = this
    buf.length = length
    buf._isBuffer = true
  }

  var i
  if (Buffer._useTypedArrays && typeof subject.byteLength === 'number') {
    // Speed optimization -- use set if we're copying from a typed array
    buf._set(subject)
  } else if (Buffer.isArrayish(subject)) {
    // Treat array-ish objects as a byte array
    if (Buffer.isBuffer(subject)) {
      for (i = 0; i < length; i++)
        buf[i] = subject.readUInt8(i)
    } else {
      for (i = 0; i < length; i++)
        buf[i] = ((subject[i] % 256) + 256) % 256
    }
  } else if (type === 'string') {
    buf.write(subject, 0, encoding)
  } else if (type === 'number' && !Buffer._useTypedArrays && !noZero) {
    for (i = 0; i < length; i++) {
      buf[i] = 0
    }
  }

  return buf
}

// STATIC METHODS
// ==============

Buffer.isEncoding = function (encoding) {
  switch (String(encoding).toLowerCase()) {
    case 'hex':
    case 'utf8':
    case 'utf-8':
    case 'ascii':
    case 'binary':
    case 'base64':
    case 'raw':
    case 'ucs2':
    case 'ucs-2':
    case 'utf16le':
    case 'utf-16le':
      return true
    default:
      return false
  }
}

Buffer.isBuffer = function (b) {
  return !!(b !== null && b !== undefined && b._isBuffer)
}

Buffer.byteLength = function (str, encoding) {
  var ret
  str = str.toString()
  switch (encoding || 'utf8') {
    case 'hex':
      ret = str.length / 2
      break
    case 'utf8':
    case 'utf-8':
      ret = Buffer.utf8ToBytes(str).length
      break
    case 'ascii':
    case 'binary':
    case 'raw':
      ret = str.length
      break
    case 'base64':
      ret = Buffer.base64ToBytes(str).length
      break
    case 'ucs2':
    case 'ucs-2':
    case 'utf16le':
    case 'utf-16le':
      ret = str.length * 2
      break
    default:
      throw new Error('Unknown encoding')
  }
  return ret
}

Buffer.concat = function (list, totalLength) {
  Buffer.assert(Buffer.isArray(list), 'Usage: Buffer.concat(list[, length])')

  if (list.length === 0) {
    return new Buffer(0)
  } else if (list.length === 1) {
    return list[0]
  }

  var i
  if (totalLength === undefined) {
    totalLength = 0
    for (i = 0; i < list.length; i++) {
      totalLength += list[i].length
    }
  }

  var buf = new Buffer(totalLength)
  var pos = 0
  for (i = 0; i < list.length; i++) {
    var item = list[i]
    item.copy(buf, pos)
    pos += item.length
  }
  return buf
}

Buffer.compare = function (a, b) {
  Buffer.assert(Buffer.isBuffer(a) && Buffer.isBuffer(b), 'Arguments must be Buffers')
  var x = a.length
  var y = b.length
  for (var i = 0, len = Math.min(x, y); i < len && a[i] === b[i]; i++) {}
  if (i !== len) {
    x = a[i]
    y = b[i]
  }
  if (x < y) {
    return -1
  }
  if (y < x) {
    return 1
  }
  return 0
}

// BUFFER INSTANCE METHODS
// =======================

Buffer.hexWrite = function(buf, string, offset, length) {
  offset = Number(offset) || 0
  var remaining = buf.length - offset
  if (!length) {
    length = remaining
  } else {
    length = Number(length)
    if (length > remaining) {
      length = remaining
    }
  }

  // must be an even number of digits
  var strLen = string.length
  Buffer.assert(strLen % 2 === 0, 'Invalid hex string')

  if (length > strLen / 2) {
    length = strLen / 2
  }
  for (var i = 0; i < length; i++) {
    var b = parseInt(string.substr(i * 2, 2), 16)
    Buffer.assert(!isNaN(b), 'Invalid hex string')
    buf[offset + i] = b
  }
  return i
}

Buffer.utf8Write = function(buf, string, offset, length) {
  var charsWritten = Buffer.blitBuffer(Buffer.utf8ToBytes(string), buf, offset, length)
  return charsWritten
}

Buffer.asciiWrite = function(buf, string, offset, length) {
  var charsWritten = Buffer.blitBuffer(Buffer.asciiToBytes(string), buf, offset, length)
  return charsWritten
}

Buffer.binaryWrite = function(buf, string, offset, length) {
  return Buffer.asciiWrite(buf, string, offset, length)
}

Buffer.base64Write = function(buf, string, offset, length) {
  var charsWritten = Buffer.blitBuffer(Buffer.base64ToBytes(string), buf, offset, length)
  return charsWritten
}

Buffer.utf16leWrite = function(buf, string, offset, length) {
  var charsWritten = Buffer.blitBuffer(Buffer.utf16leToBytes(string), buf, offset, length)
  return charsWritten
}

Buffer.prototype.write = function (string, offset, length, encoding) {
  // Support both (string, offset, length, encoding)
  // and the legacy (string, encoding, offset, length)
  if (isFinite(offset)) {
    if (!isFinite(length)) {
      encoding = length
      length = undefined
    }
  } else {  // legacy
    var swap = encoding
    encoding = offset
    offset = length
    length = swap
  }

  offset = Number(offset) || 0
  var remaining = this.length - offset
  if (!length) {
    length = remaining
  } else {
    length = Number(length)
    if (length > remaining) {
      length = remaining
    }
  }
  encoding = String(encoding || 'utf8').toLowerCase()

  var ret
  switch (encoding) {
    case 'hex':
      ret = Buffer.hexWrite(this, string, offset, length)
      break
    case 'utf8':
    case 'utf-8':
      ret = Buffer.utf8Write(this, string, offset, length)
      break
    case 'ascii':
      ret = Buffer.asciiWrite(this, string, offset, length)
      break
    case 'binary':
      ret = Buffer.binaryWrite(this, string, offset, length)
      break
    case 'base64':
      ret = Buffer.base64Write(this, string, offset, length)
      break
    case 'ucs2':
    case 'ucs-2':
    case 'utf16le':
    case 'utf-16le':
      ret = Buffer.utf16leWrite(this, string, offset, length)
      break
    default:
      throw new Error('Unknown encoding')
  }
  return ret
}

Buffer.prototype.toString = function (encoding, start, end) {
  var self = this

  encoding = String(encoding || 'utf8').toLowerCase()
  start = Number(start) || 0
  end = (end === undefined) ? self.length : Number(end)

  // Fastpath empty strings
  if (end === start)
    return ''

  var ret
  switch (encoding) {
    case 'hex':
      ret = Buffer.hexSlice(self, start, end)
      break
    case 'utf8':
    case 'utf-8':
      ret = Buffer.utf8Slice(self, start, end)
      break
    case 'ascii':
      ret = Buffer.asciiSlice(self, start, end)
      break
    case 'binary':
      ret = Buffer.binarySlice(self, start, end)
      break
    case 'base64':
      ret = Buffer.base64Slice(self, start, end)
      break
    case 'ucs2':
    case 'ucs-2':
    case 'utf16le':
    case 'utf-16le':
      ret = utf16leSlice(self, start, end)
      break
    default:
      throw new Error('Unknown encoding')
  }
  return ret
}

Buffer.prototype.toJSON = function () {
  return {
    type: 'Buffer',
    data: Array.prototype.slice.call(this._arr || this, 0)
  }
}

Buffer.prototype.equals = function (b) {
  Buffer.assert(Buffer.isBuffer(b), 'Argument must be a Buffer')
  return Buffer.compare(this, b) === 0
}

Buffer.prototype.compare = function (b) {
  Buffer.assert(Buffer.isBuffer(b), 'Argument must be a Buffer')
  return Buffer.compare(this, b)
}

// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
Buffer.prototype.copy = function (target, target_start, start, end) {
  var source = this

  if (!start) start = 0
  if (!end && end !== 0) end = this.length
  if (!target_start) target_start = 0

  // Copy 0 bytes; we're done
  if (end === start) return
  if (target.length === 0 || source.length === 0) return

  // Fatal error conditions
  Buffer.assert(end >= start, 'sourceEnd < sourceStart')
  Buffer.assert(target_start >= 0 && target_start < target.length,
      'targetStart out of bounds')
  Buffer.assert(start >= 0 && start < source.length, 'sourceStart out of bounds')
  Buffer.assert(end >= 0 && end <= source.length, 'sourceEnd out of bounds')

  // Are we oob?
  if (end > this.length)
    end = this.length
  if (target.length - target_start < end - start)
    end = target.length - target_start + start

  var len = end - start

  if (len < 100 || !Buffer._useTypedArrays) {
    for (var i = 0; i < len; i++) {
      target[i + target_start] = this[i + start]
    }
  } else {
    target._set(this.subarray(start, start + len), target_start)
  }
}

Buffer.base64Slice = function(buf, start, end) {
  if (start === 0 && end === buf.length) {
    return base64.fromByteArray(buf)
  } else {
    return base64.fromByteArray(buf.slice(start, end))
  }
}

Buffer.utf8Slice = function(buf, start, end) {
  var res = ''
  var tmp = ''
  end = Math.min(buf.length, end)

  for (var i = start; i < end; i++) {
    if (buf[i] <= 0x7F) {
      res += Buffer.decodeUtf8Char(tmp) + String.fromCharCode(buf[i])
      tmp = ''
    } else {
      tmp += '%' + buf[i].toString(16)
    }
  }

  return res + Buffer.decodeUtf8Char(tmp)
}

Buffer.asciiSlice = function(buf, start, end) {
  var ret = ''
  end = Math.min(buf.length, end)

  for (var i = start; i < end; i++) {
    ret += String.fromCharCode(buf[i])
  }
  return ret
}

Buffer.binarySlice = function(buf, start, end) {
  return Buffer.asciiSlice(buf, start, end)
}

Buffer.hexSlice = function(buf, start, end) {
  var len = buf.length

  if (!start || start < 0) start = 0
  if (!end || end < 0 || end > len) end = len

  var out = ''
  for (var i = start; i < end; i++) {
    out += Buffer.toHex(buf[i])
  }
  return out
}

function utf16leSlice (buf, start, end) {
  var bytes = buf.slice(start, end)
  var res = ''
  for (var i = 0; i < bytes.length; i += 2) {
    res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)
  }
  return res
}

Buffer.prototype.slice = function (start, end) {
  var len = this.length
  start = Buffer.clamp(start, len, 0)
  end = Buffer.clamp(end, len, len)

  if (Buffer._useTypedArrays) {
    return Buffer._augment(this.subarray(start, end))
  } else {
    var sliceLen = end - start
    var newBuf = new Buffer(sliceLen, undefined, true)
    for (var i = 0; i < sliceLen; i++) {
      newBuf[i] = this[i + start]
    }
    return newBuf
  }
}

// `get` will be removed in Node 0.13+
Buffer.prototype.get = function (offset) {
  console.log('.get() is deprecated. Access using array indexes instead.')
  return this.readUInt8(offset)
}

// `set` will be removed in Node 0.13+
Buffer.prototype.set = function (v, offset) {
  console.log('.set() is deprecated. Access using array indexes instead.')
  return this.writeUInt8(v, offset)
}

Buffer.prototype.readUInt8 = function (offset, noAssert) {
  if (!noAssert) {
    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
    Buffer.assert(offset < this.length, 'Trying to read beyond buffer length')
  }

  if (offset >= this.length)
    return

  return this[offset]
}

Buffer.readUInt16 = function(buf, offset, littleEndian, noAssert) {
  if (!noAssert) {
    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
    Buffer.assert(offset + 1 < buf.length, 'Trying to read beyond buffer length')
  }

  var len = buf.length
  if (offset >= len)
    return

  var val
  if (littleEndian) {
    val = buf[offset]
    if (offset + 1 < len)
      val |= buf[offset + 1] << 8
  } else {
    val = buf[offset] << 8
    if (offset + 1 < len)
      val |= buf[offset + 1]
  }
  return val
}

Buffer.prototype.readUInt16LE = function (offset, noAssert) {
  return Buffer.readUInt16(this, offset, true, noAssert)
}

Buffer.prototype.readUInt16BE = function (offset, noAssert) {
  return Buffer.readUInt16(this, offset, false, noAssert)
}

Buffer.readUInt32 = function(buf, offset, littleEndian, noAssert) {
  if (!noAssert) {
    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
    Buffer.assert(offset + 3 < buf.length, 'Trying to read beyond buffer length')
  }

  var len = buf.length
  if (offset >= len)
    return

  var val
  if (littleEndian) {
    if (offset + 2 < len)
      val = buf[offset + 2] << 16
    if (offset + 1 < len)
      val |= buf[offset + 1] << 8
    val |= buf[offset]
    if (offset + 3 < len)
      val = val + (buf[offset + 3] << 24 >>> 0)
  } else {
    if (offset + 1 < len)
      val = buf[offset + 1] << 16
    if (offset + 2 < len)
      val |= buf[offset + 2] << 8
    if (offset + 3 < len)
      val |= buf[offset + 3]
    val = val + (buf[offset] << 24 >>> 0)
  }
  return val
}

Buffer.prototype.readUInt32LE = function (offset, noAssert) {
  return Buffer.readUInt32(this, offset, true, noAssert)
}

Buffer.prototype.readUInt32BE = function (offset, noAssert) {
  return Buffer.readUInt32(this, offset, false, noAssert)
}

Buffer.prototype.readInt8 = function (offset, noAssert) {
  if (!noAssert) {
    Buffer.assert(offset !== undefined && offset !== null,
        'missing offset')
    Buffer.assert(offset < this.length, 'Trying to read beyond buffer length')
  }

  if (offset >= this.length)
    return

  var neg = this[offset] & 0x80
  if (neg)
    return (0xff - this[offset] + 1) * -1
  else
    return this[offset]
}

Buffer.readInt16 = function(buf, offset, littleEndian, noAssert) {
  if (!noAssert) {
    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
    Buffer.assert(offset + 1 < buf.length, 'Trying to read beyond buffer length')
  }

  var len = buf.length
  if (offset >= len)
    return

  var val = Buffer.readUInt16(buf, offset, littleEndian, true)
  var neg = val & 0x8000
  if (neg)
    return (0xffff - val + 1) * -1
  else
    return val
}

Buffer.prototype.readInt16LE = function (offset, noAssert) {
  return Buffer.readInt16(this, offset, true, noAssert)
}

Buffer.prototype.readInt16BE = function (offset, noAssert) {
  return Buffer.readInt16(this, offset, false, noAssert)
}

Buffer.readInt32 = function(buf, offset, littleEndian, noAssert) {
  if (!noAssert) {
    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
    Buffer.assert(offset + 3 < buf.length, 'Trying to read beyond buffer length')
  }

  var len = buf.length
  if (offset >= len)
    return

  var val = Buffer.readUInt32(buf, offset, littleEndian, true)
  var neg = val & 0x80000000
  if (neg)
    return (0xffffffff - val + 1) * -1
  else
    return val
}

Buffer.prototype.readInt32LE = function (offset, noAssert) {
  return Buffer.readInt32(this, offset, true, noAssert)
}

Buffer.prototype.readInt32BE = function (offset, noAssert) {
  return Buffer.readInt32(this, offset, false, noAssert)
}

Buffer.readFloat = function(buf, offset, littleEndian, noAssert) {
  if (!noAssert) {
    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
    Buffer.assert(offset + 3 < buf.length, 'Trying to read beyond buffer length')
  }

  return ieee754.read(buf, offset, littleEndian, 23, 4)
}

Buffer.prototype.readFloatLE = function (offset, noAssert) {
  return Buffer.readFloat(this, offset, true, noAssert)
}

Buffer.prototype.readFloatBE = function (offset, noAssert) {
  return Buffer.readFloat(this, offset, false, noAssert)
}

Buffer.readDouble = function(buf, offset, littleEndian, noAssert) {
  if (!noAssert) {
    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
    Buffer.assert(offset + 7 < buf.length, 'Trying to read beyond buffer length')
  }

  return ieee754.read(buf, offset, littleEndian, 52, 8)
}

Buffer.prototype.readDoubleLE = function (offset, noAssert) {
  return Buffer.readDouble(this, offset, true, noAssert)
}

Buffer.prototype.readDoubleBE = function (offset, noAssert) {
  return Buffer.readDouble(this, offset, false, noAssert)
}

Buffer.prototype.writeUInt8 = function (value, offset, noAssert) {
  if (!noAssert) {
    Buffer.assert(value !== undefined && value !== null, 'missing value')
    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
    Buffer.assert(offset < this.length, 'trying to write beyond buffer length')
    Buffer.verifuint(value, 0xff)
  }

  if (offset >= this.length) return

  this[offset] = value
  return offset + 1
}

Buffer.writeUInt16 = function(buf, value, offset, littleEndian, noAssert) {
  if (!noAssert) {
    Buffer.assert(value !== undefined && value !== null, 'missing value')
    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
    Buffer.assert(offset + 1 < buf.length, 'trying to write beyond buffer length')
    Buffer.verifuint(value, 0xffff)
  }

  var len = buf.length
  if (offset >= len)
    return

  for (var i = 0, j = Math.min(len - offset, 2); i < j; i++) {
    buf[offset + i] =
        (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
            (littleEndian ? i : 1 - i) * 8
  }
  return offset + 2
}

Buffer.prototype.writeUInt16LE = function (value, offset, noAssert) {
  return Buffer.writeUInt16(this, value, offset, true, noAssert)
}

Buffer.prototype.writeUInt16BE = function (value, offset, noAssert) {
  return Buffer.writeUInt16(this, value, offset, false, noAssert)
}

Buffer.writeUInt32 = function(buf, value, offset, littleEndian, noAssert) {
  if (!noAssert) {
    Buffer.assert(value !== undefined && value !== null, 'missing value')
    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
    Buffer.assert(offset + 3 < buf.length, 'trying to write beyond buffer length')
    Buffer.verifuint(value, 0xffffffff)
  }

  var len = buf.length
  if (offset >= len)
    return

  for (var i = 0, j = Math.min(len - offset, 4); i < j; i++) {
    buf[offset + i] =
        (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff
  }
  return offset + 4
}

Buffer.prototype.writeUInt32LE = function (value, offset, noAssert) {
  return Buffer.writeUInt32(this, value, offset, true, noAssert)
}

Buffer.prototype.writeUInt32BE = function (value, offset, noAssert) {
  return Buffer.writeUInt32(this, value, offset, false, noAssert)
}

Buffer.prototype.writeInt8 = function (value, offset, noAssert) {
  if (!noAssert) {
    Buffer.assert(value !== undefined && value !== null, 'missing value')
    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
    Buffer.assert(offset < this.length, 'Trying to write beyond buffer length')
    Buffer.verifsint(value, 0x7f, -0x80)
  }

  if (offset >= this.length)
    return

  if (value >= 0)
    this.writeUInt8(value, offset, noAssert)
  else
    this.writeUInt8(0xff + value + 1, offset, noAssert)
  return offset + 1
}

Buffer.writeInt16 = function(buf, value, offset, littleEndian, noAssert) {
  if (!noAssert) {
    Buffer.assert(value !== undefined && value !== null, 'missing value')
    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
    Buffer.assert(offset + 1 < buf.length, 'Trying to write beyond buffer length')
    Buffer.verifsint(value, 0x7fff, -0x8000)
  }

  var len = buf.length
  if (offset >= len)
    return

  if (value >= 0)
    Buffer.writeUInt16(buf, value, offset, littleEndian, noAssert)
  else
    Buffer.writeUInt16(buf, 0xffff + value + 1, offset, littleEndian, noAssert)
  return offset + 2
}

Buffer.prototype.writeInt16LE = function (value, offset, noAssert) {
  return Buffer.writeInt16(this, value, offset, true, noAssert)
}

Buffer.prototype.writeInt16BE = function (value, offset, noAssert) {
  return Buffer.writeInt16(this, value, offset, false, noAssert)
}

Buffer.writeInt32 = function(buf, value, offset, littleEndian, noAssert) {
  if (!noAssert) {
    Buffer.assert(value !== undefined && value !== null, 'missing value')
    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
    Buffer.assert(offset + 3 < buf.length, 'Trying to write beyond buffer length')
    Buffer.verifsint(value, 0x7fffffff, -0x80000000)
  }

  var len = buf.length
  if (offset >= len)
    return

  if (value >= 0)
    Buffer.writeUInt32(buf, value, offset, littleEndian, noAssert)
  else
    Buffer.writeUInt32(buf, 0xffffffff + value + 1, offset, littleEndian, noAssert)
  return offset + 4
}

Buffer.prototype.writeInt32LE = function (value, offset, noAssert) {
  return Buffer.writeInt32(this, value, offset, true, noAssert)
}

Buffer.prototype.writeInt32BE = function (value, offset, noAssert) {
  return Buffer.writeInt32(this, value, offset, false, noAssert)
}

Buffer.writeFloat = function(buf, value, offset, littleEndian, noAssert) {
  if (!noAssert) {
    Buffer.assert(value !== undefined && value !== null, 'missing value')
    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
    Buffer.assert(offset + 3 < buf.length, 'Trying to write beyond buffer length')
    Buffer.verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38)
  }

  var len = buf.length
  if (offset >= len)
    return

  ieee754.write(buf, value, offset, littleEndian, 23, 4)
  return offset + 4
}

Buffer.prototype.writeFloatLE = function (value, offset, noAssert) {
  return Buffer.writeFloat(this, value, offset, true, noAssert)
}

Buffer.prototype.writeFloatBE = function (value, offset, noAssert) {
  return Buffer.writeFloat(this, value, offset, false, noAssert)
}

Buffer.writeDouble = function(buf, value, offset, littleEndian, noAssert) {
  if (!noAssert) {
    Buffer.assert(value !== undefined && value !== null, 'missing value')
    Buffer.assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
    Buffer.assert(offset !== undefined && offset !== null, 'missing offset')
    Buffer.assert(offset + 7 < buf.length,
        'Trying to write beyond buffer length')
    Buffer.verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308)
  }

  var len = buf.length
  if (offset >= len)
    return

  ieee754.write(buf, value, offset, littleEndian, 52, 8)
  return offset + 8
}

Buffer.prototype.writeDoubleLE = function (value, offset, noAssert) {
  return Buffer.writeDouble(this, value, offset, true, noAssert)
}

Buffer.prototype.writeDoubleBE = function (value, offset, noAssert) {
  return Buffer.writeDouble(this, value, offset, false, noAssert)
}

// fill(value, start=0, end=buffer.length)
Buffer.prototype.fill = function (value, start, end) {
  if (!value) value = 0
  if (!start) start = 0
  if (!end) end = this.length

  Buffer.assert(end >= start, 'end < start')

  // Fill 0 bytes; we're done
  if (end === start) return
  if (this.length === 0) return

  Buffer.assert(start >= 0 && start < this.length, 'start out of bounds')
  Buffer.assert(end >= 0 && end <= this.length, 'end out of bounds')

  var i
  if (typeof value === 'number') {
    for (i = start; i < end; i++) {
      this[i] = value
    }
  } else {
    var bytes = Buffer.utf8ToBytes(value.toString())
    var len = bytes.length
    for (i = start; i < end; i++) {
      this[i] = bytes[i % len]
    }
  }

  return this
}

Buffer.prototype.inspect = function () {
  var out = []
  var len = this.length
  for (var i = 0; i < len; i++) {
    out[i] = Buffer.toHex(this[i])
    if (i === exports.INSPECT_MAX_BYTES) {
      out[i + 1] = '...'
      break
    }
  }
  return '<Buffer ' + out.join(' ') + '>'
}

/**
 * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance.
 * Added in Node 0.12. Only available in browsers that support ArrayBuffer.
 */
Buffer.prototype.toArrayBuffer = function () {
  if (typeof Uint8Array !== 'undefined') {
    if (Buffer._useTypedArrays) {
      return (new Buffer(this)).buffer
    } else {
      var buf = new Uint8Array(this.length)
      for (var i = 0, len = buf.length; i < len; i += 1) {
        buf[i] = this[i]
      }
      return buf.buffer
    }
  } else {
    throw new Error('Buffer.toArrayBuffer not supported in this browser')
  }
}

// HELPER FUNCTIONS
// ================

var BP = Buffer.prototype

/**
 * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods
 */
Buffer._augment = function (arr) {
  arr._isBuffer = true

  // save reference to original Uint8Array get/set methods before overwriting
  arr._get = arr.get
  arr._set = arr.set

  // deprecated, will be removed in node 0.13+
  arr.get = BP.get
  arr.set = BP.set

  arr.write = BP.write
  arr.toString = BP.toString
  arr.toLocaleString = BP.toString
  arr.toJSON = BP.toJSON
  arr.equals = BP.equals
  arr.compare = BP.compare
  arr.copy = BP.copy
  arr.slice = BP.slice
  arr.readUInt8 = BP.readUInt8
  arr.readUInt16LE = BP.readUInt16LE
  arr.readUInt16BE = BP.readUInt16BE
  arr.readUInt32LE = BP.readUInt32LE
  arr.readUInt32BE = BP.readUInt32BE
  arr.readInt8 = BP.readInt8
  arr.readInt16LE = BP.readInt16LE
  arr.readInt16BE = BP.readInt16BE
  arr.readInt32LE = BP.readInt32LE
  arr.readInt32BE = BP.readInt32BE
  arr.readFloatLE = BP.readFloatLE
  arr.readFloatBE = BP.readFloatBE
  arr.readDoubleLE = BP.readDoubleLE
  arr.readDoubleBE = BP.readDoubleBE
  arr.writeUInt8 = BP.writeUInt8
  arr.writeUInt16LE = BP.writeUInt16LE
  arr.writeUInt16BE = BP.writeUInt16BE
  arr.writeUInt32LE = BP.writeUInt32LE
  arr.writeUInt32BE = BP.writeUInt32BE
  arr.writeInt8 = BP.writeInt8
  arr.writeInt16LE = BP.writeInt16LE
  arr.writeInt16BE = BP.writeInt16BE
  arr.writeInt32LE = BP.writeInt32LE
  arr.writeInt32BE = BP.writeInt32BE
  arr.writeFloatLE = BP.writeFloatLE
  arr.writeFloatBE = BP.writeFloatBE
  arr.writeDoubleLE = BP.writeDoubleLE
  arr.writeDoubleBE = BP.writeDoubleBE
  arr.fill = BP.fill
  arr.inspect = BP.inspect
  arr.toArrayBuffer = BP.toArrayBuffer

  return arr
}

Buffer.stringtrim = function(str) {
  if (str.trim) return str.trim()
  return str.replace(/^\s+|\s+$/g, '')
}

// slice(start, end)
Buffer.clamp = function(index, len, defaultValue) {
  if (typeof index !== 'number') return defaultValue
  index = ~~index;  // Coerce to integer.
  if (index >= len) return len
  if (index >= 0) return index
  index += len
  if (index >= 0) return index
  return 0
}

Buffer.coerce = function(length) {
  // Coerce length to a number (possibly NaN), round up
  // in case it's fractional (e.g. 123.456) then do a
  // double negate to coerce a NaN to 0. Easy, right?
  length = ~~Math.ceil(+length)
  return length < 0 ? 0 : length
}

Buffer.isArray = function(subject) {
  return (Array.isArray || function (subject) {
    return Object.prototype.toString.call(subject) === '[object Array]'
  })(subject)
}

Buffer.isArrayish = function(subject) {
  return Buffer.isArray(subject) || Buffer.isBuffer(subject) ||
      subject && typeof subject === 'object' &&
      typeof subject.length === 'number'
}

Buffer.toHex = function(n) {
  if (n < 16) return '0' + n.toString(16)
  return n.toString(16)
}

Buffer.utf8ToBytes = function(str) {
  var byteArray = []
  for (var i = 0; i < str.length; i++) {
    var b = str.charCodeAt(i)
    if (b <= 0x7F) {
      byteArray.push(b)
    } else {
      var start = i
      if (b >= 0xD800 && b <= 0xDFFF) i++
      var h = encodeURIComponent(str.slice(start, i+1)).substr(1).split('%')
      for (var j = 0; j < h.length; j++) {
        byteArray.push(parseInt(h[j], 16))
      }
    }
  }
  return byteArray
}

Buffer.asciiToBytes = function(str) {
  var byteArray = []
  for (var i = 0; i < str.length; i++) {
    // Node's code seems to be doing this and not & 0x7F..
    byteArray.push(str.charCodeAt(i) & 0xFF)
  }
  return byteArray
}

Buffer.utf16leToBytes = function(str) {
  var c, hi, lo
  var byteArray = []
  for (var i = 0; i < str.length; i++) {
    c = str.charCodeAt(i)
    hi = c >> 8
    lo = c % 256
    byteArray.push(lo)
    byteArray.push(hi)
  }

  return byteArray
}

Buffer.base64ToBytes = function(str) {
  return base64.toByteArray(str)
}

Buffer.blitBuffer = function(src, dst, offset, length) {
  for (var i = 0; i < length; i++) {
    if ((i + offset >= dst.length) || (i >= src.length))
      break
    dst[i + offset] = src[i]
  }
  return i
}

Buffer.decodeUtf8Char = function(str) {
  try {
    return decodeURIComponent(str)
  } catch (err) {
    return String.fromCharCode(0xFFFD) // UTF 8 invalid char
  }
}

/*
 * We have to make sure that the value is a valid integer. This means that it
 * is non-negative. It has no fractional component and that it does not
 * exceed the maximum allowed value.
 */
Buffer.verifuint = function(value, max) {
  Buffer.assert(typeof value === 'number', 'cannot write a non-number as a number')
  Buffer.assert(value >= 0, 'specified a negative value for writing an unsigned value')
  Buffer.assert(value <= max, 'value is larger than maximum value for type')
  Buffer.assert(Math.floor(value) === value, 'value has a fractional component')
}

Buffer.verifsint = function(value, max, min) {
  Buffer.assert(typeof value === 'number', 'cannot write a non-number as a number')
  Buffer.assert(value <= max, 'value larger than maximum allowed value')
  Buffer.assert(value >= min, 'value smaller than minimum allowed value')
  Buffer.assert(Math.floor(value) === value, 'value has a fractional component')
}

Buffer.verifIEEE754 = function(value, max, min) {
  Buffer.assert(typeof value === 'number', 'cannot write a non-number as a number')
  Buffer.assert(value <= max, 'value larger than maximum allowed value')
  Buffer.assert(value >= min, 'value smaller than minimum allowed value')
}

Buffer.assert = function(test, message) {
  if (!test) throw new Error(message || 'Failed assertion')
}
/**
 * Copyright (C) 2013-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/**
 * The Log class holds the global static variable LOG.
 */
var Log = function Log()
{
}

exports.Log = Log;

/**
 * LOG is the level for logging debugging statements.  0 means no log messages.
 * @type Number
 */
Log.LOG = 0;
/**
 * Encapsulate a Buffer and support dynamic reallocation.
 * Copyright (C) 2015-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var printStackTrace = require('../../contrib/stacktrace/stacktrace.js').printStackTrace;

/**
 * NdnCommon has static NDN utility methods and constants.
 * @constructor
 */
var NdnCommon = {};

exports.NdnCommon = NdnCommon;

/**
 * The practical limit of the size of a network-layer packet. If a packet is
 * larger than this, the library or application MAY drop it. This constant is
 * defined in this low-level class so that internal code can use it, but
 * applications should use the static API method
 * Face.getMaxNdnPacketSize() which is equivalent.
 */
NdnCommon.MAX_NDN_PACKET_SIZE = 8800;

/**
 * Get the error message plus its stack trace.
 * @param {Error} error The error object.
 * @return {string} The error message, plus the stack trace with each line
 * separated by '\n'.
 */
NdnCommon.getErrorWithStackTrace = function(error)
{
  return error + '\n' + printStackTrace({e: error}).join('\n');
};

/**
 * Check for Indexed DB support and call onComplete with the result as described
 * below. This has to use an onComplete callback since IndexedDB is async.
 * @param {function} onComplete This calls onComplete(haveIndexedDb) where
 * haveIndexedDb is true if the browser has Indexed DB support, otherwise false.
 */
NdnCommon.checkIndexedDb = function(onComplete)
{
  try {
    var database = new Dexie("test-Dexie-support");
    database.version(1).stores({});
    database.open();

    // Give Dexie a little time to open.
    setTimeout(function() {
      try {
        onComplete(database.isOpen());
      } catch (ex) {
        onComplete(false);
      }
    }, 200);
  } catch (ex) {
    onComplete(false);
  }
};
/**
 * Copyright (C) 2015-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var NdnCommon = require('./ndn-common.js').NdnCommon;

/**
 * An ExponentialReExpress uses an internal onTimeout to express the interest again
 * with double the interestLifetime. See ExponentialReExpress.makeOnTimeout,
 * which you should call instead of the private constructor.
 * Create a new ExponentialReExpress where onTimeout expresses the interest
 * again with double the interestLifetime. If the interesLifetime goes
 * over settings.maxInterestLifetime, then call the given onTimeout. If this
 * internally gets onData, just call the given onData.
 * @constructor
 */
var ExponentialReExpress = function ExponentialReExpress
  (face, onData, onTimeout, settings)
{
  settings = (settings || {});
  this.face = face;
  this.callerOnData = onData;
  this.callerOnTimeout = onTimeout;

  this.maxInterestLifetime = (settings.maxInterestLifetime || 16000);
};

exports.ExponentialReExpress = ExponentialReExpress;

/**
 * Return a callback to use in expressInterest for onTimeout which will express
 * the interest again with double the interestLifetime. If the interesLifetime
 * goes over maxInterestLifetime (see settings below), then call the provided
 * onTimeout. If a Data packet is received, this calls the provided onData.
 * Use it like this:
 *   var onData = function() { ... };
 *   var onTimeout = function() { ... };
 *   face.expressInterest
 *     (interest, onData,
 *      ExponentialReExpress.makeOnTimeout(face, onData, onTimeout));
 * @param {Face} face This calls face.expressInterest.
 * @param {function} onData When a matching data packet is received, this calls
 * onData(interest, data) where interest is the interest given to
 * expressInterest and data is the received Data object. This is normally the
 * same onData you initially passed to expressInterest.
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onTimeout If the interesLifetime goes over
 * maxInterestLifetime, this calls onTimeout(interest). However, if onTimeout is
 * null, this does not use it.
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {Object} settings (optional) If not null, an associative array with
 * the following defaults:
 * {
 *   maxInterestLifetime: 16000 // milliseconds
 * }
 * @return {function} The onTimeout callback to pass to expressInterest.
 */
ExponentialReExpress.makeOnTimeout = function(face, onData, onTimeout, settings)
{
  var reExpress = new ExponentialReExpress(face, onData, onTimeout, settings);
  return function(interest) { reExpress.onTimeout(interest); };
};

ExponentialReExpress.prototype.onTimeout = function(interest)
{
  var interestLifetime = interest.getInterestLifetimeMilliseconds();
  if (interestLifetime == null) {
    // Can't re-express.
    if (this.callerOnTimeout) {
      try {
        this.callerOnTimeout(interest);
      } catch (ex) {
        console.log("Error in onTimeout: " + NdnCommon.getErrorWithStackTrace(ex));
      }
    }
    return;
  }

  var nextInterestLifetime = interestLifetime * 2;
  if (nextInterestLifetime > this.maxInterestLifetime) {
    if (this.callerOnTimeout) {
      try {
        this.callerOnTimeout(interest);
      } catch (ex) {
        console.log("Error in onTimeout: " + NdnCommon.getErrorWithStackTrace(ex));
      }
    }
    return;
  }

  var nextInterest = interest.clone();
  nextInterest.setInterestLifetimeMilliseconds(nextInterestLifetime);
  var thisObject = this;
  this.face.expressInterest
    (nextInterest, this.callerOnData,
     function(localInterest) { thisObject.onTimeout(localInterest); });
};
/**
 * Copyright (C) 2013 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/**
 * A Blob holds an immutable byte array implemented as a Buffer.  This should be
 * treated like a string which is a pointer to an immutable string. (It is OK to
 * pass a pointer to the string because the new owner can’t change the bytes of
 * the string.)  Blob does not inherit from Buffer. Instead you must call buf()
 * to get the byte array which reminds you that you should not change the
 * contents.  Also remember that buf() can return null.
 * @param {Blob|Buffer|Array<number>} value (optional) If value is a Blob, take
 * another pointer to the Buffer without copying. If value is a Buffer or byte
 * array, copy to create a new Buffer.  If omitted, buf() will return null.
 * @param {boolean} copy (optional) If true, copy the contents of
 * value into a new Buffer.  If false, just use the existing value without
 * copying. If omitted, then copy the contents (unless value is already a Blob).
 * IMPORTANT: If copy is false, if you keep a pointer to the value then you must
 * treat the value as immutable and promise not to change it.
 * @constructor
 */
var Blob = function Blob(value, copy)
{
  if (copy == null)
    copy = true;

  if (value == null)
    this.buffer = null;
  else if (typeof value === 'object' && value instanceof Blob)
    // Use the existing buffer.  Don't need to check for copy.
    this.buffer = value.buffer;
  else {
    if (typeof value === 'string')
      // Convert from a string to utf-8 byte encoding.
      this.buffer = new Buffer(value, 'utf8');
    else {
      if (copy)
        // We are copying, so just make another Buffer.
        this.buffer = new Buffer(value);
      else {
        if (Buffer.isBuffer(value))
          // We can use as-is.
          this.buffer = value;
        else
          // We need a Buffer, so copy.
          this.buffer = new Buffer(value);
      }
    }
  }

  // Set the length to be "JavaScript-like".
  this.length = this.buffer != null ? this.buffer.length : 0;
};

exports.Blob = Blob;

/**
 * Return the length of the immutable byte array.
 * @return {number} The length of the array.  If buf() is null, return 0.
 */
Blob.prototype.size = function()
{
  if (this.buffer != null)
    return this.buffer.length;
  else
    return 0;
};

/**
 * Return the immutable byte array.  DO NOT change the contents of the Buffer.
 * If you need to change it, make a copy.
 * @return {Buffer} The Buffer holding the immutable byte array, or null.
 */
Blob.prototype.buf = function()
{
  return this.buffer;
};

/**
 * Return true if the array is null, otherwise false.
 * @return {boolean} True if the array is null.
 */
Blob.prototype.isNull = function()
{
  return this.buffer == null;
};

/**
 * Return the hex representation of the bytes in the byte array.
 * @return {string} The hex string.
 */
Blob.prototype.toHex = function()
{
  if (this.buffer == null)
    return "";
  else
    return this.buffer.toString('hex');
};

/**
 * Decode the byte array as UTF8 and return the Unicode string.
 * @return A unicode string, or "" if the buffer is null.
 */
Blob.prototype.toString = function()
{
  if (this.buffer == null)
    return "";
  else
    return this.buffer.toString('utf8');
};

/**
 * Check if the value of this Blob equals the other blob.
 * @param {Blob} other The other Blob to check.
 * @return {boolean} if this isNull and other isNull or if the bytes of this
 * blob equal the bytes of the other.
 */
Blob.prototype.equals = function(other)
{
  if (this.isNull())
    return other.isNull();
  else if (other.isNull())
    return false;
  else {
    if (this.buffer.length != other.buffer.length)
      return false;

    for (var i = 0; i < this.buffer.length; ++i) {
      if (this.buffer[i] != other.buffer[i])
        return false;
    }

    return true;
  }
};
/**
 * Copyright (C) 2013 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var Blob = require('./blob.js').Blob;

/**
 * A SignedBlob extends Blob to keep the offsets of a signed portion (e.g., the
 * bytes of Data packet). This inherits from Blob, including Blob.size and Blob.buf.
 * @param {Blob|Buffer|Array<number>} value (optional) If value is a Blob, take
 * another pointer to the Buffer without copying. If value is a Buffer or byte
 * array, copy to create a new Buffer.  If omitted, buf() will return null.
 * @param {number} signedPortionBeginOffset (optional) The offset in the
 * encoding of the beginning of the signed portion. If omitted, set to 0.
 * @param {number} signedPortionEndOffset (optional) The offset in the encoding
 * of the end of the signed portion. If omitted, set to 0.
 * @constructor
 */
var SignedBlob = function SignedBlob(value, signedPortionBeginOffset, signedPortionEndOffset)
{
  // Call the base constructor.
  Blob.call(this, value);

  if (this.buffer == null) {
    this.signedPortionBeginOffset = 0;
    this.signedPortionEndOffset = 0;
  }
  else if (typeof value === 'object' && value instanceof SignedBlob) {
    // Copy the SignedBlob, allowing override for offsets.
    this.signedPortionBeginOffset = signedPortionBeginOffset == null ?
      value.signedPortionBeginOffset : signedPortionBeginOffset;
    this.signedPortionEndOffset = signedPortionEndOffset == null ?
      value.signedPortionEndOffset : signedPortionEndOffset;
  }
  else {
    this.signedPortionBeginOffset = signedPortionBeginOffset || 0;
    this.signedPortionEndOffset = signedPortionEndOffset || 0;
  }

  if (this.buffer == null)
    this.signedBuffer = null;
  else
    this.signedBuffer = this.buffer.slice
      (this.signedPortionBeginOffset, this.signedPortionEndOffset);
};

SignedBlob.prototype = new Blob();
SignedBlob.prototype.name = "SignedBlob";

exports.SignedBlob = SignedBlob;

/**
 * Return the length of the signed portion of the immutable byte array.
 * @return {number} The length of the signed portion.  If signedBuf() is null,
 * return 0.
 */
SignedBlob.prototype.signedSize = function()
{
  if (this.signedBuffer != null)
    return this.signedBuffer.length;
  else
    return 0;
};

/**
 * Return a the signed portion of the immutable byte array.
 * @return {Buffer} A slice into the Buffer which is the signed portion.
 * If the pointer to the array is null, return null.
 */
SignedBlob.prototype.signedBuf = function() { return this.signedBuffer; };

/**
 * Return the offset in the array of the beginning of the signed portion.
 * @return {number} The offset in the array.
 */
SignedBlob.prototype.getSignedPortionBeginOffset = function()
{
  return this.signedPortionBeginOffset;
};

/**
 * Return the offset in the array of the end of the signed portion.
 * @return {number} The offset in the array.
 */
SignedBlob.prototype.getSignedPortionEndOffset = function()
{
  return this.signedPortionEndOffset;
};
/**
 * Encapsulate a Buffer and support dynamic reallocation.
 * Copyright (C) 2013-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/**
 * Create a DynamicBuffer where this.array is a Buffer of size length.
 * To access the array, use this.array or call slice.
 * @constructor
 * @param {number} length the initial length of the array.  If null, use a default.
 */
var DynamicBuffer = function DynamicBuffer(length)
{
  if (!length)
    length = 16;

  this.array = new Buffer(length);
};

exports.DynamicBuffer = DynamicBuffer;

/**
 * Ensure that this.array has the length, reallocate and copy if necessary.
 * Update the length of this.array which may be greater than length.
 * @param {number} length The minimum length for the array.
 */
DynamicBuffer.prototype.ensureLength = function(length)
{
  if (this.array.length >= length)
    return;

  // See if double is enough.
  var newLength = this.array.length * 2;
  if (length > newLength)
    // The needed length is much greater, so use it.
    newLength = length;

  var newArray = new Buffer(newLength);
  this.array.copy(newArray);
  this.array = newArray;
};

/**
 * Copy the value to this.array at offset, reallocating if necessary.
 * @param {Buffer} value The buffer to copy.
 * @param {number} offset The offset in the buffer to start copying into.
 * @return {number} The new offset which is offset + value.length.
 */
DynamicBuffer.prototype.copy = function(value, offset)
{
  this.ensureLength(value.length + offset);

  if (Buffer.isBuffer(value))
    value.copy(this.array, offset);
  else
    // Need to make value a Buffer to copy.
    new Buffer(value).copy(this.array, offset);

  return offset + value.length;
};

/**
 * Ensure that this.array has the length. If necessary, reallocate the array
 *   and shift existing data to the back of the new array.
 * Update the length of this.array which may be greater than length.
 * @param {number} length The minimum length for the array.
 */
DynamicBuffer.prototype.ensureLengthFromBack = function(length)
{
  if (this.array.length >= length)
    return;

  // See if double is enough.
  var newLength = this.array.length * 2;
  if (length > newLength)
    // The needed length is much greater, so use it.
    newLength = length;

  var newArray = new Buffer(newLength);
  // Copy to the back of newArray.
  this.array.copy(newArray, newArray.length - this.array.length);
  this.array = newArray;
};

/**
 * First call ensureLengthFromBack to make sure the bytearray has
 * offsetFromBack bytes, then copy value into the array starting
 * offsetFromBack bytes from the back of the array.
 * @param {Buffer} value The buffer to copy.
 * @param {number} offsetFromBack The offset from the back of the array to start
 * copying.
 */
DynamicBuffer.prototype.copyFromBack = function(value, offsetFromBack)
{
  this.ensureLengthFromBack(offsetFromBack);

  if (Buffer.isBuffer(value))
    value.copy(this.array, this.array.length - offsetFromBack);
  else
    // Need to make value a Buffer to copy.
    new Buffer(value).copy(this.array, this.array.length - offsetFromBack);
};

/**
 * Return this.array.slice(begin, end);
 * @param {number} begin The begin index for the slice.
 * @param {number} end (optional) The end index for the slice.
 * @return {Buffer} The buffer slice.
 */
DynamicBuffer.prototype.slice = function(begin, end)
{
  if (end == undefined)
    return this.array.slice(begin);
  else
    return this.array.slice(begin, end);
};
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/**
 * A ChangeCounter keeps a target object whose change count is tracked by a
 * local change count.  You can set to a new target which updates the local
 * change count, and you can call checkChanged to check if the target (or one of
 * the target's targets) has been changed. The target object must have a method
 * getChangeCount.
 *
 * Create a new ChangeCounter to track the given target. If target is not null,
 * this sets the local change counter to target.getChangeCount().
 * @param {object} target The target to track, as an object with the method
 * getChangeCount().
 * @constructor
 */
var ChangeCounter = function ChangeCounter(target)
{
  this.target = target;
  this.changeCount = (target == null ? 0 : target.getChangeCount());
};

exports.ChangeCounter = ChangeCounter;

/**
 * Get the target object. If the target is changed, then checkChanged will
 * detect it.
 * @return {object} The target, as an object with the method
 * getChangeCount().
 */
ChangeCounter.prototype.get = function()
{
  return this.target;
};

/**
 * Set the target to the given target. If target is not null, this sets the
 * local change counter to target.getChangeCount().
 * @param {object} target The target to track, as an object with the method
 * getChangeCount().
 */
ChangeCounter.prototype.set = function(target)
{
  this.target = target;
  this.changeCount = (target == null ? 0 : target.getChangeCount());
};

/**
 * If the target's change count is different than the local change count, then
 * update the local change count and return true. Otherwise return false,
 * meaning that the target has not changed. Also, if the target is null,
 * simply return false. This is useful since the target (or one of the target's
 * targets) may be changed and you need to find out.
 * @return {boolean} True if the change count has been updated, false if not.
 */
ChangeCounter.prototype.checkChanged = function()
{
  if (this.target == null)
    return false;

  var targetChangeCount = this.target.getChangeCount();
  if (this.changeCount != targetChangeCount) {
    this.changeCount = targetChangeCount;
    return true;
  }
  else
    return false;
};
/**
 * Copyright (C) 2015-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var NdnCommon = require('./ndn-common.js').NdnCommon;

/**
 * A SyncPromise is a promise which is immediately fulfilled or rejected, used
 * to return a promise in synchronous code.
 * This private constructor creates a SyncPromise fulfilled or rejected with the
 * given value. You should normally not call this constructor but call
 * SyncPromise.resolve or SyncPromise.reject. Note that we don't need a
 * constructor like SyncPromise(function(resolve, reject)) because this would be
 * for scheduling the function to be called later, which we don't do.
 * @param {any} value If isRejected is false, this is the value of the fulfilled
 * promise, else if isRejected is true, this is the error.
 * @param {boolean} isRejected True to create a promise in the rejected state,
 * where value is the error.
 * @constructor
 */
var SyncPromise = function SyncPromise(value, isRejected)
{
  this.value = value;
  this.isRejected = isRejected;
};

exports.SyncPromise = SyncPromise;

/**
 * If this promise is fulfilled, immediately call onFulfilled with the fulfilled
 * value as described below. Otherwise, if this promise is rejected, immediately
 * call onRejected with the error as described below.
 * @param {function} (optional) onFulfilled If this promise is fulfilled, this
 * calls onFulfilled(value) with the value of this promise and returns the
 * result. The function should return a promise. To use all synchronous code,
 * onFulfilled should return SyncPromise.resolve(newValue).
 * @param {function} (optional) onRejected If this promise is rejected, this
 * calls onRejected(err) with the error value of this promise and returns the
 * result. The function should return a promise. To use all synchronous code,
 * onFulfilled should return SyncPromise.resolve(newValue) (or throw an
 * exception).
 * @return {Promise|SyncPromise} If this promise is fulfilled, return the result
 * of calling onFulfilled(value). Note that this does not create a promise which
 * is scheduled to execute later. Rather it immediately calls onFulfilled which
 * should return a promise. But if onFulfilled is undefined, simply return this
 * promise to pass it forward. If this promise is rejected, return the result of
 * calling onRejected(err) with the error value. But if onRejected is undefined,
 * simply return this promise to pass it forward. However, if onFulfilled or
 * onRejected throws an exception, then return a new SyncPromise in the rejected
 * state with the exception.
 */
SyncPromise.prototype.then = function(onFulfilled, onRejected)
{
  if (this.isRejected) {
    if (onRejected) {
      try {
        return onRejected(this.value);
      }
      catch(err) {
        return new SyncPromise(err, true);
      }
    }
    else
      // Pass the error forward.
      return this;
  }
  else {
    if (onFulfilled) {
      try {
        return onFulfilled(this.value);
      }
      catch(err) {
        return new SyncPromise(err, true);
      }
    }
    else
      // Pass the fulfilled value forward.
      return this;
  }
};

/**
 * Call this.then(undefined, onRejected) and return the result. If this promise
 * is rejected then onRejected will process it. If this promise is fulfilled,
 * this simply passes it forward.
 */
SyncPromise.prototype.catch = function(onRejected)
{
  return this.then(undefined, onRejected);
};

/**
 * Return a new SyncPromise which is already fulfilled to the given value.
 * @param {any} value The value of the promise.
 */
SyncPromise.resolve = function(value)
{
  return new SyncPromise(value, false);
};

/**
 * Return a new SyncPromise which is already rejected with the given error.
 * @param {any} err The error for the rejected promise.
 */
SyncPromise.reject = function(err)
{
  return new SyncPromise(err, true);
};

/**
 * This static method checks if the promise is a SyncPromise and immediately
 * returns its value or throws the error if promise is rejected. If promise is
 * not a SyncPromise, this throws an exception since it is not possible to
 * immediately get the value. This can be used with "promise-based" code which
 * you expect to always return a SyncPromise to operate in synchronous mode.
 * @param {SyncPromise} promise The SyncPromise with the value to get.
 * @return {any} The value of the promise.
 * @throws Error If promise is not a SyncPromise.
 * @throws any If promise is a SyncPromise in the rejected state, this throws
 * the error.
 */
SyncPromise.getValue = function(promise)
{
  if (promise instanceof SyncPromise) {
    if (promise.isRejected)
      throw promise.value;
    else
      return promise.value;
  }
  else
    throw new Error("Cannot return immediately because promise is not a SyncPromise");
};

/**
 * This can be called with complete(onComplete, promise) or
 * complete(onComplete, onError, promise) to handle both synchronous and
 * asynchronous code based on whether the caller supplies the onComlete callback.
 * If onComplete is defined, call promise.then with a function which calls
 * onComplete(value) when fulfilled (possibly in asynchronous mode). If
 * onComplete is undefined, then we are in synchronous mode so return
 * SyncPromise.getValue(promise) which will throw an exception if the promise is
 * not a SyncPromise (or is a SyncPromise in the rejected state).
 * @param {function} onComplete If defined, this calls promise.then to fulfill
 * the promise, then calls onComplete(value) with the value of the promise.
 * If onComplete is undefined, the return value is described below.
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onError (optional) If defined, then onComplete must be
 * defined and if there is an error when this calls promise.then, this calls
 * onError(err) with the value of the error. If onComplete is undefined, then
 * onError is ignored and this will call SyncPromise.getValue(promise) which may
 * throw an exception.
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {Promise|SyncPromise} promise If onComplete is defined, this calls
 * promise.then. Otherwise, this calls SyncPromise.getValue(promise).
 * @return {any} If onComplete is undefined, return SyncPromise.getValue(promise).
 * Otherwise, if onComplete is supplied then return undefined and use
 * onComplete as described above.
 * @throws Error If onComplete is undefined and promise is not a SyncPromise.
 * @throws any If onComplete is undefined and promise is a SyncPromise in the
 * rejected state.
 */
SyncPromise.complete = function(onComplete, onErrorOrPromise, promise)
{
  var onError;
  if (promise)
    onError = onErrorOrPromise;
  else {
    promise = onErrorOrPromise;
    onError = null;
  }

  if (onComplete)
    promise
    .then(function(value) {
      try {
        onComplete(value);
      } catch (ex) {
        console.log("Error in onComplete: " + NdnCommon.getErrorWithStackTrace(ex));
      }
    }, function(err) {
      if (onError) {
        try {
          onError(err);
        } catch (ex) {
          console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
        }
      }
      else {
        if (promise instanceof SyncPromise)
          throw err;
        else
          // We are in an async promise callback, so a thrown exception won't
          // reach the caller. Just log it.
          console.log("Uncaught exception from a Promise: " +
            NdnCommon.getErrorWithStackTrace(err));
      }
    });
  else
    return SyncPromise.getValue(promise);
};
/**
 * This class contains utilities to help parse the data
 *
 * Copyright (C) 2013-2016 Regents of the University of California.
 * @author: Meki Cheraoui
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/**
 * A DataUtils has static methods for converting data.
 * @constructor
 */
var DataUtils = {};

exports.DataUtils = DataUtils;

/*
 * NOTE THIS IS CURRENTLY NOT BEING USED
 *
 */

DataUtils.keyStr = "ABCDEFGHIJKLMNOP" +
                   "QRSTUVWXYZabcdef" +
                   "ghijklmnopqrstuv" +
                   "wxyz0123456789+/" +
                   "=";

/**
 * Raw String to Base 64
 */
DataUtils.stringtoBase64 = function stringtoBase64(input)
{
   //input = escape(input);
   var output = "";
   var chr1, chr2, chr3 = "";
   var enc1, enc2, enc3, enc4 = "";
   var i = 0;

   do {
    chr1 = input.charCodeAt(i++);
    chr2 = input.charCodeAt(i++);
    chr3 = input.charCodeAt(i++);

    enc1 = chr1 >> 2;
    enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
    enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
    enc4 = chr3 & 63;

    if (isNaN(chr2))
       enc3 = enc4 = 64;
    else if (isNaN(chr3))
       enc4 = 64;

    output = output +
       DataUtils.keyStr.charAt(enc1) +
       DataUtils.keyStr.charAt(enc2) +
       DataUtils.keyStr.charAt(enc3) +
       DataUtils.keyStr.charAt(enc4);
    chr1 = chr2 = chr3 = "";
    enc1 = enc2 = enc3 = enc4 = "";
   } while (i < input.length);

   return output;
};

/**
 * Base 64 to Raw String
 */
DataUtils.base64toString = function base64toString(input)
{
  var output = "";
  var chr1, chr2, chr3 = "";
  var enc1, enc2, enc3, enc4 = "";
  var i = 0;

  // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
  var base64test = /[^A-Za-z0-9\+\/\=]/g;
  /* Test for invalid characters. */
  if (base64test.exec(input)) {
    alert("There were invalid base64 characters in the input text.\n" +
          "Valid base64 characters are A-Z, a-z, 0-9, '+', '/',and '='\n" +
          "Expect errors in decoding.");
  }

  input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

  do {
    enc1 = DataUtils.keyStr.indexOf(input.charAt(i++));
    enc2 = DataUtils.keyStr.indexOf(input.charAt(i++));
    enc3 = DataUtils.keyStr.indexOf(input.charAt(i++));
    enc4 = DataUtils.keyStr.indexOf(input.charAt(i++));

    chr1 = (enc1 << 2) | (enc2 >> 4);
    chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
    chr3 = ((enc3 & 3) << 6) | enc4;

    output = output + String.fromCharCode(chr1);

    if (enc3 != 64)
      output = output + String.fromCharCode(chr2);

    if (enc4 != 64)
      output = output + String.fromCharCode(chr3);

    chr1 = chr2 = chr3 = "";
    enc1 = enc2 = enc3 = enc4 = "";
  } while (i < input.length);

  return output;
};

/**
 * Buffer to Hex String
 */
DataUtils.toHex = function(buffer)
{
  return buffer.toString('hex');
};

/**
 * Raw string to hex string.
 */
DataUtils.stringToHex = function(args)
{
  var ret = "";
  for (var i = 0; i < args.length; ++i) {
    var value = args.charCodeAt(i);
    ret += (value < 16 ? "0" : "") + value.toString(16);
  }
  return ret;
};

/**
 * Buffer to raw string.
 */
DataUtils.toString = function(buffer)
{
  return buffer.toString('binary');
};

/**
 * Hex String to Buffer.
 */
DataUtils.toNumbers = function(str)
{
  return new Buffer(str, 'hex');
};

/**
 * Hex String to raw string.
 */
DataUtils.hexToRawString = function(str)
{
  if (typeof str =='string') {
  var ret = "";
  str.replace(/(..)/g, function(s) {
    ret += String.fromCharCode(parseInt(s, 16));
  });
  return ret;
  }
};

/**
 * Raw String to Buffer.
 */
DataUtils.toNumbersFromString = function(str)
{
  return new Buffer(str, 'binary');
};

/**
 * If value is a string, then interpret it as a raw string and convert to
 * a Buffer. Otherwise assume it is a Buffer or array type and just return it.
 * @param {string|any} value
 * @return {Buffer}
 */
DataUtils.toNumbersIfString = function(value)
{
  if (typeof value === 'string')
    return new Buffer(value, 'binary');
  else
    return value;
};

/**
 * Encode str as utf8 and return as Buffer.
 */
DataUtils.stringToUtf8Array = function(str)
{
  return new Buffer(str, 'utf8');
};

/**
 * arrays is an array of Buffer. Return a new Buffer which is the concatenation of all.
 */
DataUtils.concatArrays = function(arrays)
{
  return Buffer.concat(arrays);
};

// TODO: Take Buffer and use TextDecoder when available.
DataUtils.decodeUtf8 = function(utftext)
{
  var string = "";
  var i = 0;
  var c = 0;
    var c1 = 0;
    var c2 = 0;

  while (i < utftext.length) {
    c = utftext.charCodeAt(i);

    if (c < 128) {
      string += String.fromCharCode(c);
      i++;
    }
    else if (c > 191 && c < 224) {
      c2 = utftext.charCodeAt(i + 1);
      string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
      i += 2;
    }
    else {
      c2 = utftext.charCodeAt(i+1);
      var c3 = utftext.charCodeAt(i+2);
      string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
      i += 3;
    }
  }

  return string;
};

/**
 * Return true if a1 and a2 are the same length with equal elements.
 */
DataUtils.arraysEqual = function(a1, a2)
{
  // A simple sanity check that it is an array.
  if (!a1.slice)
    throw new Error("DataUtils.arraysEqual: a1 is not an array");
  if (!a2.slice)
    throw new Error("DataUtils.arraysEqual: a2 is not an array");

  if (a1.length != a2.length)
    return false;

  for (var i = 0; i < a1.length; ++i) {
    if (a1[i] != a2[i])
      return false;
  }

  return true;
};

/**
 * Convert the big endian Buffer to an unsigned int.
 * Don't check for overflow.
 */
DataUtils.bigEndianToUnsignedInt = function(bytes)
{
  var result = 0;
  for (var i = 0; i < bytes.length; ++i) {
    // Multiply by 0x100 instead of shift by 8 because << is restricted to 32 bits.
    result *= 0x100;
    result += bytes[i];
  }
  return result;
};

/**
 * Convert the int value to a new big endian Buffer and return.
 * If value is 0 or negative, return new Buffer(0).
 */
DataUtils.nonNegativeIntToBigEndian = function(value)
{
  value = Math.round(value);
  if (value <= 0)
    return new Buffer(0);

  // Assume value is not over 64 bits.
  var size = 8;
  var result = new Buffer(size);
  var i = 0;
  while (value != 0) {
    ++i;
    result[size - i] = value & 0xff;
    // Divide by 0x100 and floor instead of shift by 8 because >> is restricted to 32 bits.
    value = Math.floor(value / 0x100);
  }
  return result.slice(size - i, size);
};

/**
 * Modify array to randomly shuffle the elements.
 */
DataUtils.shuffle = function(array)
{
  for (var i = array.length - 1; i >= 1; --i) {
    // j is from 0 to i.
    var j = Math.floor(Math.random() * (i + 1));
    var temp = array[i];
    array[i] = array[j];
    array[j] = temp;
  }
};

/**
 * Decode the base64-encoded private key PEM and return the binary DER.
 * @param {string} The PEM-encoded private key.
 * @return {Buffer} The binary DER.
 *
 */
DataUtils.privateKeyPemToDer = function(privateKeyPem)
{
  // Remove the '-----XXX-----' from the beginning and the end of the key and
  // also remove any \n in the key string.
  var lines = privateKeyPem.split('\n');
  var privateKey = "";
  for (var i = 1; i < lines.length - 1; i++)
    privateKey += lines[i];

  return new Buffer(privateKey, 'base64');
};
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/**
 * Create a new DecodingException wrapping the given error object.
 * Call with: throw new DecodingException(new Error("message")).
 * @constructor
 * @param {Error} error The exception created with new Error.
 */
function DecodingException(error)
{
  if (error) {
    error.__proto__ = DecodingException.prototype;
    return error;
  }
}
DecodingException.prototype = new Error();
DecodingException.prototype.name = "DecodingException";

exports.DecodingException = DecodingException;
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/**
 * The Tlv class has static type codes for the NDN-TLV wire format.
 * @constructor
 */
var Tlv = function Tlv()
{
};

exports.Tlv = Tlv;

Tlv.Interest =         5;
Tlv.Data =             6;
Tlv.Name =             7;
Tlv.ImplicitSha256DigestComponent = 1;
Tlv.NameComponent =    8;
Tlv.Selectors =        9;
Tlv.Nonce =            10;
// <Unassigned> =      11;
Tlv.InterestLifetime = 12;
Tlv.MinSuffixComponents = 13;
Tlv.MaxSuffixComponents = 14;
Tlv.PublisherPublicKeyLocator = 15;
Tlv.Exclude =          16;
Tlv.ChildSelector =    17;
Tlv.MustBeFresh =      18;
Tlv.Any =              19;
Tlv.MetaInfo =         20;
Tlv.Content =          21;
Tlv.SignatureInfo =    22;
Tlv.SignatureValue =   23;
Tlv.ContentType =      24;
Tlv.FreshnessPeriod =  25;
Tlv.FinalBlockId =     26;
Tlv.SignatureType =    27;
Tlv.KeyLocator =       28;
Tlv.KeyLocatorDigest = 29;
Tlv.SelectedDelegation = 32;
Tlv.FaceInstance =     128;
Tlv.ForwardingEntry =  129;
Tlv.StatusResponse =   130;
Tlv.Action =           131;
Tlv.FaceID =           132;
Tlv.IPProto =          133;
Tlv.Host =             134;
Tlv.Port =             135;
Tlv.MulticastInterface = 136;
Tlv.MulticastTTL =     137;
Tlv.ForwardingFlags =  138;
Tlv.StatusCode =       139;
Tlv.StatusText =       140;

Tlv.SignatureType_DigestSha256 = 0;
Tlv.SignatureType_SignatureSha256WithRsa = 1;
Tlv.SignatureType_SignatureSha256WithEcdsa = 3;
Tlv.SignatureType_SignatureHmacWithSha256 = 4;

Tlv.ContentType_Default = 0;
Tlv.ContentType_Link =    1;
Tlv.ContentType_Key =     2;

Tlv.NfdCommand_ControlResponse = 101;
Tlv.NfdCommand_StatusCode =      102;
Tlv.NfdCommand_StatusText =      103;

Tlv.ControlParameters_ControlParameters =   104;
Tlv.ControlParameters_FaceId =              105;
Tlv.ControlParameters_Uri =                 114;
Tlv.ControlParameters_LocalControlFeature = 110;
Tlv.ControlParameters_Origin =              111;
Tlv.ControlParameters_Cost =                106;
Tlv.ControlParameters_Flags =               108;
Tlv.ControlParameters_Strategy =            107;
Tlv.ControlParameters_ExpirationPeriod =    109;

Tlv.LpPacket_LpPacket =        100;
Tlv.LpPacket_Fragment =         80;
Tlv.LpPacket_Sequence =         81;
Tlv.LpPacket_FragIndex =        82;
Tlv.LpPacket_FragCount =        83;
Tlv.LpPacket_Nack =            800;
Tlv.LpPacket_NackReason =      801;
Tlv.LpPacket_NextHopFaceId =   816;
Tlv.LpPacket_IncomingFaceId =  817;
Tlv.LpPacket_CachePolicy =     820;
Tlv.LpPacket_CachePolicyType = 821;
Tlv.LpPacket_IGNORE_MIN =      800;
Tlv.LpPacket_IGNORE_MAX =      959;

Tlv.Link_Preference = 30;
Tlv.Link_Delegation = 31;

Tlv.Encrypt_EncryptedContent = 130;
Tlv.Encrypt_EncryptionAlgorithm = 131;
Tlv.Encrypt_EncryptedPayload = 132;
Tlv.Encrypt_InitialVector = 133;

// For RepetitiveInterval.
Tlv.Encrypt_StartDate = 134;
Tlv.Encrypt_EndDate = 135;
Tlv.Encrypt_IntervalStartHour = 136;
Tlv.Encrypt_IntervalEndHour = 137;
Tlv.Encrypt_NRepeats = 138;
Tlv.Encrypt_RepeatUnit = 139;
Tlv.Encrypt_RepetitiveInterval = 140;

// For Schedule.
Tlv.Encrypt_WhiteIntervalList = 141;
Tlv.Encrypt_BlackIntervalList = 142;
Tlv.Encrypt_Schedule = 143;

/**
 * Strip off the lower 32 bits of x and divide by 2^32, returning the "high
 * bytes" above 32 bits.  This is necessary because JavaScript << and >> are
 * restricted to 32 bits.
 * (This could be a general function, but we define it here so that the
 * Tlv encoder/decoder is self-contained.)
 * @param {number} x
 * @return {number}
 */
Tlv.getHighBytes = function(x)
{
  // Don't use floor because we expect the caller to use & and >> on the result
  // which already strip off the fraction.
  return (x - (x % 0x100000000)) / 0x100000000;
};
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var DynamicBuffer = require('../../util/dynamic-buffer.js').DynamicBuffer; /** @ignore */
var Tlv = require('./tlv.js').Tlv;

/**
 * Create a new TlvEncoder with an initialCapacity for the encoding buffer.
 * @constructor
 * @param {number} initialCapacity (optional) The initial capacity of the
 * encoding buffer. If omitted, use a default value.
 */
var TlvEncoder = function TlvEncoder(initialCapacity)
{
  initialCapacity = initialCapacity || 16;
  this.output = new DynamicBuffer(initialCapacity);
  // length is the number of bytes that have been written to the back of
  //  this.output.array.
  this.length = 0;
};

exports.TlvEncoder = TlvEncoder;

/**
 * Get the number of bytes that have been written to the output.  You can
 * save this number, write sub TLVs, then subtract the new length from this
 * to get the total length of the sub TLVs.
 * @return {number} The number of bytes that have been written to the output.
 */
TlvEncoder.prototype.getLength = function()
{
  return this.length;
};

/**
 * Encode varNumber as a VAR-NUMBER in NDN-TLV and write it to this.output just
 * before this.length from the back.  Advance this.length.
 * @param {number} varNumber The non-negative number to encode.
 */
TlvEncoder.prototype.writeVarNumber = function(varNumber)
{
  if (varNumber < 253) {
    this.length += 1;
    this.output.ensureLengthFromBack(this.length);
    this.output.array[this.output.array.length - this.length] = varNumber & 0xff;
  }
  else if (varNumber <= 0xffff) {
    this.length += 3;
    this.output.ensureLengthFromBack(this.length);
    var offset = this.output.array.length - this.length;
    this.output.array[offset] = 253;
    this.output.array[offset + 1] = (varNumber >> 8) & 0xff;
    this.output.array[offset + 2] = varNumber & 0xff;
  }
  else if (varNumber <= 0xffffffff) {
    this.length += 5;
    this.output.ensureLengthFromBack(this.length);
    var offset = this.output.array.length - this.length;
    this.output.array[offset] = 254;
    this.output.array[offset + 1] = (varNumber >> 24) & 0xff;
    this.output.array[offset + 2] = (varNumber >> 16) & 0xff;
    this.output.array[offset + 3] = (varNumber >> 8) & 0xff;
    this.output.array[offset + 4] = varNumber & 0xff;
  }
  else {
    this.length += 9;
    this.output.ensureLengthFromBack(this.length);
    var offset = this.output.array.length - this.length;
    this.output.array[offset] = 255;
    var highBytes = Tlv.getHighBytes(varNumber);
    this.output.array[offset + 1] = (highBytes >> 24) & 0xff;
    this.output.array[offset + 2] = (highBytes >> 16) & 0xff;
    this.output.array[offset + 3] = (highBytes >> 8)  & 0xff;
    this.output.array[offset + 4] = (highBytes)       & 0xff;
    this.output.array[offset + 5] = (varNumber >> 24) & 0xff;
    this.output.array[offset + 6] = (varNumber >> 16) & 0xff;
    this.output.array[offset + 7] = (varNumber >> 8) & 0xff;
    this.output.array[offset + 8] = varNumber & 0xff;
  }
};

/**
 * Encode the type and length as VAR-NUMBER and write to this.output just before
 * this.length from the back.  Advance this.length.
 * @param {number} type The type of the TLV.
 * @param {number} length The non-negative length of the TLV.
 */
TlvEncoder.prototype.writeTypeAndLength = function(type, length)
{
  // Write backwards.
  this.writeVarNumber(length);
  this.writeVarNumber(type);
};

/**
 * Write value as a non-negative integer and write it to this.output just before
 * this.length from the back. Advance this.length.
 * @param {number} value The non-negative integer to encode.
 */
TlvEncoder.prototype.writeNonNegativeInteger = function(value)
{
  if (value < 0)
    throw new Error("TLV integer value may not be negative");

  // JavaScript doesn't distinguish int from float, so round.
  value = Math.round(value);

  if (value <= 0xff) {
    this.length += 1;
    this.output.ensureLengthFromBack(this.length);
    this.output.array[this.output.array.length - this.length] = value & 0xff;
  }
  else if (value <= 0xffff) {
    this.length += 2;
    this.output.ensureLengthFromBack(this.length);
    var offset = this.output.array.length - this.length;
    this.output.array[offset]     = (value >> 8) & 0xff;
    this.output.array[offset + 1] = value & 0xff;
  }
  else if (value <= 0xffffffff) {
    this.length += 4;
    this.output.ensureLengthFromBack(this.length);
    var offset = this.output.array.length - this.length;
    this.output.array[offset]     = (value >> 24) & 0xff;
    this.output.array[offset + 1] = (value >> 16) & 0xff;
    this.output.array[offset + 2] = (value >> 8) & 0xff;
    this.output.array[offset + 3] = value & 0xff;
  }
  else {
    this.length += 8;
    this.output.ensureLengthFromBack(this.length);
    var offset = this.output.array.length - this.length;
    var highBytes = Tlv.getHighBytes(value);
    this.output.array[offset]     = (highBytes >> 24) & 0xff;
    this.output.array[offset + 1] = (highBytes >> 16) & 0xff;
    this.output.array[offset + 2] = (highBytes >> 8)  & 0xff;
    this.output.array[offset + 3] = (highBytes)       & 0xff;
    this.output.array[offset + 4] = (value >> 24) & 0xff;
    this.output.array[offset + 5] = (value >> 16) & 0xff;
    this.output.array[offset + 6] = (value >> 8) & 0xff;
    this.output.array[offset + 7] = value & 0xff;
  }
};

/**
 * Write the type, then the length of the encoded value then encode value as a
 * non-negative integer and write it to this.output just before this.length from
 * the back. Advance this.length.
 * @param {number} type The type of the TLV.
 * @param {number} value The non-negative integer to encode.
 */
TlvEncoder.prototype.writeNonNegativeIntegerTlv = function(type, value)
{
  // Write backwards.
  var saveNBytes = this.length;
  this.writeNonNegativeInteger(value);
  this.writeTypeAndLength(type, this.length - saveNBytes);
};

/**
 * If value is negative or null then do nothing, otherwise call
 * writeNonNegativeIntegerTlv.
 * @param {number} type The type of the TLV.
 * @param {number} value If negative or null do nothing, otherwise the integer
 *   to encode.
 */
TlvEncoder.prototype.writeOptionalNonNegativeIntegerTlv = function(type, value)
{
  if (value != null && value >= 0)
    this.writeNonNegativeIntegerTlv(type, value);
};

/**
 * Write the buffer value to this.output just before this.length from the back.
 * Advance this.length.
 * @param {Buffer} buffer The byte array with the bytes to write.  If value is
 * null, then do nothing.
 */
TlvEncoder.prototype.writeBuffer = function(buffer)
{
  if (buffer == null)
    return;

  this.length += buffer.length;
  this.output.copyFromBack(buffer, this.length);
};

/**
 * Write the type, then the length of the buffer then the buffer value to
 * this.output just before this.length from the back. Advance this.length.
 * @param {number} type The type of the TLV.
 * @param {Buffer} value The byte array with the bytes of the blob.  If value is
    null, then just write the type and length 0.
 */
TlvEncoder.prototype.writeBlobTlv = function(type, value)
{
  if (value == null) {
    this.writeTypeAndLength(type, 0);
    return;
  }

  // Write backwards, starting with the blob array.
  this.writeBuffer(value);
  this.writeTypeAndLength(type, value.length);
};

/**
 * If the byte array is null or zero length then do nothing, otherwise call
 * writeBlobTlv.
 * @param {number} type The type of the TLV.
 * @param {Buffer} value If null or zero length do nothing, otherwise the byte
 * array with the bytes of the blob.
 */
TlvEncoder.prototype.writeOptionalBlobTlv = function(type, value)
{
  if (value != null && value.length > 0)
    this.writeBlobTlv(type, value);
};

/**
 * Get a slice of the encoded bytes.
 * @return {Buffer} A slice backed by the encoding Buffer.
 */
TlvEncoder.prototype.getOutput = function()
{
  return this.output.array.slice(this.output.array.length - this.length);
};
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var DecodingException = require('../decoding-exception.js').DecodingException;

/**
 * Create a new TlvDecoder for decoding the input in the NDN-TLV wire format.
 * @constructor
 * @param {Buffer} input The buffer with the bytes to decode.
 */
var TlvDecoder = function TlvDecoder(input)
{
  this.input = input;
  this.offset = 0;
};

exports.TlvDecoder = TlvDecoder;

/**
 * Decode VAR-NUMBER in NDN-TLV and return it. Update offset.
 * @return {number} The decoded VAR-NUMBER.
 */
TlvDecoder.prototype.readVarNumber = function()
{
  // Assume array values are in the range 0 to 255.
  var firstOctet = this.input[this.offset];
  this.offset += 1;
  if (firstOctet < 253)
    return firstOctet;
  else
    return this.readExtendedVarNumber(firstOctet);
};

/**
 * A private function to do the work of readVarNumber, given the firstOctet
 * which is >= 253.
 * @param {number} firstOctet The first octet which is >= 253, used to decode
 * the remaining bytes.
 * @return {number} The decoded VAR-NUMBER.
 */
TlvDecoder.prototype.readExtendedVarNumber = function(firstOctet)
{
  var result;
  // This is a private function so we know firstOctet >= 253.
  if (firstOctet == 253) {
    result = ((this.input[this.offset] << 8) +
           this.input[this.offset + 1]);
    this.offset += 2;
  }
  else if (firstOctet == 254) {
    // Use abs because << 24 can set the high bit of the 32-bit int making it negative.
    result = (Math.abs(this.input[this.offset] << 24) +
          (this.input[this.offset + 1] << 16) +
          (this.input[this.offset + 2] << 8) +
           this.input[this.offset + 3]);
    this.offset += 4;
  }
  else {
    // Get the high byte first because JavaScript << is restricted to 32 bits.
    // Use abs because << 24 can set the high bit of the 32-bit int making it negative.
    var highByte = Math.abs(this.input[this.offset] << 24) +
                           (this.input[this.offset + 1] << 16) +
                           (this.input[this.offset + 2] << 8) +
                            this.input[this.offset + 3];
    result = (highByte * 0x100000000 +
          (this.input[this.offset + 4] << 24) +
          (this.input[this.offset + 5] << 16) +
          (this.input[this.offset + 6] << 8) +
           this.input[this.offset + 7]);
    this.offset += 8;
  }

  return result;
};

/**
 * Decode the type and length from this's input starting at offset, expecting
 * the type to be expectedType and return the length. Update offset.  Also make
 * sure the decoded length does not exceed the number of bytes remaining in the
 * input.
 * @param {number} expectedType The expected type.
 * @return {number} The length of the TLV.
 * @throws DecodingException if (did not get the expected TLV type or the TLV length
 * exceeds the buffer length.
 */
TlvDecoder.prototype.readTypeAndLength = function(expectedType)
{
  var type = this.readVarNumber();
  if (type != expectedType)
    throw new DecodingException(new Error("Did not get the expected TLV type"));

  var length = this.readVarNumber();
  if (this.offset + length > this.input.length)
    throw new DecodingException(new Error("TLV length exceeds the buffer length"));

  return length;
};

/**
 * Decode the type and length from the input starting at offset, expecting the
 * type to be expectedType.  Update offset.  Also make sure the decoded length
 * does not exceed the number of bytes remaining in the input. Return the offset
 * of the end of this parent TLV, which is used in decoding optional nested
 * TLVs. After reading all nested TLVs, call finishNestedTlvs.
 * @param {number} expectedType The expected type.
 * @return {number} The offset of the end of the parent TLV.
 * @throws DecodingException if did not get the expected TLV type or the TLV
 * length exceeds the buffer length.
 */
TlvDecoder.prototype.readNestedTlvsStart = function(expectedType)
{
  return this.readTypeAndLength(expectedType) + this.offset;
};

/**
 * Call this after reading all nested TLVs to skip any remaining unrecognized
 * TLVs and to check if the offset after the final nested TLV matches the
 * endOffset returned by readNestedTlvsStart.
 * @param {number} endOffset The offset of the end of the parent TLV, returned
 * by readNestedTlvsStart.
 * @throws DecodingException if the TLV length does not equal the total length
 * of the nested TLVs.
 */
TlvDecoder.prototype.finishNestedTlvs = function(endOffset)
{
  // We expect offset to be endOffset, so check this first.
  if (this.offset == endOffset)
    return;

  // Skip remaining TLVs.
  while (this.offset < endOffset) {
    // Skip the type VAR-NUMBER.
    this.readVarNumber();
    // Read the length and update offset.
    var length = this.readVarNumber();
    this.offset += length;

    if (this.offset > this.input.length)
      throw new DecodingException(new Error("TLV length exceeds the buffer length"));
  }

  if (this.offset != endOffset)
    throw new DecodingException(new Error
      ("TLV length does not equal the total length of the nested TLVs"));
};

/**
 * Decode the type from this's input starting at offset, and if it is the
 * expectedType, then return true, else false.  However, if this's offset is
 * greater than or equal to endOffset, then return false and don't try to read
 * the type. Do not update offset.
 * @param {number} expectedType The expected type.
 * @param {number} endOffset The offset of the end of the parent TLV, returned
 * by readNestedTlvsStart.
 * @return {boolean} true if the type of the next TLV is the expectedType,
 *  otherwise false.
 */
TlvDecoder.prototype.peekType = function(expectedType, endOffset)
{
  if (this.offset >= endOffset)
    // No more sub TLVs to look at.
    return false;
  else {
    var saveOffset = this.offset;
    var type = this.readVarNumber();
    // Restore offset.
    this.offset = saveOffset;

    return type == expectedType;
  }
};

/**
 * Decode a non-negative integer in NDN-TLV and return it. Update offset by
 * length.
 * @param {number} length The number of bytes in the encoded integer.
 * @return {number} The integer.
 * @throws DecodingException if length is an invalid length for a TLV
 * non-negative integer.
 */
TlvDecoder.prototype.readNonNegativeInteger = function(length)
{
  var result;
  if (length == 1)
    result = this.input[this.offset];
  else if (length == 2)
    result = ((this.input[this.offset] << 8) +
           this.input[this.offset + 1]);
  else if (length == 4)
    // Use abs because << 24 can set the high bit of the 32-bit int making it negative.
    result = (Math.abs(this.input[this.offset] << 24) +
          (this.input[this.offset + 1] << 16) +
          (this.input[this.offset + 2] << 8) +
           this.input[this.offset + 3]);
  else if (length == 8) {
    // Use abs because << 24 can set the high bit of the 32-bit int making it negative.
    var highByte = Math.abs(this.input[this.offset] << 24) +
                       (this.input[this.offset + 1] << 16) +
                       (this.input[this.offset + 2] << 8) +
                        this.input[this.offset + 3];
    result = (highByte * 0x100000000 +
          Math.abs(this.input[this.offset + 4] << 24) +
          (this.input[this.offset + 5] << 16) +
          (this.input[this.offset + 6] << 8) +
           this.input[this.offset + 7]);
  }
  else
    throw new DecodingException(new Error("Invalid length for a TLV nonNegativeInteger"));

  this.offset += length;
  return result;
};

/**
 * Decode the type and length from this's input starting at offset, expecting
 * the type to be expectedType. Then decode a non-negative integer in NDN-TLV
 * and return it.  Update offset.
 * @param {number} expectedType The expected type.
 * @return {number} The integer.
 * @throws DecodingException if did not get the expected TLV type or can't
 * decode the value.
 */
TlvDecoder.prototype.readNonNegativeIntegerTlv = function(expectedType)
{
  var length = this.readTypeAndLength(expectedType);
  return this.readNonNegativeInteger(length);
};

/**
 * Peek at the next TLV, and if it has the expectedType then call
 * readNonNegativeIntegerTlv and return the integer.  Otherwise, return null.
 * However, if this's offset is greater than or equal to endOffset, then return
 * null and don't try to read the type.
 * @param {number} expectedType The expected type.
 * @param {number} endOffset The offset of the end of the parent TLV, returned
 * by readNestedTlvsStart.
 * @return {number} The integer or null if the next TLV doesn't have the
 * expected type.
 */
TlvDecoder.prototype.readOptionalNonNegativeIntegerTlv = function
  (expectedType, endOffset)
{
  if (this.peekType(expectedType, endOffset))
    return this.readNonNegativeIntegerTlv(expectedType);
  else
    return null;
};

/**
 * Decode the type and length from this's input starting at offset, expecting
 * the type to be expectedType. Then return an array of the bytes in the value.
 * Update offset.
 * @param {number} expectedType The expected type.
 * @return {Buffer} The bytes in the value as a slice on the buffer.  This is
 * not a copy of the bytes in the input buffer.  If you need a copy, then you
 * must make a copy of the return value.
 * @throws DecodingException if did not get the expected TLV type.
 */
TlvDecoder.prototype.readBlobTlv = function(expectedType)
{
  var length = this.readTypeAndLength(expectedType);
  var result = this.input.slice(this.offset, this.offset + length);

  // readTypeAndLength already checked if length exceeds the input buffer.
  this.offset += length;
  return result;
};

/**
 * Peek at the next TLV, and if it has the expectedType then call readBlobTlv
 * and return the value.  Otherwise, return null. However, if this's offset is
 * greater than or equal to endOffset, then return null and don't try to read
 * the type.
 * @param {number} expectedType The expected type.
 * @param {number} endOffset The offset of the end of the parent TLV, returned
 * by readNestedTlvsStart.
 * @return {Buffer} The bytes in the value as a slice on the buffer or null if
 * the next TLV doesn't have the expected type.  This is not a copy of the bytes
 * in the input buffer.  If you need a copy, then you must make a copy of the
 * return value.
 */
TlvDecoder.prototype.readOptionalBlobTlv = function(expectedType, endOffset)
{
  if (this.peekType(expectedType, endOffset))
    return this.readBlobTlv(expectedType);
  else
    return null;
};

/**
 * Peek at the next TLV, and if it has the expectedType then read a type and
 * value, ignoring the value, and return true. Otherwise, return false.
 * However, if this's offset is greater than or equal to endOffset, then return
 * false and don't try to read the type.
 * @param {number} expectedType The expected type.
 * @param {number} endOffset The offset of the end of the parent TLV, returned
 * by readNestedTlvsStart.
 * @return {boolean} true, or else false if the next TLV doesn't have the
 * expected type.
 */
TlvDecoder.prototype.readBooleanTlv = function(expectedType, endOffset)
{
  if (this.peekType(expectedType, endOffset)) {
    var length = this.readTypeAndLength(expectedType);
    // We expect the length to be 0, but update offset anyway.
    this.offset += length;
    return true;
  }
  else
    return false;
};

/**
 * Get the offset into the input, used for the next read.
 * @return {number} The offset.
 */
TlvDecoder.prototype.getOffset = function()
{
  return this.offset;
};

/**
 * Set the offset into the input, used for the next read.
 * @param {number} offset The new offset.
 */
TlvDecoder.prototype.seek = function(offset)
{
  this.offset = offset;
};

/**
 * Return an array of a slice of the input for the given offset range.
 * @param {number} beginOffset The offset in the input of the beginning of the
 * slice.
 * @param {number} endOffset The offset in the input of the end of the slice.
 * @return {Buffer} The bytes in the value as a slice on the buffer.  This is
 * not a copy of the bytes in the input buffer.  If you need a copy, then you
 * must make a copy of the return value.
 */
TlvDecoder.prototype.getSlice = function(beginOffset, endOffset)
{
  return this.input.slice(beginOffset, endOffset);
};
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var TlvDecoder = require('./tlv-decoder.js').TlvDecoder;

/**
 * A TlvStructureDecoder finds the end of an NDN-TLV element, even if the
 * element is supplied in parts.
 * Create and initialize a TlvStructureDecoder.
 * @constructor
 */
var TlvStructureDecoder = function TlvStructureDecoder()
{
  this.gotElementEnd_ = false;
  this.offset_ = 0;
  this.state_ = TlvStructureDecoder.READ_TYPE;
  this.headerLength_ = 0;
  this.useHeaderBuffer_ = false;
  // 8 bytes is enough to hold the extended bytes in the length encoding
  // where it is an 8-byte number.
  this.headerBuffer_ = new Buffer(8);
  this.nBytesToRead_ = 0;
};

exports.TlvStructureDecoder = TlvStructureDecoder;

TlvStructureDecoder.READ_TYPE =         0;
TlvStructureDecoder.READ_TYPE_BYTES =   1;
TlvStructureDecoder.READ_LENGTH =       2;
TlvStructureDecoder.READ_LENGTH_BYTES = 3;
TlvStructureDecoder.READ_VALUE_BYTES =  4;

/**
 * Continue scanning input starting from this.offset_ to find the element end.
 * If the end of the element which started at offset 0 is found, this returns
 * true and getOffset() is the length of the element.  Otherwise, this returns
 * false which means you should read more into input and call again.
 * @param {Buffer} input The input buffer. You have to pass in input each time
 * because the buffer could be reallocated.
 * @return {boolean} true if found the element end, false if not.
 */
TlvStructureDecoder.prototype.findElementEnd = function(input)
{
  if (this.gotElementEnd_)
    // Someone is calling when we already got the end.
    return true;

  var decoder = new TlvDecoder(input);

  while (true) {
    if (this.offset_ >= input.length)
      // All the cases assume we have some input. Return and wait for more.
      return false;

    if (this.state_ == TlvStructureDecoder.READ_TYPE) {
      var firstOctet = input[this.offset_];
      this.offset_ += 1;
      if (firstOctet < 253)
        // The value is simple, so we can skip straight to reading the length.
        this.state_ = TlvStructureDecoder.READ_LENGTH;
      else {
        // Set up to skip the type bytes.
        if (firstOctet == 253)
          this.nBytesToRead_ = 2;
        else if (firstOctet == 254)
          this.nBytesToRead_ = 4;
        else
          // value == 255.
          this.nBytesToRead_ = 8;

        this.state_ = TlvStructureDecoder.READ_TYPE_BYTES;
      }
    }
    else if (this.state_ == TlvStructureDecoder.READ_TYPE_BYTES) {
      var nRemainingBytes = input.length - this.offset_;
      if (nRemainingBytes < this.nBytesToRead_) {
        // Need more.
        this.offset_ += nRemainingBytes;
        this.nBytesToRead_ -= nRemainingBytes;
        return false;
      }

      // Got the type bytes. Move on to read the length.
      this.offset_ += this.nBytesToRead_;
      this.state_ = TlvStructureDecoder.READ_LENGTH;
    }
    else if (this.state_ == TlvStructureDecoder.READ_LENGTH) {
      var firstOctet = input[this.offset_];
      this.offset_ += 1;
      if (firstOctet < 253) {
        // The value is simple, so we can skip straight to reading
        //  the value bytes.
        this.nBytesToRead_ = firstOctet;
        if (this.nBytesToRead_ == 0) {
          // No value bytes to read. We're finished.
          this.gotElementEnd_ = true;
          return true;
        }

        this.state_ = TlvStructureDecoder.READ_VALUE_BYTES;
      }
      else {
        // We need to read the bytes in the extended encoding of
        //  the length.
        if (firstOctet == 253)
          this.nBytesToRead_ = 2;
        else if (firstOctet == 254)
          this.nBytesToRead_ = 4;
        else
          // value == 255.
          this.nBytesToRead_ = 8;

        // We need to use firstOctet in the next state.
        this.firstOctet_ = firstOctet;
        this.state_ = TlvStructureDecoder.READ_LENGTH_BYTES;
      }
    }
    else if (this.state_ == TlvStructureDecoder.READ_LENGTH_BYTES) {
      var nRemainingBytes = input.length - this.offset_;
      if (!this.useHeaderBuffer_ && nRemainingBytes >= this.nBytesToRead_) {
        // We don't have to use the headerBuffer. Set nBytesToRead.
        decoder.seek(this.offset_);

        this.nBytesToRead_ = decoder.readExtendedVarNumber(this.firstOctet_);
        // Update this.offset_ to the decoder's offset after reading.
        this.offset_ = decoder.getOffset();
      }
      else {
        this.useHeaderBuffer_ = true;

        var nNeededBytes = this.nBytesToRead_ - this.headerLength_;
        if (nNeededBytes > nRemainingBytes) {
          // We can't get all of the header bytes from this input.
          // Save in headerBuffer.
          if (this.headerLength_ + nRemainingBytes > this.headerBuffer_.length)
            // We don't expect this to happen.
            throw new Error
              ("Cannot store more header bytes than the size of headerBuffer");
          input.slice(this.offset_, this.offset_ + nRemainingBytes).copy
            (this.headerBuffer_, this.headerLength_);
          this.offset_ += nRemainingBytes;
          this.headerLength_ += nRemainingBytes;

          return false;
        }

        // Copy the remaining bytes into headerBuffer, read the
        //   length and set nBytesToRead.
        if (this.headerLength_ + nNeededBytes > this.headerBuffer_.length)
          // We don't expect this to happen.
          throw new Error
            ("Cannot store more header bytes than the size of headerBuffer");
        input.slice(this.offset_, this.offset_ + nNeededBytes).copy
          (this.headerBuffer_, this.headerLength_);
        this.offset_ += nNeededBytes;

        // Use a local decoder just for the headerBuffer.
        var bufferDecoder = new TlvDecoder(this.headerBuffer_);
        // Replace nBytesToRead with the length of the value.
        this.nBytesToRead_ = bufferDecoder.readExtendedVarNumber(this.firstOctet_);
      }

      if (this.nBytesToRead_ == 0) {
        // No value bytes to read. We're finished.
        this.gotElementEnd_ = true;
        return true;
      }

      // Get ready to read the value bytes.
      this.state_ = TlvStructureDecoder.READ_VALUE_BYTES;
    }
    else if (this.state_ == TlvStructureDecoder.READ_VALUE_BYTES) {
      var nRemainingBytes = input.length - this.offset_;
      if (nRemainingBytes < this.nBytesToRead_) {
        // Need more.
        this.offset_ += nRemainingBytes;
        this.nBytesToRead_ -= nRemainingBytes;
        return false;
      }

      // Got the bytes. We're finished.
      this.offset_ += this.nBytesToRead_;
      this.gotElementEnd_ = true;
      return true;
    }
    else
      // We don't expect this to happen.
      throw new Error("findElementEnd: unrecognized state");
  }
};

/**
 * Get the current offset into the input buffer.
 * @return {number} The offset.
 */
TlvStructureDecoder.prototype.getOffset = function()
{
  return this.offset_;
};

/**
 * Set the offset into the input, used for the next read.
 * @param {number} offset The new offset.
 */
TlvStructureDecoder.prototype.seek = function(offset)
{
  this.offset_ = offset;
};
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var TlvEncoder = require('./tlv/tlv-encoder.js').TlvEncoder; /** @ignore */
var TlvDecoder = require('./tlv/tlv-decoder.js').TlvDecoder; /** @ignore */
var Blob = require('../util/blob.js').Blob; /** @ignore */
var Name = require('../name.js').Name; /** @ignore */

/**
 * ProtobufTlv has static methods to encode and decode an Protobuf Message
 * object as NDN-TLV. The Protobuf tag value is used as the TLV type code. A
 * Protobuf message is encoded/decoded as a nested TLV encoding. Protobuf types
 * uint32, uint64 and enum are encoded/decoded as TLV nonNegativeInteger. (It is
 * an error if an enum value is negative.) Protobuf types bytes and string are
 * encoded/decoded as TLV bytes. The Protobuf type bool is encoded/decoded as a
 * TLV boolean (a zero length value for True, omitted for False). The Protobuf
 * type double is encoded/decoded as an 8-byte little-endian IEEE 754 double.
 * Other Protobuf types are an error.
 *
 * Protobuf has no "outer" message type, so you need to put your TLV message
 * inside an outer "typeless" message.
 * @constructor
 */
var ProtobufTlv = function ProtobufTlv()
{
};

exports.ProtobufTlv = ProtobufTlv;

// Load ProtoBuf.Reflect.Message.Field dynamically so that protobufjs is optional.
ProtobufTlv._Field = null;
ProtobufTlv.establishField = function()
{
  if (ProtobufTlv._Field === null) {
    try {
      // Using protobuf.min.js in the browser.
      ProtobufTlv._Field = dcodeIO.ProtoBuf.Reflect.Message.Field;
    }
    catch (ex) {
      // Using protobufjs in node.
      ProtobufTlv._Field = require("protobufjs").Reflect.Message.Field;
    }
  }
}

/**
 * Encode the Protobuf message object as NDN-TLV. This calls
 * message.encodeAB() to ensure that all required fields are present and
 * raises an exception if not. (This does not use the result of toArrayBuffer().)
 * @param {ProtoBuf.Builder.Message} message The Protobuf message object.
 * @param {ProtoBuf.Reflect.T} descriptor The reflection descriptor for the
 * message. For example, if the message is of type "MyNamespace.MyMessage" then
 * the descriptor is builder.lookup("MyNamespace.MyMessage").
 * @return {Blob} The encoded buffer in a Blob object.
 */
ProtobufTlv.encode = function(message, descriptor)
{
  ProtobufTlv.establishField();

  message.encodeAB();
  var encoder = new TlvEncoder();
  ProtobufTlv._encodeMessageValue(message, descriptor, encoder);
  return new Blob(encoder.getOutput(), false);
};

/**
 * Decode the input as NDN-TLV and update the fields of the Protobuf message
 * object.
 * @param {ProtoBuf.Builder.Message} message The Protobuf message object. This
 * does not first clear the object.
 * @param {ProtoBuf.Reflect.T} descriptor The reflection descriptor for the
 * message. For example, if the message is of type "MyNamespace.MyMessage" then
 * the descriptor is builder.lookup("MyNamespace.MyMessage").
 * @param {Blob|Buffer} input The buffer with the bytes to decode.
 */
ProtobufTlv.decode = function(message, descriptor, input)
{
  ProtobufTlv.establishField();

  // If input is a blob, get its buf().
  var decodeBuffer = typeof input === 'object' && input instanceof Blob ?
                     input.buf() : input;

  var decoder = new TlvDecoder(decodeBuffer);
  ProtobufTlv._decodeMessageValue
    (message, descriptor, decoder, decodeBuffer.length);
};

ProtobufTlv._encodeMessageValue = function(message, descriptor, encoder)
{
  var fields = descriptor.getChildren(ProtobufTlv._Field);
  // Encode the fields backwards.
  for (var iField = fields.length - 1; iField >= 0; --iField) {
    var field = fields[iField];
    var tlvType = field.id;

    var values;
    if (field.repeated)
      values = message[field.name];
    else {
      if (message[field.name] != null)
        // Make a singleton list.
        values = [message[field.name]];
      else
        continue;
    }

    // Encode the values backwards.
    for (var iValue = values.length - 1; iValue >= 0; --iValue) {
      var value = values[iValue];

      if (field.type.name == "message") {
        var saveLength =  encoder.getLength();

        // Encode backwards.
        ProtobufTlv._encodeMessageValue(value, field.resolvedType, encoder);
        encoder.writeTypeAndLength(tlvType, encoder.getLength() - saveLength);
      }
      else if (field.type.name == "uint32" ||
               field.type.name == "uint64")
        encoder.writeNonNegativeIntegerTlv(tlvType, value);
      else if (field.type.name == "enum") {
        if (value < 0)
          throw new Error("ProtobufTlv::encode: ENUM value may not be negative");
        encoder.writeNonNegativeIntegerTlv(tlvType, value);
      }
      else if (field.type.name == "bytes") {
        var buffer = value.toBuffer();
        if (buffer.length == undefined)
          // We are not running in Node.js, so assume we are using the dcodeIO
          // browser implementation based on ArrayBuffer.
          buffer = new Uint8Array(value.toArrayBuffer());
        encoder.writeBlobTlv(tlvType, buffer);
      }
      else if (field.type.name == "string")
        // Use Blob to convert.
        encoder.writeBlobTlv(tlvType, new Blob(value, false).buf());
      else if (field.type.name == "bool") {
        if (value)
          encoder.writeTypeAndLength(tlvType, 0);
      }
      else if (field.type.name == "double") {
        var encoding = new Buffer(8);
        encoding.writeDoubleLE(value, 0);
        encoder.writeBlobTlv(tlvType, encoding);
      }
      else
        throw new Error("ProtobufTlv::encode: Unknown field type");
    }
  }
};

ProtobufTlv._decodeMessageValue = function(message, descriptor, decoder, endOffset)
{
  var fields = descriptor.getChildren(ProtobufTlv._Field);
  for (var iField = 0; iField < fields.length; ++iField) {
    var field = fields[iField];
    var tlvType = field.id;

    if (!field.required && !decoder.peekType(tlvType, endOffset))
      continue;

    if (field.repeated) {
      while (decoder.peekType(tlvType, endOffset)) {
        if (field.type.name == "message") {
          var innerEndOffset = decoder.readNestedTlvsStart(tlvType);
          var value = new (field.resolvedType.build())();
          message.add(field.name, value);
          ProtobufTlv._decodeMessageValue
            (value, field.resolvedType, decoder, innerEndOffset);
          decoder.finishNestedTlvs(innerEndOffset);
        }
        else
          message.add
            (field.name,
             ProtobufTlv._decodeFieldValue(field, tlvType, decoder, endOffset));
      }
    }
    else {
      if (field.type.name == "message") {
        var innerEndOffset = decoder.readNestedTlvsStart(tlvType);
        var value = new (field.resolvedType.build())();
        message.set(field.name, value);
        ProtobufTlv._decodeMessageValue
          (value, field.resolvedType, decoder, innerEndOffset);
        decoder.finishNestedTlvs(innerEndOffset);
      }
      else
        message.set
          (field.name,
           ProtobufTlv._decodeFieldValue(field, tlvType, decoder, endOffset));
    }
  }
};

/**
 * This is a helper for _decodeMessageValue. Decode a single field and return
 * the value. Assume the field.type.name is not "message".
 */
ProtobufTlv._decodeFieldValue = function(field, tlvType, decoder, endOffset)
{
  if (field.type.name == "uint32" ||
      field.type.name == "uint64" ||
      field.type.name == "enum")
    return decoder.readNonNegativeIntegerTlv(tlvType);
  else if (field.type.name == "bytes")
    return decoder.readBlobTlv(tlvType);
  else if (field.type.name == "string")
    return decoder.readBlobTlv(tlvType).toString();
  else if (field.type.name == "bool")
    return decoder.readBooleanTlv(tlvType, endOffset);
  else if (field.type.name == "double")
    return decoder.readBlobTlv(tlvType).readDoubleLE(0);
  else
    throw new Error("ProtobufTlv.decode: Unknown field type");
};

/**
 * Return a Name made from the component array in a Protobuf message object,
 * assuming that it was defined with "repeated bytes". For example:
 * message Name {
 *   repeated bytes component = 8;
 * }
 * @param {Array} componentArray The array from the Protobuf message object
 * representing the "repeated bytes" component array.
 * @return A new Name.
 */
ProtobufTlv.toName = function(componentArray)
{
  var name = new Name();
  for (var i = 0; i < componentArray.length; ++i)
    name.append
      (new Blob(new Buffer(componentArray[i].toBinary(), "binary")), false);

  return name;
};
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * @author: From code in ndn-cxx by Yingdi Yu <yingdi@cs.ucla.edu>
 *
 * 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.
 */

/**
 * @constructor
 */
var OID = function OID(oid)
{
  if (typeof oid === 'string') {
    var splitString = oid.split(".");
    this.oid = [];
    for (var i = 0; i < splitString.length; ++i)
      this.oid.push(parseInt(splitString[i]));
  }
  else
    // Assume oid is an array of int.  Make a copy.
    this.oid = oid.slice(0, oid.length);
};

exports.OID = OID;

OID.prototype.getIntegerList = function()
{
  return this.oid;
};

OID.prototype.setIntegerList = function(oid)
{
  // Make a copy.
  this.oid = oid.slice(0, oid.length);
};

OID.prototype.toString = function()
{
  var result = "";
  for (var i = 0; i < this.oid.length; ++i) {
    if (i !== 0)
      result += ".";
    result += this.oid[i];
  }

  return result;
};

OID.prototype.equals = function(other)
{
  if (!(other instanceof OID))
    return false;
  if (this.oid.length !== other.oid.length)
    return false;

  for (var i = 0; i < this.oid.length; ++i) {
    if (this.oid[i] != other.oid[i])
      return false;
  }
  return true;
};
/**
 * Copyright (C) 2013-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/**
 * Create a WireFormat base class where the encode and decode methods throw an error. You should use a derived class like TlvWireFormat.
 * @constructor
 */
var WireFormat = function WireFormat() {
};

exports.WireFormat = WireFormat;

/**
 * Encode name and return the encoding.  Your derived class should override.
 * @param {Name} name The Name to encode.
 * @return {Blob} A Blob containing the encoding.
 * @throws Error This always throws an "unimplemented" error. The derived class should override.
 */
WireFormat.prototype.encodeName = function(name)
{
  throw new Error("encodeName is unimplemented in the base WireFormat class.  You should use a derived class.");
};

/**
 * Decode input as a name and set the fields of the Name object.
 * Your derived class should override.
 * @param {Name} name The Name object whose fields are updated.
 * @param {Buffer} input The buffer with the bytes to decode.
 * @param {boolean} copy (optional) If true, copy from the input when making new
 * Blob values. If false, then Blob values share memory with the input, which
 * must remain unchanged while the Blob values are used. If omitted, use true.
 * @throws Error This always throws an "unimplemented" error. The derived class should override.
 */
WireFormat.prototype.decodeName = function(name, input, copy)
{
  throw new Error("decodeName is unimplemented in the base WireFormat class.  You should use a derived class.");
};

/**
 * Encode interest and return the encoding.  Your derived class should override.
 * @param {Interest} interest The Interest to encode.
 * @return {object} An associative array with fields
 * (encoding, signedPortionBeginOffset, signedPortionEndOffset) where encoding
 * is a Blob containing the encoding, signedPortionBeginOffset is the offset in
 * the encoding of the beginning of the signed portion, and
 * signedPortionEndOffset is the offset in the encoding of the end of the signed
 * portion. The signed portion starts from the first name component and ends
 * just before the final name component (which is assumed to be a signature for
 * a signed interest).
 * @throws Error This always throws an "unimplemented" error. The derived class should override.
 */
WireFormat.prototype.encodeInterest = function(interest)
{
  throw new Error("encodeInterest is unimplemented in the base WireFormat class.  You should use a derived class.");
};

/**
 * Decode input as an interest and set the fields of the interest object.
 * Your derived class should override.
 * @param {Interest} interest The Interest object whose fields are updated.
 * @param {Buffer} input The buffer with the bytes to decode.
 * @param {boolean} copy (optional) If true, copy from the input when making new
 * Blob values. If false, then Blob values share memory with the input, which
 * must remain unchanged while the Blob values are used. If omitted, use true.
 * @return {object} An associative array with fields
 * (signedPortionBeginOffset, signedPortionEndOffset) where
 * signedPortionBeginOffset is the offset in the encoding of the beginning of
 * the signed portion, and signedPortionEndOffset is the offset in the encoding
 * of the end of the signed portion. The signed portion starts from the first
 * name component and ends just before the final name component (which is
 * assumed to be a signature for a signed interest).
 * @throws Error This always throws an "unimplemented" error. The derived class should override.
 */
WireFormat.prototype.decodeInterest = function(interest, input, copy)
{
  throw new Error("decodeInterest is unimplemented in the base WireFormat class.  You should use a derived class.");
};

/**
 * Encode data and return the encoding and signed offsets. Your derived class
 * should override.
 * @param {Data} data The Data object to encode.
 * @return {object} An associative array with fields
 * (encoding, signedPortionBeginOffset, signedPortionEndOffset) where encoding
 * is a Blob containing the encoding, signedPortionBeginOffset is the offset in
 * the encoding of the beginning of the signed portion, and
 * signedPortionEndOffset is the offset in the encoding of the end of the
 * signed portion.
 * @throws Error This always throws an "unimplemented" error. The derived class should override.
 */
WireFormat.prototype.encodeData = function(data)
{
  throw new Error("encodeData is unimplemented in the base WireFormat class.  You should use a derived class.");
};

/**
 * Decode input as a data packet, set the fields in the data object, and return
 * the signed offsets.  Your derived class should override.
 * @param {Data} data The Data object whose fields are updated.
 * @param {Buffer} input The buffer with the bytes to decode.
 * @param {boolean} copy (optional) If true, copy from the input when making new
 * Blob values. If false, then Blob values share memory with the input, which
 * must remain unchanged while the Blob values are used. If omitted, use true.
 * @return {object} An associative array with fields
 * (signedPortionBeginOffset, signedPortionEndOffset) where
 * signedPortionBeginOffset is the offset in the encoding of the beginning of
 * the signed portion, and signedPortionEndOffset is the offset in the encoding
 * of the end of the signed portion.
 * @throws Error This always throws an "unimplemented" error. The derived class should override.
 */
WireFormat.prototype.decodeData = function(data, input, copy)
{
  throw new Error("decodeData is unimplemented in the base WireFormat class.  You should use a derived class.");
};

/**
 * Encode controlParameters and return the encoding.  Your derived class should
 * override.
 * @param {ControlParameters} controlParameters The ControlParameters object to
 * encode.
 * @return {Blob} A Blob containing the encoding.
 * @throws Error This always throws an "unimplemented" error. The derived class should override.
 */
WireFormat.prototype.encodeControlParameters = function(controlParameters)
{
  throw new Error("encodeControlParameters is unimplemented in the base WireFormat class.  You should use a derived class.");
};

/**
 * Decode input as a controlParameters and set the fields of the
 * controlParameters object. Your derived class should override.
 * @param {ControlParameters} controlParameters The ControlParameters object
 * whose fields are updated.
 * @param {Buffer} input The buffer with the bytes to decode.
 * @param {boolean} copy (optional) If true, copy from the input when making new
 * Blob values. If false, then Blob values share memory with the input, which
 * must remain unchanged while the Blob values are used. If omitted, use true.
 * @throws Error This always throws an "unimplemented" error. The derived class should override.
 */
WireFormat.prototype.decodeControlParameters = function
  (controlParameters, input, copy)
{
  throw new Error("decodeControlParameters is unimplemented in the base WireFormat class.  You should use a derived class.");
};

/**
 * Encode controlResponse and return the encoding.  Your derived class should
 * override.
 * @param {ControlResponse} controlResponse The ControlResponse object to
 * encode.
 * @return {Blob} A Blob containing the encoding.
 * @throws Error This always throws an "unimplemented" error. The derived class should override.
 */
WireFormat.prototype.encodeControlResponse = function(controlResponse)
{
  throw new Error("encodeControlResponse is unimplemented in the base WireFormat class.  You should use a derived class.");
};

/**
 * Decode input as a controlResponse and set the fields of the
 * controlResponse object. Your derived class should override.
 * @param {ControlResponse} controlResponse The ControlResponse object
 * whose fields are updated.
 * @param {Buffer} input The buffer with the bytes to decode.
 * @param {boolean} copy (optional) If true, copy from the input when making new
 * Blob values. If false, then Blob values share memory with the input, which
 * must remain unchanged while the Blob values are used. If omitted, use true.
 * @throws Error This always throws an "unimplemented" error. The derived class should override.
 */
WireFormat.prototype.decodeControlResponse = function
  (controlResponse, input, copy)
{
  throw new Error("decodeControlResponse is unimplemented in the base WireFormat class.  You should use a derived class.");
};

/**
 * Encode signature as a SignatureInfo and return the encoding. Your derived
 * class should override.
 * @param {Signature} signature An object of a subclass of Signature to encode.
 * @return {Blob} A Blob containing the encoding.
 * @throws Error This always throws an "unimplemented" error. The derived class should override.
 */
WireFormat.prototype.encodeSignatureInfo = function(signature)
{
  throw new Error("encodeSignatureInfo is unimplemented in the base WireFormat class.  You should use a derived class.");
};

/**
 * Decode signatureInfo as a signature info and signatureValue as the related
 * SignatureValue, and return a new object which is a subclass of Signature.
 * Your derived class should override.
 * @param {Buffer} signatureInfo The buffer with the signature info bytes to
 * decode.
 * @param {Buffer} signatureValue The buffer with the signature value to decode.
 * @param {boolean} copy (optional) If true, copy from the input when making new
 * Blob values. If false, then Blob values share memory with the input, which
 * must remain unchanged while the Blob values are used. If omitted, use true.
 * @return {Signature} A new object which is a subclass of Signature.
 * @throws Error This always throws an "unimplemented" error. The derived class should override.
 */
WireFormat.prototype.decodeSignatureInfoAndValue = function
  (signatureInfo, signatureValue, copy)
{
  throw new Error("decodeSignatureInfoAndValue is unimplemented in the base WireFormat class.  You should use a derived class.");
};

/**
 * Encode the signatureValue in the Signature object as a SignatureValue (the
 * signature bits) and return the encoding. Your derived class should override.
 * @param {Signature} signature An object of a subclass of Signature with the
 * signature value to encode.
 * @return {Blob} A Blob containing the encoding.
 * @throws Error This always throws an "unimplemented" error. The derived class should override.
 */
WireFormat.prototype.encodeSignatureValue = function(signature)
{
  throw new Error("encodeSignatureValue is unimplemented in the base WireFormat class.  You should use a derived class.");
};

/**
 * Decode input as an NDN-TLV LpPacket and set the fields of the lpPacket object.
 * Your derived class should override.
 * @param {LpPacket} lpPacket The LpPacket object whose fields are updated.
 * @param {Buffer} input The buffer with the bytes to decode.
 * @param {boolean} copy (optional) If true, copy from the input when making new
 * Blob values. If false, then Blob values share memory with the input, which
 * must remain unchanged while the Blob values are used. If omitted, use true.
 * @throws Error This always throws an "unimplemented" error. The derived class
 * should override.
 */
WireFormat.prototype.decodeLpPacket = function(lpPacket, input, copy)
{
  throw new Error
    ("decodeLpPacket is unimplemented in the base WireFormat class. You should use a derived class.");
};

/**
 * Encode the DelegationSet and return the encoding.  Your derived class
 * should override.
 * @param {DelegationSet} delegationSet The DelegationSet object to
 * encode.
 * @return {Blob} A Blob containing the encoding.
 * @throws Error This always throws an "unimplemented" error. The derived class
 * should override.
 */
WireFormat.prototype.encodeDelegationSet = function(delegationSet)
{
  throw new Error
    ("encodeDelegationSet is unimplemented in the base WireFormat class. You should use a derived class.");
};

/**
 * Decode input as an DelegationSet and set the fields of the
 * delegationSet object. Your derived class should override.
 * @param {DelegationSet} delegationSet The DelegationSet object
 * whose fields are updated.
 * @param {Buffer} input The buffer with the bytes to decode.
 * @param {boolean} copy (optional) If true, copy from the input when making new
 * Blob values. If false, then Blob values share memory with the input, which
 * must remain unchanged while the Blob values are used. If omitted, use true.
 * @throws Error This always throws an "unimplemented" error. The derived class
 * should override.
 */
WireFormat.prototype.decodeDelegationSet = function(delegationSet, input, copy)
{
  throw new Error
    ("decodeDelegationSet is unimplemented in the base WireFormat class. You should use a derived class.");
};

/**
 * Encode the EncryptedContent and return the encoding.  Your derived class
 * should override.
 * @param {EncryptedContent} encryptedContent The EncryptedContent object to
 * encode.
 * @return {Blob} A Blob containing the encoding.
 * @throws Error This always throws an "unimplemented" error. The derived class
 * should override.
 */
WireFormat.prototype.encodeEncryptedContent = function(encryptedContent)
{
  throw new Error
    ("encodeEncryptedContent is unimplemented in the base WireFormat class. You should use a derived class.");
};

/**
 * Decode input as an EncryptedContent and set the fields of the
 * encryptedContent object. Your derived class should override.
 * @param {EncryptedContent} encryptedContent The EncryptedContent object
 * whose fields are updated.
 * @param {Buffer} input The buffer with the bytes to decode.
 * @param {boolean} copy (optional) If true, copy from the input when making new
 * Blob values. If false, then Blob values share memory with the input, which
 * must remain unchanged while the Blob values are used. If omitted, use true.
 * @throws Error This always throws an "unimplemented" error. The derived class
 * should override.
 */
WireFormat.prototype.decodeEncryptedContent = function
  (encryptedContent, input, copy)
{
  throw new Error
    ("decodeEncryptedContent is unimplemented in the base WireFormat class. You should use a derived class.");
};

/**
 * Set the static default WireFormat used by default encoding and decoding
 * methods.
 * @param {WireFormat} wireFormat An object of a subclass of WireFormat.
 */
WireFormat.setDefaultWireFormat = function(wireFormat)
{
  WireFormat.defaultWireFormat = wireFormat;
};

/**
 * Return the default WireFormat used by default encoding and decoding methods
 * which was set with setDefaultWireFormat.
 * @return {WireFormat} An object of a subclass of WireFormat.
 */
WireFormat.getDefaultWireFormat = function()
{
  return WireFormat.defaultWireFormat;
};

// Invoke TlvWireFormat to set the default format.
// Since tlv-wire-format.js includes this file, put this at the bottom
// to avoid problems with cycles of require.
var TlvWireFormat = require('./tlv-wire-format.js').TlvWireFormat;
/**
 * Copyright (C) 2013-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var DataUtils = require('./data-utils.js').DataUtils; /** @ignore */
var Tlv = require('./tlv/tlv.js').Tlv; /** @ignore */
var TlvStructureDecoder = require('./tlv/tlv-structure-decoder.js').TlvStructureDecoder; /** @ignore */
var DecodingException = require('./decoding-exception.js').DecodingException; /** @ignore */
var NdnCommon = require('../util/ndn-common.js').NdnCommon; /** @ignore */
var LOG = require('../log.js').Log.LOG;

/**
 * A ElementReader lets you call onReceivedData multiple times which uses a
 * TlvStructureDecoder to detect the end of a TLV element and calls
 * elementListener.onReceivedElement(element) with the element.  This handles
 * the case where a single call to onReceivedData may contain multiple elements.
 * @constructor
 * @param {object} elementListener An object with an onReceivedElement method.
 */
var ElementReader = function ElementReader(elementListener)
{
  this.elementListener_ = elementListener;
  this.dataParts_ = [];
  this.tlvStructureDecoder_ = new TlvStructureDecoder();
};

exports.ElementReader = ElementReader;

/**
 * Continue to read data until the end of an element, then call
 * this.elementListener_.onReceivedElement(element). The buffer passed to
 * onReceivedElement is only valid during this call.  If you need the data
 * later, you must copy.
 * @param {Buffer} data The Buffer with the incoming element's bytes.
 */
ElementReader.prototype.onReceivedData = function(data)
{
  // Process multiple elements in the data.
  while (true) {
    var gotElementEnd;
    var offset;

    try {
      if (this.dataParts_.length === 0) {
        // This is the beginning of an element.
        if (data.length <= 0)
          // Wait for more data.
          return;
      }

      // Scan the input to check if a whole TLV element has been read.
      this.tlvStructureDecoder_.seek(0);
      gotElementEnd = this.tlvStructureDecoder_.findElementEnd(data);
      offset = this.tlvStructureDecoder_.getOffset();
    } catch (ex) {
      // Reset to read a new element on the next call.
      this.dataParts_ = [];
      this.tlvStructureDecoder_ = new TlvStructureDecoder();

      throw ex;
    }

    if (gotElementEnd) {
      // Got the remainder of an element.  Report to the caller.
      var element;
      if (this.dataParts_.length === 0)
        element = data.slice(0, offset);
      else {
        this.dataParts_.push(data.slice(0, offset));
        element = DataUtils.concatArrays(this.dataParts_);
        this.dataParts_ = [];
      }

      // Reset to read a new element. Do this before calling onReceivedElement
      // in case it throws an exception.
      data = data.slice(offset, data.length);
      this.tlvStructureDecoder_ = new TlvStructureDecoder();

      this.elementListener_.onReceivedElement(element);
      if (data.length == 0)
        // No more data in the packet.
        return;

      // else loop back to decode.
    }
    else {
      // Save a copy. We will call concatArrays later.
      var totalLength = data.length;
      for (var i = 0; i < this.dataParts_.length; ++i)
        totalLength += this.dataParts_[i].length;
      if (totalLength > NdnCommon.MAX_NDN_PACKET_SIZE) {
        // Reset to read a new element on the next call.
        this.dataParts_ = [];
        this.tlvStructureDecoder_ = new TlvStructureDecoder();

        throw new DecodingException(new Error
          ("The incoming packet exceeds the maximum limit Face.getMaxNdnPacketSize()"));
      }

      this.dataParts_.push(new Buffer(data));
      if (LOG > 3) console.log('Incomplete packet received. Length ' + data.length + '. Wait for more input.');
      return;
    }
  }
};
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/**
 * Create a new DerDecodingException wrapping the given error object.
 * Call with: throw new DerDecodingException(new Error("message")).
 * @constructor
 * @param {Error} error The exception created with new Error.
 */
function DerDecodingException(error)
{
  if (error) {
    error.__proto__ = DerDecodingException.prototype;
    return error;
  }
}
DerDecodingException.prototype = new Error();
DerDecodingException.prototype.name = "DerDecodingException";

exports.DerDecodingException = DerDecodingException;
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/**
 * Create a new DerEncodingException wrapping the given error object.
 * Call with: throw new DerEncodingException(new Error("message")).
 * @constructor
 * @param {Error} error The exception created with new Error.
 */
function DerEncodingException(error)
{
  if (error) {
    error.__proto__ = DerEncodingException.prototype;
    return error;
  }
}
DerEncodingException.prototype = new Error();
DerEncodingException.prototype.name = "DerEncodingException";

exports.DerEncodingException = DerEncodingException;
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * @author: From PyNDN der.py by Adeola Bannis <thecodemaiden@gmail.com>.
 * @author: Originally from code in ndn-cxx by Yingdi Yu <yingdi@cs.ucla.edu>
 *
 * 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.
 */

/**
 * The DerNodeType enum defines the known DER node types.
 */
var DerNodeType = function DerNodeType()
{
}

exports.DerNodeType = DerNodeType;

DerNodeType.Eoc = 0;
DerNodeType.Boolean = 1;
DerNodeType.Integer = 2;
DerNodeType.BitString = 3;
DerNodeType.OctetString = 4;
DerNodeType.Null = 5;
DerNodeType.ObjectIdentifier = 6;
DerNodeType.ObjectDescriptor = 7;
DerNodeType.External = 40;
DerNodeType.Real = 9;
DerNodeType.Enumerated = 10;
DerNodeType.EmbeddedPdv = 43;
DerNodeType.Utf8String = 12;
DerNodeType.RelativeOid = 13;
DerNodeType.Sequence = 48;
DerNodeType.Set = 49;
DerNodeType.NumericString = 18;
DerNodeType.PrintableString = 19;
DerNodeType.T61String = 20;
DerNodeType.VideoTexString = 21;
DerNodeType.Ia5String = 22;
DerNodeType.UtcTime = 23;
DerNodeType.GeneralizedTime = 24;
DerNodeType.GraphicString = 25;
DerNodeType.VisibleString = 26;
DerNodeType.GeneralString = 27;
DerNodeType.UniversalString = 28;
DerNodeType.CharacterString = 29;
DerNodeType.BmpString = 30;
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * @author: From PyNDN der_node.py by Adeola Bannis <thecodemaiden@gmail.com>.
 * @author: Originally from code in ndn-cxx by Yingdi Yu <yingdi@cs.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var DynamicBuffer = require('../../util/dynamic-buffer.js').DynamicBuffer; /** @ignore */
var Blob = require('../../util/blob.js').Blob; /** @ignore */
var DerDecodingException = require('./der-decoding-exception.js').DerDecodingException; /** @ignore */
var DerEncodingException = require('./der-encoding-exception.js').DerEncodingException; /** @ignore */
var DerNodeType = require('./der-node-type.js').DerNodeType;

/**
 * DerNode implements the DER node types used in encoding/decoding DER-formatted
 * data.
 *
 * Create a generic DER node with the given nodeType. This is a private
 * constructor used by one of the public DerNode subclasses defined below.
 * @param {number} nodeType One of the defined DER DerNodeType constants.
 * @constructor
 */
var DerNode = function DerNode(nodeType)
{
  this.nodeType_ = nodeType;
  this.parent_ = null;
  this.header_ = new Buffer(0);
  this.payload_ = new DynamicBuffer(0);
  this.payloadPosition_ = 0;
};

exports.DerNode = DerNode;

/**
 * Return the number of bytes in DER
 * @return {number}
 */
DerNode.prototype.getSize = function()
{
  return this.header_.length + this.payloadPosition_;
};

/**
 * Encode the given size and update the header.
 * @param {number} size
 */
DerNode.prototype.encodeHeader = function(size)
{
  var buffer = new DynamicBuffer(10);
  var bufferPosition = 0;
  buffer.array[bufferPosition++] = this.nodeType_;
  if (size < 0)
    // We don't expect this to happen since this is an internal method and
    // always called with the non-negative size() of some buffer.
    throw new Error("encodeHeader: DER object has negative length");
  else if (size <= 127)
    buffer.array[bufferPosition++] = size & 0xff;
  else {
    var tempBuf = new DynamicBuffer(10);
    // We encode backwards from the back.

    var val = size;
    var n = 0;
    while (val != 0) {
      ++n;
      tempBuf.ensureLengthFromBack(n);
      tempBuf.array[tempBuf.array.length - n] = val & 0xff;
      val >>= 8;
    }
    var nTempBufBytes = n + 1;
    tempBuf.ensureLengthFromBack(nTempBufBytes);
    tempBuf.array[tempBuf.array.length - nTempBufBytes] = ((1<<7) | n) & 0xff;

    buffer.copy(tempBuf.slice(tempBuf.array.length - nTempBufBytes), bufferPosition);
    bufferPosition += nTempBufBytes;
  }

  this.header_ = buffer.slice(0, bufferPosition);
};

/**
 * Extract the header from an input buffer and return the size.
 * @param {Buffer} inputBuf The input buffer to read from.
 * @param {number} startIdx The offset into the buffer.
 * @return {number} The parsed size in the header.
 */
DerNode.prototype.decodeHeader = function(inputBuf, startIdx)
{
  var idx = startIdx;

  var nodeType = inputBuf[idx] & 0xff;
  idx += 1;

  this.nodeType_ = nodeType;

  var sizeLen = inputBuf[idx] & 0xff;
  idx += 1;

  var header = new DynamicBuffer(10);
  var headerPosition = 0;
  header.array[headerPosition++] = nodeType;
  header.array[headerPosition++] = sizeLen;

  var size = sizeLen;
  var isLongFormat = (sizeLen & (1 << 7)) != 0;
  if (isLongFormat) {
    var lenCount = sizeLen & ((1<<7) - 1);
    size = 0;
    while (lenCount > 0) {
      var b = inputBuf[idx];
      idx += 1;
      header.ensureLength(headerPosition + 1);
      header.array[headerPosition++] = b;
      size = 256 * size + (b & 0xff);
      lenCount -= 1;
    }
  }

  this.header_ = header.slice(0, headerPosition);
  return size;
};

/**
 * Get the raw data encoding for this node.
 * @return {Blob} The raw data encoding.
 */
DerNode.prototype.encode = function()
{
  var buffer = new Buffer(this.getSize());

  this.header_.copy(buffer);
  this.payload_.slice(0, this.payloadPosition_).copy(buffer, this.header_.length);

  return new Blob(buffer, false);
};

/**
 * Decode and store the data from an input buffer.
 * @param {Buffer} inputBuf The input buffer to read from. This reads from
 * startIdx (regardless of the buffer's position) and does not change the
 * position.
 * @param {number} startIdx The offset into the buffer.
 */
DerNode.prototype.decode = function(inputBuf, startIdx)
{
  var idx = startIdx;
  var payloadSize = this.decodeHeader(inputBuf, idx);
  var skipBytes = this.header_.length;
  if (payloadSize > 0) {
    idx += skipBytes;
    this.payloadAppend(inputBuf.slice(idx, idx + payloadSize));
  }
};

/**
 * Copy buffer to this.payload_ at this.payloadPosition_ and update
 * this.payloadPosition_.
 * @param {Buffer} buffer The buffer to copy.
 */
DerNode.prototype.payloadAppend = function(buffer)
{
  this.payloadPosition_ = this.payload_.copy(buffer, this.payloadPosition_);
}

/**
 * Parse the data from the input buffer recursively and return the root as an
 * object of a subclass of DerNode.
 * @param {Buffer} inputBuf The input buffer to read from.
 * @param {number} startIdx (optional) The offset into the buffer. If omitted,
 * use 0.
 * @return {DerNode} An object of a subclass of DerNode.
 */
DerNode.parse = function(inputBuf, startIdx)
{
  if (startIdx == undefined)
    startIdx = 0;

  var nodeType = inputBuf[startIdx] & 0xff;
  // Don't increment idx. We're just peeking.

  var newNode;
  if (nodeType === DerNodeType.Boolean)
    newNode = new DerNode.DerBoolean();
  else if (nodeType === DerNodeType.Integer)
    newNode = new DerNode.DerInteger();
  else if (nodeType === DerNodeType.BitString)
    newNode = new DerNode.DerBitString();
  else if (nodeType === DerNodeType.OctetString)
    newNode = new DerNode.DerOctetString();
  else if (nodeType === DerNodeType.Null)
    newNode = new DerNode.DerNull();
  else if (nodeType === DerNodeType.ObjectIdentifier)
    newNode = new DerNode.DerOid();
  else if (nodeType === DerNodeType.Sequence)
    newNode = new DerNode.DerSequence();
  else if (nodeType === DerNodeType.PrintableString)
    newNode = new DerNode.DerPrintableString();
  else if (nodeType === DerNodeType.GeneralizedTime)
    newNode = new DerNode.DerGeneralizedTime();
  else
    throw new DerDecodingException(new Error("Unimplemented DER type " + nodeType));

  newNode.decode(inputBuf, startIdx);
  return newNode;
};

/**
 * Convert the encoded data to a standard representation. Overridden by some
 * subclasses (e.g. DerBoolean).
 * @return {Blob} The encoded data as a Blob.
 */
DerNode.prototype.toVal = function()
{
  return this.encode();
};

/**
 * Get a copy of the payload bytes.
 * @return {Blob} A copy of the payload.
 */
DerNode.prototype.getPayload = function()
{
  return new Blob(this.payload_.slice(0, this.payloadPosition_), true);
};

/**
 * If this object is a DerNode.DerSequence, get the children of this node.
 * Otherwise, throw an exception. (DerSequence overrides to implement this
 * method.)
 * @return {Array<DerNode>} The children as an array of DerNode.
 * @throws DerDecodingException if this object is not a DerSequence.
 */
DerNode.prototype.getChildren = function()
{
  throw new DerDecodingException(new Error
    ("getChildren: This DerNode is not DerSequence"));
};

/**
 * Check that index is in bounds for the children list, return children[index].
 * @param {Array<DerNode>} children The list of DerNode, usually returned by
 * another call to getChildren.
 * @param {number} index The index of the children.
 * @return {DerNode.DerSequence} children[index].
 * @throws DerDecodingException if index is out of bounds or if children[index]
 * is not a DerSequence.
 */
DerNode.getSequence = function(children, index)
{
  if (index < 0 || index >= children.length)
    throw new DerDecodingException(new Error
      ("getSequence: Child index is out of bounds"));

  if (!(children[index] instanceof DerNode.DerSequence))
    throw new DerDecodingException(new Error
      ("getSequence: Child DerNode is not a DerSequence"));

  return children[index];
};

/**
 * A DerStructure extends DerNode to hold other DerNodes.
 * Create a DerStructure with the given nodeType. This is a private
 * constructor. To create an object, use DerSequence.
 * @param {number} nodeType One of the defined DER DerNodeType constants.
 */
DerNode.DerStructure = function DerStructure(nodeType)
{
  // Call the base constructor.
  DerNode.call(this, nodeType);

  this.childChanged_ = false;
  this.nodeList_ = []; // Of DerNode.
  this.size_ = 0;
};
DerNode.DerStructure.prototype = new DerNode();
DerNode.DerStructure.prototype.name = "DerStructure";

/**
 * Get the total length of the encoding, including children.
 * @return {number} The total (header + payload) length.
 */
DerNode.DerStructure.prototype.getSize = function()
{
  if (this.childChanged_) {
    this.updateSize();
    this.childChanged_ = false;
  }

  this.encodeHeader(this.size_);
  return this.size_ + this.header_.length;
};

/**
 * Get the children of this node.
 * @return {Array<DerNode>} The children as an array of DerNode.
 */
DerNode.DerStructure.prototype.getChildren = function()
{
  return this.nodeList_;
};

DerNode.DerStructure.prototype.updateSize = function()
{
  var newSize = 0;

  for (var i = 0; i < this.nodeList_.length; ++i) {
    var n = this.nodeList_[i];
    newSize += n.getSize();
  }

  this.size_ = newSize;
  this.childChanged_ = false;
};

/**
 * Add a child to this node.
 * @param {DerNode} node The child node to add.
 * @param {boolean} (optional) notifyParent Set to true to cause any containing
 * nodes to update their size.  If omitted, use false.
 */
DerNode.DerStructure.prototype.addChild = function(node, notifyParent)
{
  node.parent_ = this;
  this.nodeList_.push(node);

  if (notifyParent) {
    if (this.parent_ != null)
      this.parent_.setChildChanged();
  }

  this.childChanged_ = true;
};

/**
 * Mark the child list as dirty, so that we update size when necessary.
 */
DerNode.DerStructure.prototype.setChildChanged = function()
{
  if (this.parent_ != null)
    this.parent_.setChildChanged();
  this.childChanged_ = true;
};

/**
 * Override the base encode to return raw data encoding for this node and its
 * children.
 * @return {Blob} The raw data encoding.
 */
DerNode.DerStructure.prototype.encode = function()
{
  var buffer = new DynamicBuffer(10);
  var bufferPosition = 0;
  this.updateSize();
  this.encodeHeader(this.size_);
  bufferPosition = buffer.copy(this.header_, bufferPosition);

  for (var i = 0; i < this.nodeList_.length; ++i) {
    var n = this.nodeList_[i];
    var encodedChild = n.encode();
    bufferPosition = buffer.copy(encodedChild.buf(), bufferPosition);
  }

  return new Blob(buffer.slice(0, bufferPosition), false);
};

/**
 * Override the base decode to decode and store the data from an input
 * buffer. Recursively populates child nodes.
 * @param {Buffer} inputBuf The input buffer to read from.
 * @param {number} startIdx The offset into the buffer.
 */
DerNode.DerStructure.prototype.decode = function(inputBuf, startIdx)
{
  var idx = startIdx;
  this.size_ = this.decodeHeader(inputBuf, idx);
  idx += this.header_.length;

  var accSize = 0;
  while (accSize < this.size_) {
    var node = DerNode.parse(inputBuf, idx);
    var size = node.getSize();
    idx += size;
    accSize += size;
    this.addChild(node, false);
  }
};

////////
// Now for all the node types...
////////

/**
 * A DerByteString extends DerNode to handle byte strings.
 * Create a DerByteString with the given inputData and nodeType. This is a
 * private constructor used by one of the public subclasses such as
 * DerOctetString or DerPrintableString.
 * @param {Buffer} inputData An input buffer containing the string to encode.
 * @param {number} nodeType One of the defined DER DerNodeType constants.
 */
DerNode.DerByteString = function DerByteString(inputData, nodeType)
{
  // Call the base constructor.
  DerNode.call(this, nodeType);

  if (inputData != null) {
    this.payloadAppend(inputData);
    this.encodeHeader(inputData.length);
  }
};
DerNode.DerByteString.prototype = new DerNode();
DerNode.DerByteString.prototype.name = "DerByteString";

/**
 * Override to return just the byte string.
 * @return {Blob} The byte string as a copy of the payload buffer.
 */
DerNode.DerByteString.prototype.toVal = function()
{
  return this.getPayload();
};

/**
 * DerBoolean extends DerNode to encode a boolean value.
 * Create a new DerBoolean for the value.
 * @param {boolean} value The value to encode.
 */
DerNode.DerBoolean = function DerBoolean(value)
{
  // Call the base constructor.
  DerNode.call(this, DerNodeType.Boolean);

  if (value != undefined) {
    var val = value ? 0xff : 0x00;
    this.payload_.ensureLength(this.payloadPosition_ + 1);
    this.payload_.array[this.payloadPosition_++] = val;
    this.encodeHeader(1);
  }
};
DerNode.DerBoolean.prototype = new DerNode();
DerNode.DerBoolean.prototype.name = "DerBoolean";

DerNode.DerBoolean.prototype.toVal = function()
{
  var val = this.payload_.array[0];
  return val != 0x00;
};

/**
 * DerInteger extends DerNode to encode an integer value.
 * Create a new DerInteger for the value.
 * @param {number|Buffer} integer The value to encode. If integer is a Buffer
 * byte array of a positive integer, you must ensure that the first byte is less
 * than 0x80.
 */
DerNode.DerInteger = function DerInteger(integer)
{
  // Call the base constructor.
  DerNode.call(this, DerNodeType.Integer);

  if (integer != undefined) {
    if (Buffer.isBuffer(integer)) {
      if (integer.length > 0 && integer[0] >= 0x80)
        throw new DerEncodingException(new Error
          ("DerInteger: Negative integers are not currently supported"));

      if (integer.length == 0)
        this.payloadAppend(new Buffer([0]));
      else
        this.payloadAppend(integer);
    }
    else {
      // JavaScript doesn't distinguish int from float, so round.
      integer = Math.round(integer);

      if (integer < 0)
        throw new DerEncodingException(new Error
          ("DerInteger: Negative integers are not currently supported"));

      // Convert the integer to bytes the easy/slow way.
      var temp = new DynamicBuffer(10);
      // We encode backwards from the back.
      var length = 0;
      while (true) {
        ++length;
        temp.ensureLengthFromBack(length);
        temp.array[temp.array.length - length] = integer & 0xff;
        integer >>= 8;

        if (integer <= 0)
          // We check for 0 at the end so we encode one byte if it is 0.
          break;
      }

      if (temp.array[temp.array.length - length] >= 0x80) {
        // Make it a non-negative integer.
        ++length;
        temp.ensureLengthFromBack(length);
        temp.array[temp.array.length - length] = 0;
      }

      this.payloadAppend(temp.slice(temp.array.length - length));
    }

    this.encodeHeader(this.payloadPosition_);
  }
};
DerNode.DerInteger.prototype = new DerNode();
DerNode.DerInteger.prototype.name = "DerInteger";

DerNode.DerInteger.prototype.toVal = function()
{
  if (this.payloadPosition_ > 0 && this.payload_.array[0] >= 0x80)
    throw new DerDecodingException(new Error
      ("DerInteger: Negative integers are not currently supported"));

  var result = 0;
  for (var i = 0; i < this.payloadPosition_; ++i) {
    result <<= 8;
    result += this.payload_.array[i];
  }

  return result;
};

/**
 * A DerBitString extends DerNode to handle a bit string.
 * Create a DerBitString with the given padding and inputBuf.
 * @param {Buffer} inputBuf An input buffer containing the bit octets to encode.
 * @param {number} paddingLen The number of bits of padding at the end of the bit
 * string.  Should be less than 8.
 */
DerNode.DerBitString = function DerBitString(inputBuf, paddingLen)
{
  // Call the base constructor.
  DerNode.call(this, DerNodeType.BitString);

  if (inputBuf != undefined) {
    this.payload_.ensureLength(this.payloadPosition_ + 1);
    this.payload_.array[this.payloadPosition_++] = paddingLen & 0xff;
    this.payloadAppend(inputBuf);
    this.encodeHeader(this.payloadPosition_);
  }
};
DerNode.DerBitString.prototype = new DerNode();
DerNode.DerBitString.prototype.name = "DerBitString";

/**
 * DerOctetString extends DerByteString to encode a string of bytes.
 * Create a new DerOctetString for the inputData.
 * @param {Buffer} inputData An input buffer containing the string to encode.
 */
DerNode.DerOctetString = function DerOctetString(inputData)
{
  // Call the base constructor.
  DerNode.DerByteString.call(this, inputData, DerNodeType.OctetString);
};
DerNode.DerOctetString.prototype = new DerNode.DerByteString();
DerNode.DerOctetString.prototype.name = "DerOctetString";

/**
 * A DerNull extends DerNode to encode a null value.
 * Create a DerNull.
 */
DerNode.DerNull = function DerNull()
{
  // Call the base constructor.
  DerNode.call(this, DerNodeType.Null);
  this.encodeHeader(0);
};
DerNode.DerNull.prototype = new DerNode();
DerNode.DerNull.prototype.name = "DerNull";

/**
 * A DerOid extends DerNode to represent an object identifier.
 * Create a DerOid with the given object identifier. The object identifier
 * string must begin with 0,1, or 2 and must contain at least 2 digits.
 * @param {string|OID} oid The OID string or OID object to encode.
 */
DerNode.DerOid = function DerOid(oid)
{
  // Call the base constructor.
  DerNode.call(this, DerNodeType.ObjectIdentifier);

  if (oid != undefined) {
    if (typeof oid === 'string') {
      var splitString = oid.split(".");
      var parts = [];
      for (var i = 0; i < splitString.length; ++i)
        parts.push(parseInt(splitString[i]));

      this.prepareEncoding(parts);
    }
    else
      // Assume oid is of type OID.
      this.prepareEncoding(oid.getIntegerList());
  }
};
DerNode.DerOid.prototype = new DerNode();
DerNode.DerOid.prototype.name = "DerOid";

/**
 * Encode a sequence of integers into an OID object and set the payload.
 * @param {Array<number>} value The array of integers.
 */
DerNode.DerOid.prototype.prepareEncoding = function(value)
{
  var firstNumber;
  if (value.length == 0)
    throw new DerEncodingException(new Error("No integer in OID"));
  else {
    if (value[0] >= 0 && value[0] <= 2)
      firstNumber = value[0] * 40;
    else
      throw new DerEncodingException(new Error("First integer in OID is out of range"));
  }

  if (value.length >= 2) {
    if (value[1] >= 0 && value[1] <= 39)
      firstNumber += value[1];
    else
      throw new DerEncodingException(new Error("Second integer in OID is out of range"));
  }

  var encodedBuffer = new DynamicBuffer(10);
  var encodedBufferPosition = 0;
  encodedBufferPosition = encodedBuffer.copy
    (DerNode.DerOid.encode128(firstNumber), encodedBufferPosition);

  if (value.length > 2) {
    for (var i = 2; i < value.length; ++i)
      encodedBufferPosition = encodedBuffer.copy
        (DerNode.DerOid.encode128(value[i]), encodedBufferPosition);
  }

  this.encodeHeader(encodedBufferPosition);
  this.payloadAppend(encodedBuffer.slice(0, encodedBufferPosition));
};

/**
 * Compute the encoding for one part of an OID, where values greater than 128
 * must be encoded as multiple bytes.
 * @param {number} value A component of an OID.
 * @return {Buffer} The encoded buffer.
 */
DerNode.DerOid.encode128 = function(value)
{
  var mask = (1 << 7) - 1;
  var outBytes = new DynamicBuffer(10);
  var outBytesLength = 0;
  // We encode backwards from the back.

  if (value < 128) {
    ++outBytesLength;
    outBytes.array[outBytes.array.length - outBytesLength] = value & mask;
  }
  else {
    ++outBytesLength;
    outBytes.array[outBytes.array.length - outBytesLength] = value & mask;
    value >>= 7;

    while (value != 0) {
      ++outBytesLength;
      outBytes.ensureLengthFromBack(outBytesLength);
      outBytes.array[outBytes.array.length - outBytesLength] =
        (value & mask) | (1 << 7);
      value >>= 7;
    }
  }

  return outBytes.slice(outBytes.array.length - outBytesLength);
};

/**
 * Convert an encoded component of the encoded OID to the original integer.
 * @param {number} offset The offset into this node's payload.
 * @param {Array<number>} skip Set skip[0] to the number of payload bytes to skip.
 * @return {number} The original integer.
 */
DerNode.DerOid.prototype.decode128 = function(offset, skip)
{
  var flagMask = 0x80;
  var result = 0;
  var oldOffset = offset;

  while ((this.payload_.array[offset] & flagMask) != 0) {
    result = 128 * result + (this.payload_.array[offset] & 0xff) - 128;
    offset += 1;
  }

  result = result * 128 + (this.payload_.array[offset] & 0xff);

  skip[0] = offset - oldOffset + 1;
  return result;
};

/**
 * Override to return the string representation of the OID.
 * @return {string} The string representation of the OID.
 */
DerNode.DerOid.prototype.toVal = function()
{
  var offset = 0;
  var components = []; // of number.

  while (offset < this.payloadPosition_) {
    var skip = [0];
    var nextVal = this.decode128(offset, skip);
    offset += skip[0];
    components.push(nextVal);
  }

  // For some odd reason, the first digits are represented in one byte.
  var firstByte = components[0];
  var firstDigit = Math.floor(firstByte / 40);
  var secondDigit = firstByte % 40;

  var result = firstDigit + "." + secondDigit;
  for (var i = 1; i < components.length; ++i)
    result += "." + components[i];

  return result;
};

/**
 * A DerSequence extends DerStructure to contains an ordered sequence of other
 * nodes.
 * Create a DerSequence.
 */
DerNode.DerSequence = function DerSequence()
{
  // Call the base constructor.
  DerNode.DerStructure.call(this, DerNodeType.Sequence);
};
DerNode.DerSequence.prototype = new DerNode.DerStructure();
DerNode.DerSequence.prototype.name = "DerSequence";

/**
 * A DerPrintableString extends DerByteString to handle a a printable string. No
 * escaping or other modification is done to the string.
 * Create a DerPrintableString with the given inputData.
 * @param {Buffer} inputData An input buffer containing the string to encode.
 */
DerNode.DerPrintableString = function DerPrintableString(inputData)
{
  // Call the base constructor.
  DerNode.DerByteString.call(this, inputData, DerNodeType.PrintableString);
};
DerNode.DerPrintableString.prototype = new DerNode.DerByteString();
DerNode.DerPrintableString.prototype.name = "DerPrintableString";

/**
 * A DerGeneralizedTime extends DerNode to represent a date and time, with
 * millisecond accuracy.
 * Create a DerGeneralizedTime with the given milliseconds since 1970.
 * @param {number} msSince1970 The timestamp as milliseconds since Jan 1, 1970.
 */
DerNode.DerGeneralizedTime = function DerGeneralizedTime(msSince1970)
{
  // Call the base constructor.
  DerNode.call(this, DerNodeType.GeneralizedTime);

  if (msSince1970 != undefined) {
    var derTime = DerNode.DerGeneralizedTime.toDerTimeString(msSince1970);
    // Use Blob to convert to a Buffer.
    this.payloadAppend(new Blob(derTime).buf());
    this.encodeHeader(this.payloadPosition_);
  }
};
DerNode.DerGeneralizedTime.prototype = new DerNode();
DerNode.DerGeneralizedTime.prototype.name = "DerGeneralizedTime";

/**
 * Convert a UNIX timestamp to the internal string representation.
 * @param {type} msSince1970 Timestamp as milliseconds since Jan 1, 1970.
 * @return {string} The string representation.
 */
DerNode.DerGeneralizedTime.toDerTimeString = function(msSince1970)
{
  var utcTime = new Date(Math.round(msSince1970));
  return utcTime.getUTCFullYear() +
         DerNode.DerGeneralizedTime.to2DigitString(utcTime.getUTCMonth() + 1) +
         DerNode.DerGeneralizedTime.to2DigitString(utcTime.getUTCDate()) +
         DerNode.DerGeneralizedTime.to2DigitString(utcTime.getUTCHours()) +
         DerNode.DerGeneralizedTime.to2DigitString(utcTime.getUTCMinutes()) +
         DerNode.DerGeneralizedTime.to2DigitString(utcTime.getUTCSeconds()) +
         "Z";
};

/**
 * A private method to zero pad an integer to 2 digits.
 * @param {number} x The number to pad.  Assume it is a non-negative integer.
 * @return {string} The padded string.
 */
DerNode.DerGeneralizedTime.to2DigitString = function(x)
{
  var result = x.toString();
  return result.length === 1 ? "0" + result : result;
};

/**
 * Override to return the milliseconds since 1970.
 * @return {number} The timestamp value as milliseconds since 1970.
 */
DerNode.DerGeneralizedTime.prototype.toVal = function()
{
  var timeStr = this.payload_.slice(0, this.payloadPosition_).toString();
  return Date.UTC
    (parseInt(timeStr.substr(0, 4)),
     parseInt(timeStr.substr(4, 2) - 1),
     parseInt(timeStr.substr(6, 2)),
     parseInt(timeStr.substr(8, 2)),
     parseInt(timeStr.substr(10, 2)),
     parseInt(timeStr.substr(12, 2)));
};
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * From PyNDN boost_info_parser by Adeola Bannis.
 *
 * 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.
 */

/** @ignore */
var fs = require('fs');

/**
 * BoostInfoTree is provided for compatibility with the Boost INFO property list
 * format used in ndn-cxx.
 *
 * Each node in the tree may have a name and a value as well as associated
 * sub-trees. The sub-tree names are not unique, and so sub-trees are stored as
 * dictionaries where the key is a sub-tree name and the values are the
 * sub-trees sharing the same name.
 *
 * Nodes can be accessed with a path syntax, as long as nodes in the path do not
 * contain the path separator '/' in their names.
 * @constructor
 */
var BoostInfoTree = function BoostInfoTree(value, parent)
{
  // subtrees is an array of {key: treeName, value: subtreeList} where
  // treeName is a string and subtreeList is an array of BoostInfoTree.
  // We can't use a dictionary because we want the keys to be in order.
  this.subtrees = [];
  this.value = value;
  this.parent = parent;

  this.lastChild = null;
};

/**
 * Insert a BoostInfoTree as a sub-tree with the given name.
 * @param {string} treeName The name of the new sub-tree.
 * @param {BoostInfoTree} newTree The sub-tree to add.
 */
BoostInfoTree.prototype.addSubtree = function(treeName, newTree)
{
  var subtreeList = this.find(treeName);
  if (subtreeList !== null)
    subtreeList.push(newTree);
  else
    this.subtrees.push({key: treeName, value: [newTree]});

  newTree.parent = this;
  this.lastChild = newTree;
};

/**
 * Create a new BoostInfo and insert it as a sub-tree with the given name.
 * @param {string} treeName The name of the new sub-tree.
 * @param {string} value The value associated with the new sub-tree.
 * @return {BoostInfoTree} The created sub-tree.
 */
BoostInfoTree.prototype.createSubtree = function(treeName, value)
{
  var newTree = new BoostInfoTree(value, this);
  this.addSubtree(treeName, newTree);
  return newTree;
};

/**
 * Look up using the key and return a list of the subtrees.
 * @param {string} key The key which may be a path separated with '/'.
 * @return {Array<BoostInfoTree>} A new array with pointers to the subtrees.
 */
BoostInfoTree.prototype.get = function(key)
{
  // Strip beginning '/'.
  key = key.replace(/^\/+/, "");
  if (key.length === 0)
    return [this];
  var path = key.split('/');

  var subtrees = this.find(path[0]);
  if (subtrees === null)
    return [];
  if (path.length == 1)
    return subtrees.slice(0);

  var newPath = path.slice(1).join('/');
  var foundVals = [];
  for (var i = 0; i < subtrees.length; ++i) {
    var t = subtrees[i];
    var partial = t.get(newPath);
    foundVals = foundVals.concat(partial);
  }
  return foundVals;
};

/**
 * Look up using the key and return string value of the first subtree.
 * @param {string} key The key which may be a path separated with '/'.
 * @return {string} The string value or null if not found.
 */
BoostInfoTree.prototype.getFirstValue = function(key)
{
  var list = this.get(key);
  if (list.length >= 1)
    return list[0].value;
  else
    return null;
};

BoostInfoTree.prototype.getValue = function() { return this.value; };

BoostInfoTree.prototype.getParent = function() { return this.parent; };

BoostInfoTree.prototype.getLastChild = function() { return this.lastChild; };

BoostInfoTree.prototype.prettyPrint = function(indentLevel)
{
  indentLevel = indentLevel || 1;

  var prefix = Array(indentLevel + 1).join(' ');
  var s = "";

  if (this.parent != null) {
    if (this.value && this.value.length > 0)
      s += "\"" + this.value + "\"";
    s += "\n";
  }

  if (this.subtrees.length > 0) {
    if (this.parent)
      s += prefix + "{\n";
    var nextLevel = Array(indentLevel + 2 + 1).join(' ');
    for (var i = 0; i < this.subtrees.length; ++i) {
      for (var iSubTree = 0; iSubTree < this.subtrees[i].value.length; ++iSubTree)
        s += nextLevel + this.subtrees[i].key + " " +
             this.subtrees[i].value[iSubTree].prettyPrint(indentLevel + 2);
    }

    if (this.parent)
      s +=  prefix + "}\n";
  }

  return s;
};

BoostInfoTree.prototype.toString = function()
{
  return this.prettyPrint();
};

/**
 * Use treeName to find the array of BoostInfoTree in this.subtrees.
 * @param {string} treeName The key in this.subtrees to search for. This does a
 * flat search in subtrees_.  It does not split by '/' into a path.
 * @return {Array<BoostInfoTree>} A array of BoostInfoTree, or null if not found.
 */
BoostInfoTree.prototype.find = function(treeName)
{
  for (var i = 0; i < this.subtrees.length; ++i) {
    if (this.subtrees[i].key == treeName)
      return this.subtrees[i].value;
  }

  return null;
};

/**
 * A BoostInfoParser reads files in Boost's INFO format and constructs a
 * BoostInfoTree.
 * @constructor
 */
var BoostInfoParser = function BoostInfoParser()
{
  this.root = new BoostInfoTree();
};

exports.BoostInfoParser = BoostInfoParser;
exports.BoostInfoTree = BoostInfoTree; // debug

/**
 * Add the contents of the file or input string to the root BoostInfoTree. There
 * are two forms:
 * read(fileName) reads fileName from the file system.
 * read(input, inputName) reads from the input, in which case inputName is used
 * only for log messages, etc.
 * @param {string} fileName The path to the INFO file.
 * @param {string} input The contents of the INFO file, with lines separated by
 * "\n" or "\r\n".
 * @param {string} inputName Use with input for log messages, etc.
 */
BoostInfoParser.prototype.read = function(fileNameOrInput, inputName)
{
  var input;
  if (typeof inputName == 'string')
    input = fileNameOrInput;
  else {
    // No inputName, so assume the first arg is the file name.
    var fileName = fileNameOrInput;
    inputName = fileName;
    input = fs.readFileSync(fileName).toString();
  }

  var ctx = this.root;
  var thisParser = this;
  input.split(/\r?\n/).forEach(function(line) {
    ctx = thisParser.parseLine(line.trim(), ctx);
  });
};

/**
 * Write the root tree of this BoostInfoParser as file in Boost's INFO format.
 * @param {string} fileName The output path.
 */
BoostInfoParser.prototype.write = function(fileName)
{
  fs.writeFileSync(fileName, "" + this.root);
};

/**
 * Get the root tree of this parser.
 * @return {BoostInfoTree} The root BoostInfoTree.
 */
BoostInfoParser.prototype.getRoot = function() { return this.root; };

/**
 * Similar to Python's shlex.split, split s into an array of strings which are
 * separated by whitespace, treating a string within quotes as a single entity
 * regardless of whitespace between the quotes. Also allow a backslash to escape
 * the next character.
 * @param {string} s The input string to split.
 * @return {Array<string>} An array of strings.
 */
BoostInfoParser.shlex_split = function(s)
{
  var result = [];
  if (s == "")
    return result;
  var whiteSpace = " \t\n\r";
  var iStart = 0;

  while (true) {
    // Move iStart past whitespace.
    while (whiteSpace.indexOf(s[iStart]) >= 0) {
      iStart += 1;
      if (iStart >= s.length)
        // Done.
        return result;
    }

    // Move iEnd to the end of the token.
    var iEnd = iStart;
    var inQuotation = false;
    var token = "";
    while (true) {
      if (s[iEnd] == '\\') {
        // Append characters up to the backslash, skip the backslash and
        //   move iEnd past the escaped character.
        token += s.substring(iStart, iEnd);
        iStart = iEnd + 1;
        iEnd = iStart;
        if (iEnd >= s.length)
          // An unusual case: A backslash at the end of the string.
          break;
      }
      else {
        if (inQuotation) {
          if (s[iEnd] == '\"') {
            // Append characters up to the end quote and skip.
            token += s.substring(iStart, iEnd);
            iStart = iEnd + 1;
            inQuotation = false;
          }
        }
        else {
          if (s[iEnd] == '\"') {
            // Append characters up to the start quote and skip.
            token += s.substring(iStart, iEnd);
            iStart = iEnd + 1;
            inQuotation = true;
          }
          else
            if (whiteSpace.indexOf(s[iEnd]) >= 0)
              break;
        }
      }

      iEnd += 1;
      if (iEnd >= s.length)
        break;
    }

    token += s.substring(iStart, iEnd);
    result.push(token);
    if (iEnd >= s.length)
      // Done.
      return result;

    iStart = iEnd;
  }
};

BoostInfoParser.prototype.parseLine = function(line, context)
{
  // Skip blank lines and comments.
  var commentStart = line.indexOf(';');
  if (commentStart >= 0)
    line = line.substring(0, commentStart).trim();
  if (line.length == 0)
    return context;

  // Usually we are expecting key and optional value.
  var strings = BoostInfoParser.shlex_split(line);
  var isSectionStart = false;
  var isSectionEnd = false;
  for (var i = 0; i < strings.length; ++i) {
    isSectionStart = (isSectionStart || strings[i] == "{");
    isSectionEnd = (isSectionEnd || strings[i] == "}");
  }

  if (!isSectionStart && !isSectionEnd) {
    var key = strings[0];
    var val;
    if (strings.length > 1)
      val = strings[1];
    context.createSubtree(key, val);

    return context;
  }

  // OK, who is the joker who put a { on the same line as the key name?!
  var sectionStart = line.indexOf('{');
  if (sectionStart > 0) {
    var firstPart = line.substring(0, sectionStart);
    var secondPart = line.substring(sectionStart);

    var ctx = this.parseLine(firstPart, context);
    return this.parseLine(secondPart, ctx);
  }

  // If we encounter a {, we are beginning a new context.
  // TODO: Error if there was already a subcontext here.
  if (line[0] == '{') {
    context = context.getLastChild();
    return context;
  }

  // If we encounter a }, we are ending a list context.
  if (line[0] == '}') {
    context = context.getParent();
    return context;
  }

  throw runtime_error("BoostInfoParser: input line is malformed");
};
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var Name = require('../name.js').Name; /** @ignore */
var InterestFilter = require('../interest-filter.js').InterestFilter; /** @ignore */
var ForwardingFlags = require('../forwarding-flags.js').ForwardingFlags; /** @ignore */
var WireFormat = require('../encoding/wire-format.js').WireFormat; /** @ignore */
var LOG = require('../log.js').Log.LOG;

/**
 * A MemoryContentCache holds a set of Data packets and answers an Interest to
 * return the correct Data packet. The cache is periodically cleaned up to
 * remove each stale Data packet based on its FreshnessPeriod (if it has one).
 * @note This class is an experimental feature.  See the API docs for more detail at
 * http://named-data.net/doc/ndn-ccl-api/memory-content-cache.html .
 *
 * Create a new MemoryContentCache to use the given Face.
 *
 * @param {Face} face The Face to use to call registerPrefix and
 * setInterestFilter, and which will call this object's OnInterest callback.
 * @param {number} cleanupIntervalMilliseconds (optional) The interval
 * in milliseconds between each check to clean up stale content in the cache. If
 * omitted, use a default of 1000 milliseconds. If this is a large number, then
 * effectively the stale content will not be removed from the cache.
 * @constructor
 */
var MemoryContentCache = function MemoryContentCache
  (face, cleanupIntervalMilliseconds)
{
  cleanupIntervalMilliseconds = (cleanupIntervalMilliseconds || 1000.0);

  this.face = face;
  this.cleanupIntervalMilliseconds = cleanupIntervalMilliseconds;
  this.nextCleanupTime = new Date().getTime() + cleanupIntervalMilliseconds;

  this.onDataNotFoundForPrefix = {}; /**< The map key is the prefix.toUri().
                                          The value is an OnInterest function. */
  this.interestFilterIdList = []; /**< elements are number */
  this.registeredPrefixIdList = []; /**< elements are number */
  this.noStaleTimeCache = []; /**< elements are MemoryContentCache.Content */
  this.staleTimeCache = [];   /**< elements are MemoryContentCache.StaleTimeContent */
  //StaleTimeContent::Compare contentCompare_;
  this.emptyComponent = new Name.Component();
  this.pendingInterestTable = [];

  var thisMemoryContentCache = this;
  this.storePendingInterestCallback = function
    (localPrefix, localInterest, localFace, localInterestFilterId, localFilter) {
       thisMemoryContentCache.storePendingInterest(localInterest, localFace);
    };
};

exports.MemoryContentCache = MemoryContentCache;

/**
 * Call registerPrefix on the Face given to the constructor so that this
 * MemoryContentCache will answer interests whose name has the prefix.
 * Alternatively, if the Face's registerPrefix has already been called,
 * then you can call this object's setInterestFilter.
 * @param {Name} prefix The Name for the prefix to register. This copies the Name.
 * @param {function} onRegisterFailed If this fails to register the prefix for
 * any reason, this calls onRegisterFailed(prefix) where prefix is the prefix
 * given to registerPrefix.
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onRegisterSuccess (optional) When this receives a success
 * message, this calls onRegisterSuccess[0](prefix, registeredPrefixId). If
 * onRegisterSuccess is [null] or omitted, this does not use it. (As a special
 * case, this optional parameter is supplied as an array of one function,
 * instead of just a function, in order to detect when it is used instead of the
 * following optional onDataNotFound function.)
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onDataNotFound (optional) If a data packet for an interest
 * is not found in the cache, this forwards the interest by calling
 * onDataNotFound(prefix, interest, face, interestFilterId, filter). Your
 * callback can find the Data packet for the interest and call
 * face.putData(data). If your callback cannot find the Data packet, it can
 * optionally call storePendingInterest(interest, face) to store the pending
 * interest in this object to be satisfied by a later call to add(data). If you
 * want to automatically store all pending interests, you can simply use
 * getStorePendingInterest() for onDataNotFound. If onDataNotFound is omitted or
 * null, this does not use it.
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {ForwardingFlags} flags (optional) See Face.registerPrefix.
 * @param {WireFormat} wireFormat (optional) See Face.registerPrefix.
 */
MemoryContentCache.prototype.registerPrefix = function
  (prefix, onRegisterFailed, onRegisterSuccess, onDataNotFound, flags, wireFormat)
{
  var arg3 = onRegisterSuccess;
  var arg4 = onDataNotFound;
  var arg5 = flags;
  var arg6 = wireFormat;
  // arg3,                arg4,            arg5,            arg6 may be:
  // [OnRegisterSuccess], OnDataNotFound,  ForwardingFlags, WireFormat
  // [OnRegisterSuccess], OnDataNotFound,  ForwardingFlags, null
  // [OnRegisterSuccess], OnDataNotFound,  WireFormat,      null
  // [OnRegisterSuccess], OnDataNotFound,  null,            null
  // [OnRegisterSuccess], ForwardingFlags, WireFormat,      null
  // [OnRegisterSuccess], ForwardingFlags, null,            null
  // [OnRegisterSuccess], WireFormat,      null,            null
  // [OnRegisterSuccess], null,            null,            null
  // OnDataNotFound,      ForwardingFlags, WireFormat,      null
  // OnDataNotFound,      ForwardingFlags, null,            null
  // OnDataNotFound,      WireFormat,      null,            null
  // OnDataNotFound,      null,            null,            null
  // ForwardingFlags,     WireFormat,      null,            null
  // ForwardingFlags,     null,            null,            null
  // WireFormat,          null,            null,            null
  // null,                null,            null,            null
  if (typeof arg3 === "object" && arg3.length === 1 &&
      typeof arg3[0] === "function")
    onRegisterSuccess = arg3[0];
  else
    onRegisterSuccess = null;

  if (typeof arg3 === "function")
    onDataNotFound = arg3;
  else if (typeof arg4 === "function")
    onDataNotFound = arg4;
  else
    onDataNotFound = null;

  if (arg3 instanceof ForwardingFlags)
    flags = arg3;
  else if (arg4 instanceof ForwardingFlags)
    flags = arg4;
  else if (arg5 instanceof ForwardingFlags)
    flags = arg5;
  else
    flags = new ForwardingFlags();

  if (arg3 instanceof WireFormat)
    wireFormat = arg3;
  else if (arg4 instanceof WireFormat)
    wireFormat = arg4;
  else if (arg5 instanceof WireFormat)
    wireFormat = arg5;
  else if (arg6 instanceof WireFormat)
    wireFormat = arg6;
  else
    wireFormat = WireFormat.getDefaultWireFormat();

  if (onDataNotFound)
    this.onDataNotFoundForPrefix[prefix.toUri()] = onDataNotFound;
  var registeredPrefixId = this.face.registerPrefix
    (prefix, this.onInterest.bind(this), onRegisterFailed, onRegisterSuccess,
     flags, wireFormat);
  this.registeredPrefixIdList.push(registeredPrefixId);
};

/**
 * Call setInterestFilter on the Face given to the constructor so that this
 * MemoryContentCache will answer interests whose name matches the filter.
 * There are two forms of setInterestFilter.
 * The first form uses the exact given InterestFilter:
 * setInterestFilter(filter, [onDataNotFound]).
 * The second form creates an InterestFilter from the given prefix Name:
 * setInterestFilter(prefix, [onDataNotFound]).
 * @param {InterestFilter} filter The InterestFilter with a prefix and optional
 * regex filter used to match the name of an incoming Interest. This makes a
 * copy of filter.
 * @param {Name} prefix The Name prefix used to match the name of an incoming
 * Interest.
 * @param {function} onDataNotFound (optional) If a data packet for an interest
 * is not found in the cache, this forwards the interest by calling
 * onDataNotFound(prefix, interest, face, interestFilterId, filter). Your
 * callback can find the Data packet for the interest and call
 * face.putData(data). If your callback cannot find the Data packet, it can
 * optionally call storePendingInterest(interest, face) to store the pending
 * interest in this object to be satisfied by a later call to add(data). If you
 * want to automatically store all pending interests, you can simply use
 * getStorePendingInterest() for onDataNotFound. If onDataNotFound is omitted or
 * null, this does not use it.
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 */
MemoryContentCache.prototype.setInterestFilter = function
  (filterOrPrefix, onDataNotFound)
{
  if (onDataNotFound) {
    var prefix;
    if (typeof filterOrPrefix === 'object' && filterOrPrefix instanceof InterestFilter)
      prefix = filterOrPrefix.getPrefix();
    else
      prefix = filterOrPrefix;
    this.onDataNotFoundForPrefix[prefix.toUri()] = onDataNotFound;
  }
  var interestFilterId = this.face.setInterestFilter
    (filterOrPrefix, this.onInterest.bind(this));
  this.interestFilterIdList.push(interestFilterId);
};

/**
 * Call Face.unsetInterestFilter and Face.removeRegisteredPrefix for all the
 * prefixes given to the setInterestFilter and registerPrefix method on this
 * MemoryContentCache object so that it will not receive interests any more. You
 * can call this if you want to "shut down" this MemoryContentCache while your
 * application is still running.
 */
MemoryContentCache.prototype.unregisterAll = function()
{
  for (var i = 0; i < this.interestFilterIdList.length; ++i)
    this.face.unsetInterestFilter(this.interestFilterIdList[i]);
  this.interestFilterIdList = [];

  for (var i = 0; i < this.registeredPrefixIdList.length; ++i)
    this.face.removeRegisteredPrefix(this.registeredPrefixIdList[i]);
  this.registeredPrefixIdList = [];

  // Also clear each onDataNotFoundForPrefix given to registerPrefix.
  this.onDataNotFoundForPrefix = {};
};

/**
 * Add the Data packet to the cache so that it is available to use to answer
 * interests. If data.getMetaInfo().getFreshnessPeriod() is not null, set the
 * staleness time to now plus data.getMetaInfo().getFreshnessPeriod(), which is
 * checked during cleanup to remove stale content. This also checks if
 * cleanupIntervalMilliseconds milliseconds have passed and removes stale
 * content from the cache. After removing stale content, remove timed-out
 * pending interests from storePendingInterest(), then if the added Data packet
 * satisfies any interest, send it through the face and remove the interest
 * from the pending interest table.
 * @param {Data} data The Data packet object to put in the cache. This copies
 * the fields from the object.
 */
MemoryContentCache.prototype.add = function(data)
{
  this.doCleanup();

  if (data.getMetaInfo().getFreshnessPeriod() != null &&
      data.getMetaInfo().getFreshnessPeriod() >= 0.0) {
    // The content will go stale, so use staleTimeCache.
    var content = new MemoryContentCache.StaleTimeContent(data);
    // Insert into staleTimeCache, sorted on content.staleTimeMilliseconds.
    // Search from the back since we expect it to go there.
    var i = this.staleTimeCache.length - 1;
    while (i >= 0) {
      if (this.staleTimeCache[i].staleTimeMilliseconds <= content.staleTimeMilliseconds)
        break;
      --i;
    }
    // Element i is the greatest less than or equal to
    // content.staleTimeMilliseconds, so insert after it.
    this.staleTimeCache.splice(i + 1, 0, content);
  }
  else
    // The data does not go stale, so use noStaleTimeCache.
    this.noStaleTimeCache.push(new MemoryContentCache.Content(data));

  // Remove timed-out interests and check if the data packet matches any pending
  // interest.
  // Go backwards through the list so we can erase entries.
  var nowMilliseconds = new Date().getTime();
  for (var i = this.pendingInterestTable.length - 1; i >= 0; --i) {
    if (this.pendingInterestTable[i].isTimedOut(nowMilliseconds)) {
      this.pendingInterestTable.splice(i, 1);
      continue;
    }
    if (this.pendingInterestTable[i].getInterest().matchesName(data.getName())) {
      try {
        // Send to the same face from the original call to onInterest.
        // wireEncode returns the cached encoding if available.
        this.pendingInterestTable[i].getFace().send(data.wireEncode().buf());
      }
      catch (ex) {
        if (LOG > 0)
          console.log("" + ex);
        return;
      }

      // The pending interest is satisfied, so remove it.
      this.pendingInterestTable.splice(i, 1);
    }
  }
};

/**
 * Store an interest from an OnInterest callback in the internal pending
 * interest table (normally because there is no Data packet available yet to
 * satisfy the interest). add(data) will check if the added Data packet
 * satisfies any pending interest and send it through the face.
 * @param {Interest} interest The Interest for which we don't have a Data packet
 * yet. You should not modify the interest after calling this.
 * @param {Face} face The Face with the connection which received
 * the interest. This comes from the OnInterest callback.
 */
MemoryContentCache.prototype.storePendingInterest = function(interest, face)
{
  this.pendingInterestTable.push
    (new MemoryContentCache.PendingInterest(interest, face));
};

/**
 * Return a callback to use for onDataNotFound in registerPrefix which simply
 * calls storePendingInterest() to store the interest that doesn't match a
 * Data packet. add(data) will check if the added Data packet satisfies any
 * pending interest and send it.
 * @return {function} A callback to use for onDataNotFound in registerPrefix().
 */
MemoryContentCache.prototype.getStorePendingInterest = function()
{
  return this.storePendingInterestCallback;
};

/**
 * This is the OnInterest callback which is called when the library receives
 * an interest whose name has the prefix given to registerPrefix. First check
 * if cleanupIntervalMilliseconds milliseconds have passed and remove stale
 * content from the cache. Then search the cache for the Data packet, matching
 * any interest selectors including ChildSelector, and send the Data packet
 * to the face. If no matching Data packet is in the cache, call
 * the callback in onDataNotFoundForPrefix (if defined).
 */
MemoryContentCache.prototype.onInterest = function
  (prefix, interest, face, interestFilterId, filter)
{
  this.doCleanup();

  var selectedComponent = 0;
  var selectedEncoding = null;
  // We need to iterate over both arrays.
  var totalSize = this.staleTimeCache.length + this.noStaleTimeCache.length;
  for (var i = 0; i < totalSize; ++i) {
    var content;
    if (i < this.staleTimeCache.length)
      content = this.staleTimeCache[i];
    else
      // We have iterated over the first array. Get from the second.
      content = this.noStaleTimeCache[i - this.staleTimeCache.length];

    if (interest.matchesName(content.getName())) {
      if (interest.getChildSelector() < 0) {
        // No child selector, so send the first match that we have found.
        face.send(content.getDataEncoding());
        return;
      }
      else {
        // Update selectedEncoding based on the child selector.
        var component;
        if (content.getName().size() > interest.getName().size())
          component = content.getName().get(interest.getName().size());
        else
          component = this.emptyComponent;

        var gotBetterMatch = false;
        if (selectedEncoding === null)
          // Save the first match.
          gotBetterMatch = true;
        else {
          if (interest.getChildSelector() == 0) {
            // Leftmost child.
            if (component.compare(selectedComponent) < 0)
              gotBetterMatch = true;
          }
          else {
            // Rightmost child.
            if (component.compare(selectedComponent) > 0)
              gotBetterMatch = true;
          }
        }

        if (gotBetterMatch) {
          selectedComponent = component;
          selectedEncoding = content.getDataEncoding();
        }
      }
    }
  }

  if (selectedEncoding !== null)
    // We found the leftmost or rightmost child.
    face.send(selectedEncoding);
  else {
    // Call the onDataNotFound callback (if defined).
    var onDataNotFound = this.onDataNotFoundForPrefix[prefix.toUri()];
    if (onDataNotFound)
      onDataNotFound(prefix, interest, face, interestFilterId, filter);
  }
};

/**
 * Check if now is greater than nextCleanupTime and, if so, remove stale
 * content from staleTimeCache and reset nextCleanupTime based on
 * cleanupIntervalMilliseconds. Since add(Data) does a sorted insert into
 * staleTimeCache, the check for stale data is quick and does not require
 * searching the entire staleTimeCache.
 */
MemoryContentCache.prototype.doCleanup = function()
{
  var now = new Date().getTime();
  if (now >= this.nextCleanupTime) {
    // staleTimeCache is sorted on staleTimeMilliseconds, so we only need to
    // erase the stale entries at the front, then quit.
    while (this.staleTimeCache.length > 0 && this.staleTimeCache[0].isStale(now))
      this.staleTimeCache.shift();

    this.nextCleanupTime = now + this.cleanupIntervalMilliseconds;
  }
};

/**
 * Content is a private class to hold the name and encoding for each entry
 * in the cache. This base class is for a Data packet without a FreshnessPeriod.
 *
 * Create a new Content entry to hold data's name and wire encoding.
 * @param {Data} data The Data packet whose name and wire encoding are copied.
 */
MemoryContentCache.Content = function MemoryContentCacheContent(data)
{
  // Allow an undefined data so that StaleTimeContent can set the prototype.
  if (data) {
    // Copy the name.
    this.name = new Name(data.getName());
    // wireEncode returns the cached encoding if available.
    this.dataEncoding = data.wireEncode().buf();
  }
};

MemoryContentCache.Content.prototype.getName = function() { return this.name; };

MemoryContentCache.Content.prototype.getDataEncoding = function() { return this.dataEncoding; };

/**
 * StaleTimeContent extends Content to include the staleTimeMilliseconds for
 * when this entry should be cleaned up from the cache.
 *
 * Create a new StaleTimeContent to hold data's name and wire encoding as well
 * as the staleTimeMilliseconds which is now plus
 * data.getMetaInfo().getFreshnessPeriod().
 * @param {Data} data The Data packet whose name and wire encoding are copied.
 */
MemoryContentCache.StaleTimeContent = function MemoryContentCacheStaleTimeContent
  (data)
{
  // Call the base constructor.
  MemoryContentCache.Content.call(this, data);

  // Set up staleTimeMilliseconds which is The time when the content becomse
  // stale in milliseconds according to new Date().getTime().
  this.staleTimeMilliseconds = new Date().getTime() +
    data.getMetaInfo().getFreshnessPeriod();
};

MemoryContentCache.StaleTimeContent.prototype = new MemoryContentCache.Content();
MemoryContentCache.StaleTimeContent.prototype.name = "StaleTimeContent";

/**
 * Check if this content is stale.
 * @param {number} nowMilliseconds The current time in milliseconds from
 * new Date().getTime().
 * @return {boolean} True if this content is stale, otherwise false.
 */
MemoryContentCache.StaleTimeContent.prototype.isStale = function(nowMilliseconds)
{
  return this.staleTimeMilliseconds <= nowMilliseconds;
};

/**
 * A PendingInterest holds an interest which onInterest received but could
 * not satisfy. When we add a new data packet to the cache, we will also check
 * if it satisfies a pending interest.
 */
MemoryContentCache.PendingInterest = function MemoryContentCachePendingInterest
  (interest, face)
{
  this.interest = interest;
  this.face = face;

  if (this.interest.getInterestLifetimeMilliseconds() >= 0.0)
    this.timeoutMilliseconds = (new Date()).getTime() +
      this.interest.getInterestLifetimeMilliseconds();
  else
    this.timeoutMilliseconds = -1.0;
};

/**
 * Return the interest given to the constructor.
 */
MemoryContentCache.PendingInterest.prototype.getInterest = function()
{
  return this.interest;
};

/**
 * Return the face given to the constructor.
 */
MemoryContentCache.PendingInterest.prototype.getFace = function()
{
  return this.face;
};

/**
 * Check if this interest is timed out.
 * @param {number} nowMilliseconds The current time in milliseconds from
 * new Date().getTime().
 * @return {boolean} True if this interest timed out, otherwise false.
 */
MemoryContentCache.PendingInterest.prototype.isTimedOut = function(nowMilliseconds)
{
  return this.timeoutTimeMilliseconds >= 0.0 &&
         nowMilliseconds >= this.timeoutTimeMilliseconds;
};
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * From PyNDN ndn_regex.py by Adeola Bannis.
 * Originally from Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>.
 *
 * 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.
 */

/** @ignore */
var Name = require('../name.js').Name;

/**
 * An NdnRegexMatcher has static methods to convert an NDN regex
 * (http://redmine.named-data.net/projects/ndn-cxx/wiki/Regex) to a JavaScript
 * RegExp that can match against URIs.
 * @constructor
 */
var NdnRegexMatcher = function NdnRegexMatcher()
{
};

exports.NdnRegexMatcher = NdnRegexMatcher;

/**
 * Determine if the provided NDN regex matches the given Name.
 * @param {string} pattern The NDN regex.
 * @param {Name} name The Name to match against the regex.
 * @return {Object} The match object from String.match, or null if the pattern
 * does not match.
 */
NdnRegexMatcher.match = function(pattern, name)
{
  var nameUri = name.toUri();

  pattern = NdnRegexMatcher.sanitizeSets(pattern);

  pattern = pattern.replace(/<>/g, "(?:<.+?>)");
  pattern = pattern.replace(/>/g, "");
  pattern = pattern.replace(/<(?!!)/g, "/");

  return nameUri.match(new RegExp(pattern));
};

NdnRegexMatcher.sanitizeSets = function(pattern)
{
  var newPattern = pattern;

  // Positive sets can be changed to (comp1|comp2).
  // Negative sets must be changed to negative lookahead assertions.

  var regex1 = /\[(\^?)(.*?)\]/g;
  var match;
  while ((match = regex1.exec(pattern)) !== null) {
    // Insert | between components.
    // Match 2 is the last match, so we use the hack of working backwards from
    //   lastIndex.  If possible, this should be changed to a more direct solution.
    var start = regex1.lastIndex - "]".length - match[2].length;
    var end = start + match[2].length;
    if (start - end === 0)
      continue;
    var oldStr = match[2];
    var newStr = oldStr.replace(/></g, ">|<");
    newPattern = newPattern.substr(0, start) + newStr + newPattern.substr(end);
  }

  // Replace [] with (),  or (?! ) for negative lookahead.
  // If we use negative lookahead, we also have to consume one component.
  var isNegative = newPattern.indexOf("[^") >= 0;
  if (isNegative) {
    newPattern = newPattern.replace(/\[\^/g, "(?:(?!");
    newPattern = newPattern.replace(/\]/g, ")(?:/.*)*)");
  }
  else {
    newPattern = newPattern.replace(/\[/g, "(");
    newPattern = newPattern.replace(/\]/g, ")");
  }

  return newPattern;
};
/**
 * Copyright (C) 2015-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * @author: From ndn-cxx util/segment-fetcher https://github.com/named-data/ndn-cxx
 *
 * 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.
 */

/** @ignore */
var Interest = require('../interest.js').Interest; /** @ignore */
var Blob = require('./blob.js').Blob; /** @ignore */
var KeyChain = require('../security/key-chain.js').KeyChain; /** @ignore */
var NdnCommon = require('./ndn-common.js').NdnCommon;

/**
 * SegmentFetcher is a utility class to fetch the latest version of segmented data.
 *
 * SegmentFetcher assumes that the data is named /<prefix>/<version>/<segment>,
 * where:
 * - <prefix> is the specified name prefix,
 * - <version> is an unknown version that needs to be discovered, and
 * - <segment> is a segment number. (The number of segments is unknown and is
 *   controlled by the `FinalBlockId` field in at least the last Data packet.
 *
 * The following logic is implemented in SegmentFetcher:
 *
 * 1. Express the first Interest to discover the version:
 *
 *    >> Interest: /<prefix>?ChildSelector=1&MustBeFresh=true
 *
 * 2. Infer the latest version of the Data: <version> = Data.getName().get(-2)
 *
 * 3. If the segment number in the retrieved packet == 0, go to step 5.
 *
 * 4. Send an Interest for segment 0:
 *
 *    >> Interest: /<prefix>/<version>/<segment=0>
 *
 * 5. Keep sending Interests for the next segment while the retrieved Data does
 *    not have a FinalBlockId or the FinalBlockId != Data.getName().get(-1).
 *
 *    >> Interest: /<prefix>/<version>/<segment=(N+1))>
 *
 * 6. Call the onComplete callback with a Blob that concatenates the content
 *    from all the segmented objects.
 *
 * If an error occurs during the fetching process, the onError callback is called
 * with a proper error code.  The following errors are possible:
 *
 * - `INTEREST_TIMEOUT`: if any of the Interests times out
 * - `DATA_HAS_NO_SEGMENT`: if any of the retrieved Data packets don't have a segment
 *   as the last component of the name (not counting the implicit digest)
 * - `SEGMENT_VERIFICATION_FAILED`: if any retrieved segment fails
 *   the user-provided VerifySegment callback or KeyChain verifyData.
 * - `IO_ERROR`: for I/O errors when sending an Interest.
 *
 * In order to validate individual segments, a KeyChain needs to be supplied.
 * If verifyData fails, the fetching process is aborted with
 * SEGMENT_VERIFICATION_FAILED. If data validation is not required, pass null.
 *
 * Example:
 *     var onComplete = function(content) { ... }
 *
 *     var onError = function(errorCode, message) { ... }
 *
 *     var interest = new Interest(new Name("/data/prefix"));
 *     interest.setInterestLifetimeMilliseconds(1000);
 *
 *     SegmentFetcher.fetch(face, interest, null, onComplete, onError);
 *
 * This is a private constructor to create a new SegmentFetcher to use the Face.
 * An application should use SegmentFetcher.fetch. If validatorKeyChain is not
 * null, use it and ignore verifySegment. After creating the SegmentFetcher,
 * call fetchFirstSegment.
 * @param {Face} face This calls face.expressInterest to fetch more segments.
 * @param validatorKeyChain {KeyChain} If this is not null, use its verifyData
 * instead of the verifySegment callback.
 * @param {function} verifySegment When a Data packet is received this calls
 * verifySegment(data) where data is a Data object. If it returns False then
 * abort fetching and call onError with
 * SegmentFetcher.ErrorCode.SEGMENT_VERIFICATION_FAILED.
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onComplete When all segments are received, call
 * onComplete(content) where content is a Blob which has the concatenation of
 * the content of all the segments.
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onError Call onError.onError(errorCode, message) for
 * timeout or an error processing segments. errorCode is a value from
 * SegmentFetcher.ErrorCode and message is a related string.
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @constructor
 */
var SegmentFetcher = function SegmentFetcher
  (face, validatorKeyChain, verifySegment, onComplete, onError)
{
  this.face = face;
  this.validatorKeyChain = validatorKeyChain;
  this.verifySegment = verifySegment;
  this.onComplete = onComplete;
  this.onError = onError;

  this.contentParts = []; // of Buffer
};

exports.SegmentFetcher = SegmentFetcher;

/**
 * An ErrorCode value is passed in the onError callback.
 */
SegmentFetcher.ErrorCode = {
  INTEREST_TIMEOUT: 1,
  DATA_HAS_NO_SEGMENT: 2,
  SEGMENT_VERIFICATION_FAILED: 3
};

/**
 * DontVerifySegment may be used in fetch to skip validation of Data packets.
 */
SegmentFetcher.DontVerifySegment = function(data)
{
  return true;
};

/**
 * Initiate segment fetching. For more details, see the documentation for the
 * class. There are two forms of fetch:
 * fetch(face, baseInterest, validatorKeyChain, onComplete, onError)
 * and
 * fetch(face, baseInterest, verifySegment, onComplete, onError)
 * @param {Face} face This calls face.expressInterest to fetch more segments.
 * @param {Interest} baseInterest An Interest for the initial segment of the
 * requested data, where baseInterest.getName() has the name prefix. This
 * interest may include a custom InterestLifetime and selectors that will
 * propagate to all subsequent Interests. The only exception is that the initial
 * Interest will be forced to include selectors "ChildSelector=1" and
 * "MustBeFresh=true" which will be turned off in subsequent Interests.
 * @param validatorKeyChain {KeyChain} When a Data packet is received this calls
 * validatorKeyChain.verifyData(data). If validation fails then abortfetching
 * and call onError with SEGMENT_VERIFICATION_FAILED. This does not make a copy
 * of the KeyChain; the object must remain valid while fetching.
 * If validatorKeyChain is null, this does not validate the data packet.
 * @param {function} verifySegment When a Data packet is received this calls
 * verifySegment(data) where data is a Data object. If it returns False then
 * abort fetching and call onError with
 * SegmentFetcher.ErrorCode.SEGMENT_VERIFICATION_FAILED. If data validation is
 * not required, use SegmentFetcher.DontVerifySegment.
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onComplete When all segments are received, call
 * onComplete(content) where content is a Blob which has the concatenation of
 * the content of all the segments.
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onError Call onError.onError(errorCode, message) for
 * timeout or an error processing segments. errorCode is a value from
 * SegmentFetcher.ErrorCode and message is a related string.
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 */
SegmentFetcher.fetch = function
  (face, baseInterest, validatorKeyChainOrVerifySegment, onComplete, onError)
{
  if (validatorKeyChainOrVerifySegment == null ||
      validatorKeyChainOrVerifySegment instanceof KeyChain)
    new SegmentFetcher
      (face, validatorKeyChainOrVerifySegment, SegmentFetcher.DontVerifySegment,
       onComplete, onError)
      .fetchFirstSegment(baseInterest);
  else
    new SegmentFetcher
      (face, null, validatorKeyChainOrVerifySegment, onComplete, onError)
      .fetchFirstSegment(baseInterest);
};

SegmentFetcher.prototype.fetchFirstSegment = function(baseInterest)
{
  var interest = new Interest(baseInterest);
  interest.setChildSelector(1);
  interest.setMustBeFresh(true);
  var thisSegmentFetcher = this;
  this.face.expressInterest
    (interest,
     function(originalInterest, data)
       { thisSegmentFetcher.onData(originalInterest, data); },
     function(interest) { thisSegmentFetcher.onTimeout(interest); });
};

SegmentFetcher.prototype.fetchNextSegment = function
  (originalInterest, dataName, segment)
{
  // Start with the original Interest to preserve any special selectors.
  var interest = new Interest(originalInterest);
  // Changing a field clears the nonce so that the library will generate a new
  // one.
  interest.setChildSelector(0);
  interest.setMustBeFresh(false);
  interest.setName(dataName.getPrefix(-1).appendSegment(segment));
  var thisSegmentFetcher = this;
  this.face.expressInterest
    (interest, function(originalInterest, data)
       { thisSegmentFetcher.onData(originalInterest, data); },
     function(interest) { thisSegmentFetcher.onTimeout(interest); });
};

SegmentFetcher.prototype.onData = function(originalInterest, data)
{
  if (this.validatorKeyChain != null) {
    try {
      var thisSegmentFetcher = this;
      this.validatorKeyChain.verifyData
        (data,
         function(localData) {
           thisSegmentFetcher.onVerified(localData, originalInterest);
         },
         this.onValidationFailed.bind(this));
    } catch (ex) {
      console.log("Error in KeyChain.verifyData: " + ex);
    }
  }
  else {
    if (!this.verifySegment(data)) {
      try {
        this.onError
          (SegmentFetcher.ErrorCode.SEGMENT_VERIFICATION_FAILED,
           "Segment verification failed");
      } catch (ex) {
        console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
      }
      return;
    }

    this.onVerified(data, originalInterest);
  }
};

SegmentFetcher.prototype.onVerified = function(data, originalInterest)
{
  if (!SegmentFetcher.endsWithSegmentNumber(data.getName())) {
    // We don't expect a name without a segment number.  Treat it as a bad packet.
    try {
      this.onError
        (SegmentFetcher.ErrorCode.DATA_HAS_NO_SEGMENT,
         "Got an unexpected packet without a segment number: " +
          data.getName().toUri());
    } catch (ex) {
      console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
    }
  }
  else {
    var currentSegment = 0;
    try {
      currentSegment = data.getName().get(-1).toSegment();
    }
    catch (ex) {
      try {
        this.onError
          (SegmentFetcher.ErrorCode.DATA_HAS_NO_SEGMENT,
           "Error decoding the name segment number " +
           data.getName().get(-1).toEscapedString() + ": " + ex);
      } catch (ex) {
        console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
      }
      return;
    }

    var expectedSegmentNumber = this.contentParts.length;
    if (currentSegment != expectedSegmentNumber)
      // Try again to get the expected segment.  This also includes the case
      // where the first segment is not segment 0.
      this.fetchNextSegment
        (originalInterest, data.getName(), expectedSegmentNumber);
    else {
      // Save the content and check if we are finished.
      this.contentParts.push(data.getContent().buf());

      if (data.getMetaInfo().getFinalBlockId().getValue().size() > 0) {
        var finalSegmentNumber = 0;
        try {
          finalSegmentNumber = (data.getMetaInfo().getFinalBlockId().toSegment());
        }
        catch (ex) {
          try {
            this.onError
              (SegmentFetcher.ErrorCode.DATA_HAS_NO_SEGMENT,
               "Error decoding the FinalBlockId segment number " +
               data.getMetaInfo().getFinalBlockId().toEscapedString() +
               ": " + ex);
          } catch (ex) {
            console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
          }
          return;
        }

        if (currentSegment == finalSegmentNumber) {
          // We are finished.

          // Concatenate to get content.
          var content = Buffer.concat(this.contentParts);
          try {
            this.onComplete(new Blob(content, false));
          } catch (ex) {
            console.log("Error in onComplete: " + NdnCommon.getErrorWithStackTrace(ex));
          }
          return;
        }
      }

      // Fetch the next segment.
      this.fetchNextSegment
        (originalInterest, data.getName(), expectedSegmentNumber + 1);
    }
  }
}

SegmentFetcher.prototype.onValidationFailed = function(data, reason)
{
  try {
    this.onError
      (SegmentFetcher.ErrorCode.SEGMENT_VERIFICATION_FAILED,
       "Segment verification failed for " + data.getName().toUri() +
       " . Reason: " + reason);
  } catch (ex) {
    console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
  }
};

SegmentFetcher.prototype.onTimeout = function(interest)
{
  try {
    this.onError
      (SegmentFetcher.ErrorCode.INTEREST_TIMEOUT,
       "Time out for interest " + interest.getName().toUri());
  } catch (ex) {
    console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
  }
};

/**
 * Check if the last component in the name is a segment number.
 * @param {Name} name The name to check.
 * @return {boolean} True if the name ends with a segment number, otherwise false.
 */
SegmentFetcher.endsWithSegmentNumber = function(name)
{
  return name.size() >= 1 && name.get(-1).isSegment();
};
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/**
 * Transport is a base class for specific transport classes such as TcpTransport.
 * @constructor
 */
var Transport = function Transport()
{
};

exports.Transport = Transport;

/**
 * Transport.ConnectionInfo is a base class for connection information used by
 * subclasses of Transport.
 */
Transport.ConnectionInfo = function TransportConnectionInfo()
{
};

/**
 * Determine whether this transport connecting according to connectionInfo is to
 * a node on the current machine. This affects the processing of
 * Face.registerPrefix(): if the NFD is local, registration occurs with the
 * '/localhost/nfd...' prefix; if non-local, the library will attempt to use
 * remote prefix registration using '/localhop/nfd...'
 * @param {Transport.ConnectionInfo} connectionInfo A ConnectionInfo with the
 * host to check.
 * @param {function} onResult On success, this calls onResult(isLocal) where
 * isLocal is true if the host is local, false if not. We use callbacks because
 * this may need to do an asynchronous DNS lookup.
 * @param {function} onError On failure for DNS lookup or other error, this
 * calls onError(message) where message is an error string.
 */
Transport.prototype.isLocal = function(connectionInfo, onResult, onError)
{
  onError("Transport.isLocal is not implemented");
};
/**
 * Copyright (C) 2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * @author: Wentao Shang
 *
 * 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.
 */

/**
 * A MicroForwarderTransport extends Transport to connect to the browser's
 * micro forwarder service. This assumes that the MicroForwarder extensions has
 * been installed.
 * @constructor
 */
var MicroForwarderTransport = function MicroForwarderTransport()
{
  // Call the base constructor.
  Transport.call(this);

  this.elementReader = null;
  this.connectionInfo = null; // Read by Face.
  this.onReceivedObject = null;

  var thisTransport = this;
  window.addEventListener("message", function(event) {
    // We only accept messages from ourselves
    if (event.source != window)
      return;

    if (event.data.type && (event.data.type == "FromMicroForwarderStub")) {
      var obj = event.data.object;
      if (obj.type && obj.type == "Buffer") {
        if (thisTransport.elementReader != null)
          thisTransport.elementReader.onReceivedData(new Buffer(obj.data));
      }
      else {
        if (thisTransport.onReceivedObject)
          thisTransport.onReceivedObject(obj);
      }
    }
  }, false);
};

MicroForwarderTransport.prototype = new Transport();
MicroForwarderTransport.prototype.name = "MicroForwarderTransport";

/**
 * Create a new MicroForwarderTransport.ConnectionInfo which extends
 * Transport.ConnectionInfo to hold info for the micro forwarer connection.
 */
MicroForwarderTransport.ConnectionInfo = function MicroForwarderTransportConnectionInfo()
{
  // Call the base constructor.
  Transport.ConnectionInfo .call(this);
};

MicroForwarderTransport.ConnectionInfo.prototype = new Transport.ConnectionInfo();
MicroForwarderTransport.ConnectionInfo.prototype.name = "MicroForwarderTransport.ConnectionInfo";

/**
 * Check if the fields of this MicroForwarderTransport.ConnectionInfo equal the other
 * MicroForwarderTransport.ConnectionInfo.
 * @param {MicroForwarderTransport.ConnectionInfo} The other object to check.
 * @return {boolean} True if the objects have equal fields, false if not.
 */
MicroForwarderTransport.ConnectionInfo.prototype.equals = function(other)
{
  if (other == null)
    return false;
  return true;
};

MicroForwarderTransport.ConnectionInfo.prototype.toString = function()
{
  return "{}";
};

/**
 * Set the onReceivedObject callback, replacing any previous callback.
 * @param {function} onReceivedObject (optional) If supplied and the received
 * object type field is not "Buffer" then just call this.onReceivedObject(obj).
 * If this is null, then don't call it.
 */
MicroForwarderTransport.prototype.setOnReceivedObject = function(onReceivedObject)
{
  this.onReceivedObject = onReceivedObject;
}

/**
 * Determine whether this transport connecting according to connectionInfo is to
 * a node on the current machine. Unix transports are always local.
 * @param {MicroForwarderTransport.ConnectionInfo} connectionInfo This is ignored.
 * @param {function} onResult This calls onResult(true) because micro forwarder
 * transports are always local.
 * @param {function} onError This is ignored.
 */
MicroForwarderTransport.prototype.isLocal = function(connectionInfo, onResult, onError)
{
  onResult(true);
};

/**
 * Connect to the micro forwarder according to the info in connectionInfo.
 * Listen on the connection to read an entire packet element and call
 * elementListener.onReceivedElement(element). However, if the received object
 * type field is not "Buffer" then just call this.onReceivedObject(obj).
 * @param {MicroForwarderTransport.ConnectionInfo} connectionInfo
 * @param {object} elementListener The elementListener with function
 * onReceivedElement which must remain valid during the life of this object.
 * @param {function} onopenCallback Once connected, call onopenCallback().
 * @param {function} onclosedCallback (optional) If the connection is closed by
 * the remote host, call onclosedCallback(). If omitted or null, don't call it.
 */
MicroForwarderTransport.prototype.connect = function
  (connectionInfo, elementListener, onopenCallback, onclosedCallback)
{
  // The window listener is already set up.
  this.elementReader = new ElementReader(elementListener);
  this.connectionInfo = connectionInfo;
  onopenCallback();
};

/**
 * Send the JavaScript over the connection created by connect.
 * @param {object} obj The object to send. It should have a field "type". If
 * "type" is "Buffer" then it is processed like an NDN packet.
 */
MicroForwarderTransport.prototype.sendObject = function(obj)
{
  window.postMessage({
    type: "FromMicroForwarderTransport",
    object: obj
  }, "*");
};

/**
 * Send the buffer over the connection created by connect.
 * @param {Buffer} buffer The bytes to send.
 */
MicroForwarderTransport.prototype.send = function(buffer)
{
  if (this.connectionInfo == null) {
    console.log("MicroForwarderTransport connection is not established.");
    return;
  }

  this.sendObject(buffer.toJSON());
};
/**
 * Copyright (C) 2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * @author: Wentao Shang
 *
 * 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.
 */

/**
 * A RuntimePortTransport extends Transport to connect to a WebExtensions
 * runtime.port.
 * @param {function} onReceivedObject (optional) If supplied and the received
 * object type field is not "Buffer" then just call this.onReceivedObject(obj).
 * If this is null, then don't call it.
 * @constructor
 */
var RuntimePortTransport = function RuntimePortTransport(onReceivedObject)
{
  // Call the base constructor.
  Transport.call(this);

  this.elementReader = null;
  this.connectionInfo = null; // Read by Face.
  this.onReceivedObject = onReceivedObject;
  this.port = null;
};

RuntimePortTransport.prototype = new Transport();
RuntimePortTransport.prototype.name = "RuntimePortTransport";

/**
 * Create a new RuntimePortTransport.ConnectionInfo which extends
 * Transport.ConnectionInfo to hold the runtime.port used to connect.
 * @param {runtime.port} port The runtime.port object.
 */
RuntimePortTransport.ConnectionInfo = function RuntimePortTransportConnectionInfo
  (port)
{
  // Call the base constructor.
  Transport.ConnectionInfo .call(this);

  this.port = port;
};

RuntimePortTransport.ConnectionInfo.prototype = new Transport.ConnectionInfo();
RuntimePortTransport.ConnectionInfo.prototype.name = "RuntimePortTransport.ConnectionInfo";

/**
 * Check if the fields of this RuntimePortTransport.ConnectionInfo equal the other
 * RuntimePortTransport.ConnectionInfo.
 * @param {RuntimePortTransport.ConnectionInfo} The other object to check.
 * @return {boolean} True if the objects have equal fields, false if not.
 */
RuntimePortTransport.ConnectionInfo.prototype.equals = function(other)
{
  if (other == null || other.port == undefined)
    return false;
  return this.port == other.port;
};

RuntimePortTransport.ConnectionInfo.prototype.toString = function()
{
  return "{}";
};

/**
 * Set the onReceivedObject callback, replacing any previous callback.
 * @param {function} onReceivedObject (optional) If supplied and the received
 * object type field is not "Buffer" then just call this.onReceivedObject(obj).
 * If this is null, then don't call it.
 */
RuntimePortTransport.prototype.setOnReceivedObject = function(onReceivedObject)
{
  this.onReceivedObject = onReceivedObject;
}

/**
 * Determine whether this transport connecting according to connectionInfo is to
 * a node on the current machine. RuntimePortTransport is always local.
 * @param {RuntimePortTransport.ConnectionInfo} connectionInfo This is ignored.
 * @param {function} onResult This calls onResult(true) because a runtime.port
 * is always local.
 * @param {function} onError This is ignored.
 */
RuntimePortTransport.prototype.isLocal = function(connectionInfo, onResult, onError)
{
  onResult(true);
};

/**
 * Connect to the runtime.port in connectionInfo. For a received object obj, if
 * obj.type is "Buffer", read an entire packet element from obj.data and call
 * elementListener.onReceivedElement(element). Otherwise just call
 * onReceivedObject(obj) using the callback given to the constructor.
 * @param {RuntimePortTransport.ConnectionInfo} connectionInfo The
 * ConnectionInfo with the runtime.port.
 * @param {object} elementListener The elementListener with function
 * onReceivedElement which must remain valid during the life of this object.
 * @param {function} onOpenCallback Once connected, call onOpenCallback().
 * @param {function} onClosedCallback (optional) If the connection is closed by
 * the remote host, call onClosedCallback(). If omitted or null, don't call it.
 */
RuntimePortTransport.prototype.connect = function
  (connectionInfo, elementListener, onOpenCallback, onClosedCallback)
{
  // The window listener is already set up.
  this.elementReader = new ElementReader(elementListener);
  this.connectionInfo = connectionInfo;
  this.port = this.connectionInfo.port;

  // Add a listener to wait for a message object from the tab
  var thisTransport = this;
  this.port.onMessage.addListener(function(obj) {
    if (obj.type == "Buffer")
      thisTransport.elementReader.onReceivedData
        (Buffer.isBuffer(obj.data) ? obj.data : new Buffer(obj.data));
    else {
      if (thisTransport.onReceivedObject != null)
        thisTransport.onReceivedObject(obj);
    }
  });

  this.port.onDisconnect.addListener(function() {
    thisTransport.port = null;
    if (onClosedCallback != null)
      onClosedCallback();
  });

  onOpenCallback();
};

/**
 * Send the JavaScript object over the connection created by connect.
 * @param {object} obj The object to send. If it is a JSON Buffer then it is
 * processed like an NDN packet.
 */
RuntimePortTransport.prototype.sendObject = function(obj)
{
  if (this.port == null) {
    console.log("RuntimePortTransport connection is not established.");
    return;
  }

  this.port.postMessage(obj);
};

/**
 * Send the buffer over the connection created by connect.
 * @param {Buffer} buffer The bytes to send.
 */
RuntimePortTransport.prototype.send = function(buffer)
{
  this.sendObject(buffer.toJSON());
};
/**
 * Copyright (C) 2013-2016 Regents of the University of California.
 * @author: Wentao Shang
 *
 * 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.
 */

/** @ignore */
var ElementReader = require('../encoding/element-reader.js').ElementReader; /** @ignore */
var LOG = require('../log.js').Log.LOG; /** @ignore */
var Transport = require('./transport.js').Transport; /** @ignore */
var Face;

/**
 * @constructor
 */
var WebSocketTransport = function WebSocketTransport()
{
  // Call the base constructor.
  Transport.call(this);

  if (!WebSocket)
    throw new Error("WebSocket support is not available on this platform.");

  this.ws = null;
  this.connectionInfo = null; // Read by Face.
  this.elementReader = null;
  this.defaultGetConnectionInfo = Face.makeShuffledHostGetConnectionInfo
    (["A.ws.ndn.ucla.edu", "B.ws.ndn.ucla.edu", "C.ws.ndn.ucla.edu", "D.ws.ndn.ucla.edu",
      "E.ws.ndn.ucla.edu", "F.ws.ndn.ucla.edu", "G.ws.ndn.ucla.edu", "H.ws.ndn.ucla.edu",
      "I.ws.ndn.ucla.edu", "J.ws.ndn.ucla.edu", "K.ws.ndn.ucla.edu", "L.ws.ndn.ucla.edu",
      "M.ws.ndn.ucla.edu", "N.ws.ndn.ucla.edu"],
     9696,
     function(host, port) { return new WebSocketTransport.ConnectionInfo(host, port); });
};

WebSocketTransport.prototype = new Transport();
WebSocketTransport.prototype.name = "WebSocketTransport";

WebSocketTransport.importFace = function(face){
  Face = face;
};

exports.WebSocketTransport = WebSocketTransport;

/**
 * Create a new WebSocketTransport.ConnectionInfo which extends
 * Transport.ConnectionInfo to hold the host and port info for the WebSocket
 * connection.
 * @param {string} host The host for the connection. However, if the host string
 * begins with "ws:" or "wss:", then ignore port and use the string as the full
 * endpoint URI.
 * @param {number} port (optional) The port number for the connection. If
 * omitted, use 9696.
 */
WebSocketTransport.ConnectionInfo = function WebSocketTransportConnectionInfo
  (host, port)
{
  // Call the base constructor.
  Transport.ConnectionInfo .call(this);

  port = (port !== undefined ? port : 9696);

  this.host = host;
  this.port = port;
};

WebSocketTransport.ConnectionInfo.prototype = new Transport.ConnectionInfo();
WebSocketTransport.ConnectionInfo.prototype.name = "WebSocketTransport.ConnectionInfo";

/**
 * Check if the fields of this WebSocketTransport.ConnectionInfo equal the other
 * WebSocketTransport.ConnectionInfo.
 * @param {WebSocketTransport.ConnectionInfo} The other object to check.
 * @return {boolean} True if the objects have equal fields, false if not.
 */
WebSocketTransport.ConnectionInfo.prototype.equals = function(other)
{
  if (other == null || other.host == undefined || other.port == undefined)
    return false;
  return this.host == other.host && this.port == other.port;
};

WebSocketTransport.ConnectionInfo.prototype.toString = function()
{
  if (this.hostIsUri())
    return "{ uri: " + this.host + " }";
  else
    return "{ host: " + this.host + ", port: " + this.port + " }";
};

WebSocketTransport.ConnectionInfo.prototype.hostIsUri = function()
{
  return this.host.substr(0, 3) == "ws:" ||
         this.host.substr(0, 4) == "wss:";
}

/**
 * Determine whether this transport connecting according to connectionInfo is to
 * a node on the current machine. WebSocket transports are always non-local.
 * @param {WebSocketTransport.ConnectionInfo} connectionInfo This is ignored.
 * @param {function} onResult This calls onResult(false) because WebSocket
 * transports are always non-local.
 * @param {function} onError This is ignored.
 */
WebSocketTransport.prototype.isLocal = function(connectionInfo, onResult, onError)
{
  onResult(false);
};

/**
 * Connect to a WebSocket according to the info in connectionInfo. Listen on
 * the port to read an entire packet element and call
 * elementListener.onReceivedElement(element). Note: this connect method
 * previously took a Face object which is deprecated and renamed as the method
 * connectByFace.
 * @param {WebSocketTransport.ConnectionInfo} connectionInfo A
 * WebSocketTransport.ConnectionInfo.
 * @param {object} elementListener The elementListener with function
 * onReceivedElement which must remain valid during the life of this object.
 * @param {function} onopenCallback Once connected, call onopenCallback().
 * @param {function} onclosedCallback (optional) If the connection is closed by
 * the remote host, call onclosedCallback(). If omitted or null, don't call it.
 */
WebSocketTransport.prototype.connect = function
  (connectionInfo, elementListener, onopenCallback, onclosedCallback)
{
  this.close();

  var uri = connectionInfo.hostIsUri() ?
    connectionInfo.host : 'ws://' + connectionInfo.host + ':' + connectionInfo.port;
  this.ws = new WebSocket(uri);
  if (LOG > 0) console.log('ws connection created.');
    this.connectionInfo = connectionInfo;

  this.ws.binaryType = "arraybuffer";

  this.elementReader = new ElementReader(elementListener);
  var self = this;
  this.ws.onmessage = function(ev) {
    var result = ev.data;
    //console.log('RecvHandle called.');

    if (result == null || result == undefined || result == "") {
      console.log('INVALID ANSWER');
    }
    else if (result instanceof ArrayBuffer) {
      // The Buffer constructor expects an instantiated array.
      var bytearray = new Buffer(new Uint8Array(result));

      if (LOG > 3) console.log('BINARY RESPONSE IS ' + bytearray.toString('hex'));

      try {
        // Find the end of the element and call onReceivedElement.
        self.elementReader.onReceivedData(bytearray);
      } catch (ex) {
        console.log("NDN.ws.onmessage exception: " + ex);
        return;
      }
    }
  }

  this.ws.onopen = function(ev) {
    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);
    // Face.registerPrefix will fetch the ndndid when needed.

    onopenCallback();
  }

  this.ws.onerror = function(ev) {
    console.log('ws.onerror: ReadyState: ' + this.readyState);
    console.log(ev);
    console.log('ws.onerror: WebSocket error: ' + ev.data);
  }

  this.ws.onclose = function(ev) {
    console.log('ws.onclose: WebSocket connection closed.');
    self.ws = null;

    if (onclosedCallback != null)
      onclosedCallback();
  }
};

/**
 * @deprecated This is deprecated. You should not call Transport.connect
 * directly, since it is called by Face methods.
 */
WebSocketTransport.prototype.connectByFace = function(face, onopenCallback)
{
  this.connect
    (face.connectionInfo, face, onopenCallback,
     function() { face.closeByTransport(); });
};

/**
 * Send the Uint8Array data.
 */
WebSocketTransport.prototype.send = function(data)
{
  if (this.ws != null) {
    // If we directly use data.buffer to feed ws.send(),
    // WebSocket may end up sending a packet with 10000 bytes of data.
    // That is, WebSocket will flush the entire buffer
    // 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 binaryInterest to the new buffer.
    //    ---Wentao
    var bytearray = new Uint8Array(data.length);
    bytearray.set(data);
    this.ws.send(bytearray.buffer);
    if (LOG > 3) console.log('ws.send() returned.');
  }
  else
    console.log('WebSocket connection is not established.');
};

/**
 * Close the connection.
 */
WebSocketTransport.prototype.close = function()
{
  if (this.ws != null)
    delete this.ws;
}

/**
 * Copyright (C) 2013-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

// The Face constructor uses TcpTransport by default which is not available in the browser, so override to WebSocketTransport.
exports.TcpTransport = require("./transport/web-socket-transport").WebSocketTransport;
/**
 * This class represents a Name as an array of components where each is a byte array.
 * Copyright (C) 2013-2016 Regents of the University of California.
 * @author: Meki Cheraoui, Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var Blob = require('./util/blob.js').Blob; /** @ignore */
var DataUtils = require('./encoding/data-utils.js').DataUtils; /** @ignore */
var LOG = require('./log.js').Log.LOG;
var DecodingException = require('./encoding/decoding-exception.js').DecodingException;

/**
 * Create a new Name from components.
 *
 * @constructor
 * @param {string|Name|Array<string|Array<number>|ArrayBuffer|Buffer|Name>} components if a string, parse it as a URI.  If a Name, add a deep copy of its components.
 * Otherwise it is an array of components which are appended according to Name.append, so
 * convert each and store it as an array of Buffer.  If a component is a string, encode as utf8.
 */
var Name = function Name(components)
{
  if (typeof components == 'string') {
    if (LOG > 3) console.log('Content Name String ' + components);
    this.components = Name.createNameArray(components);
  }
  else if (typeof components === 'object') {
    this.components = [];
    if (components instanceof Name)
      this.append(components);
    else {
      for (var i = 0; i < components.length; ++i)
        this.append(components[i]);
    }
  }
  else if (components == null)
    this.components = [];
  else
    if (LOG > 1) console.log("NO CONTENT NAME GIVEN");

  this.changeCount = 0;
};

exports.Name = Name;

/**
 * Create a new GENERIC Name.Component with a copy of the given value.
 * (To create an ImplicitSha256Digest component, use fromImplicitSha256Digest.)
 * @param {Name.Component|String|Array<number>|ArrayBuffer|Buffer} value If the value is a string, encode it as utf8 (but don't unescape).
 * @constructor
 */
Name.Component = function NameComponent(value)
{
  if (typeof value === 'object' && value instanceof Name.Component) {
    // The copy constructor.
    this.value_ = value.value_;
    this.type_ = value.type_;
    return;
  }

  if (!value)
    this.value_ = new Blob([]);
  else if (typeof value === 'object' && typeof ArrayBuffer !== 'undefined' &&
           value instanceof ArrayBuffer)
    // Make a copy.  Turn the value into a Uint8Array since the Buffer
    //   constructor doesn't take an ArrayBuffer.
    this.value_ = new Blob(new Buffer(new Uint8Array(value)), false);
  else if (typeof value === 'object' && value instanceof Blob)
    this.value_ = value;
  else
    // Blob will make a copy if needed.
    this.value_ = new Blob(value);

  this.type_ = Name.Component.ComponentType.GENERIC;
};

/**
 * A Name.Component.ComponentType specifies the recognized types of a name
 * component.
 */
Name.Component.ComponentType = {
  IMPLICIT_SHA256_DIGEST: 1,
  GENERIC: 8
};

/**
 * Get the component value.
 * @return {Blob} The component value.
 */
Name.Component.prototype.getValue = function()
{
  return this.value_;
};

/**
 * @deprecated Use getValue. This method returns a Buffer which is the former
 * behavior of getValue, and should only be used while updating your code.
 */
Name.Component.prototype.getValueAsBuffer = function()
{
  // Assume the caller won't modify it.
  return this.value_.buf();
};

/**
 * @deprecated Use getValue which returns a Blob.
 */
Object.defineProperty(Name.Component.prototype, "value",
  { get: function() { return this.getValueAsBuffer(); } });

/**
 * Convert this component value to a string by escaping characters according to the NDN URI Scheme.
 * This also adds "..." to a value with zero or more ".".
 * This adds a type code prefix as needed, such as "sha256digest=".
 * @return {string} The escaped string.
 */
Name.Component.prototype.toEscapedString = function()
{
  if (this.type_ === Name.Component.ComponentType.IMPLICIT_SHA256_DIGEST)
    return "sha256digest=" + this.value_.toHex();
  else
    return Name.toEscapedString(this.value_.buf());
};

/**
 * Check if this component is a segment number according to NDN naming
 * conventions for "Segment number" (marker 0x00).
 * http://named-data.net/doc/tech-memos/naming-conventions.pdf
 * @return {number}  True if this is a segment number.
 */
Name.Component.prototype.isSegment = function()
{
  return this.value_.size() >= 1 && this.value_.buf()[0] == 0x00 &&
         this.isGeneric();
};

/**
 * Check if this component is a segment byte offset according to NDN
 * naming conventions for segment "Byte offset" (marker 0xFB).
 * http://named-data.net/doc/tech-memos/naming-conventions.pdf
 * @return  True if this is a segment byte offset.
 */
Name.Component.prototype.isSegmentOffset = function()
{
  return this.value_.size() >= 1 && this.value_.buf()[0] == 0xFB &&
         this.isGeneric();
};

/**
 * Check if this component is a version number  according to NDN naming
 * conventions for "Versioning" (marker 0xFD).
 * http://named-data.net/doc/tech-memos/naming-conventions.pdf
 * @return {number}  True if this is a version number.
 */
Name.Component.prototype.isVersion = function()
{
  return this.value_.size() >= 1 && this.value_.buf()[0] == 0xFD &&
         this.isGeneric();
};

/**
 * Check if this component is a timestamp  according to NDN naming
 * conventions for "Timestamp" (marker 0xFC).
 * http://named-data.net/doc/tech-memos/naming-conventions.pdf
 * @return  True if this is a timestamp.
 */
Name.Component.prototype.isTimestamp = function()
{
  return this.value_.size() >= 1 && this.value_.buf()[0] == 0xFC &&
         this.isGeneric();
};

/**
 * Check if this component is a sequence number according to NDN naming
 * conventions for "Sequencing" (marker 0xFE).
 * http://named-data.net/doc/tech-memos/naming-conventions.pdf
 * @return  True if this is a sequence number.
 */
Name.Component.prototype.isSequenceNumber = function()
{
  return this.value_.size() >= 1 && this.value_.buf()[0] == 0xFE &&
         this.isGeneric();
};

/**
 * Check if this component is a generic component.
 * @return {boolean} True if this is an generic component.
 */
Name.Component.prototype.isGeneric = function()
{
  return this.type_ === Name.Component.ComponentType.GENERIC;
};

/**
 * Check if this component is an ImplicitSha256Digest component.
 * @return {boolean} True if this is an ImplicitSha256Digest component.
 */
Name.Component.prototype.isImplicitSha256Digest = function()
{
  return this.type_ === Name.Component.ComponentType.IMPLICIT_SHA256_DIGEST;
};

/**
 * Interpret this name component as a network-ordered number and return an integer.
 * @return {number} The integer number.
 */
Name.Component.prototype.toNumber = function()
{
  return DataUtils.bigEndianToUnsignedInt(this.value_.buf());
};

/**
 * Interpret this name component as a network-ordered number with a marker and
 * return an integer.
 * @param {number} marker The required first byte of the component.
 * @return {number} The integer number.
 * @throws Error If the first byte of the component does not equal the marker.
 */
Name.Component.prototype.toNumberWithMarker = function(marker)
{
  if (this.value_.size() == 0 || this.value_.buf()[0] != marker)
    throw new Error("Name component does not begin with the expected marker");

  return DataUtils.bigEndianToUnsignedInt(this.value_.buf().slice(1));
};

/**
 * Interpret this name component as a segment number according to NDN naming
 * conventions for "Segment number" (marker 0x00).
 * http://named-data.net/doc/tech-memos/naming-conventions.pdf
 * @return {number} The integer segment number.
 * @throws Error If the first byte of the component is not the expected marker.
 */
Name.Component.prototype.toSegment = function()
{
  return this.toNumberWithMarker(0x00);
};

/**
 * Interpret this name component as a segment byte offset according to NDN
 * naming conventions for segment "Byte offset" (marker 0xFB).
 * http://named-data.net/doc/tech-memos/naming-conventions.pdf
 * @return The integer segment byte offset.
 * @throws Error If the first byte of the component is not the expected marker.
 */
Name.Component.prototype.toSegmentOffset = function()
{
  return this.toNumberWithMarker(0xFB);
};

/**
 * Interpret this name component as a version number  according to NDN naming
 * conventions for "Versioning" (marker 0xFD). Note that this returns
 * the exact number from the component without converting it to a time
 * representation.
 * @return {number} The integer version number.
 * @throws Error If the first byte of the component is not the expected marker.
 */
Name.Component.prototype.toVersion = function()
{
  return this.toNumberWithMarker(0xFD);
};

/**
 * Interpret this name component as a timestamp  according to NDN naming
 * conventions for "Timestamp" (marker 0xFC).
 * http://named-data.net/doc/tech-memos/naming-conventions.pdf
 * @return The number of microseconds since the UNIX epoch (Thursday,
 * 1 January 1970) not counting leap seconds.
 * @throws Error If the first byte of the component is not the expected marker.
 */
Name.Component.prototype.toTimestamp = function()
{
  return this.toNumberWithMarker(0xFC);
};

/**
 * Interpret this name component as a sequence number according to NDN naming
 * conventions for "Sequencing" (marker 0xFE).
 * http://named-data.net/doc/tech-memos/naming-conventions.pdf
 * @return The integer sequence number.
 * @throws Error If the first byte of the component is not the expected marker.
 */
Name.Component.prototype.toSequenceNumber = function()
{
  return this.toNumberWithMarker(0xFE);
};

/**
 * Create a component whose value is the nonNegativeInteger encoding of the
 * number.
 * @param {number} number
 * @return {Name.Component}
 */
Name.Component.fromNumber = function(number)
{
  var encoder = new TlvEncoder(8);
  encoder.writeNonNegativeInteger(number);
  return new Name.Component(new Blob(encoder.getOutput(), false));
};

/**
 * Create a component whose value is the marker appended with the
 * nonNegativeInteger encoding of the number.
 * @param {number} number
 * @param {number} marker
 * @return {Name.Component}
 */
Name.Component.fromNumberWithMarker = function(number, marker)
{
  var encoder = new TlvEncoder(9);
  // Encode backwards.
  encoder.writeNonNegativeInteger(number);
  encoder.writeNonNegativeInteger(marker);
  return new Name.Component(new Blob(encoder.getOutput(), false));
};

/**
 * Create a component with the encoded segment number according to NDN
 * naming conventions for "Segment number" (marker 0x00).
 * http://named-data.net/doc/tech-memos/naming-conventions.pdf
 * param {number} segment The segment number.
 * returns {Name.Component} The new Component.
 */
Name.Component.fromSegment = function(segment)
{
  return Name.Component.fromNumberWithMarker(segment, 0x00);
};

/**
 * Create a component with the encoded segment byte offset according to NDN
 * naming conventions for segment "Byte offset" (marker 0xFB).
 * http://named-data.net/doc/tech-memos/naming-conventions.pdf
 * param {number} segmentOffset The segment byte offset.
 * returns {Name.Component} The new Component.
 */
Name.Component.fromSegmentOffset = function(segmentOffset)
{
  return Name.Component.fromNumberWithMarker(segmentOffset, 0xFB);
};

/**
 * Create a component with the encoded version number according to NDN
 * naming conventions for "Versioning" (marker 0xFD).
 * http://named-data.net/doc/tech-memos/naming-conventions.pdf
 * Note that this encodes the exact value of version without converting from a
 * time representation.
 * param {number} version The version number.
 * returns {Name.Component} The new Component.
 */
Name.Component.fromVersion = function(version)
{
  return Name.Component.fromNumberWithMarker(version, 0xFD);
};

/**
 * Create a component with the encoded timestamp according to NDN naming
 * conventions for "Timestamp" (marker 0xFC).
 * http://named-data.net/doc/tech-memos/naming-conventions.pdf
 * param {number} timestamp The number of microseconds since the UNIX epoch (Thursday,
 * 1 January 1970) not counting leap seconds.
 * returns {Name.Component} The new Component.
 */
Name.Component.fromTimestamp = function(timestamp)
{
  return Name.Component.fromNumberWithMarker(timestamp, 0xFC);
};

/**
 * Create a component with the encoded sequence number according to NDN naming
 * conventions for "Sequencing" (marker 0xFE).
 * http://named-data.net/doc/tech-memos/naming-conventions.pdf
 * param {number} sequenceNumber The sequence number.
 * returns {Name.Component} The new Component.
 */
Name.Component.fromSequenceNumber = function(sequenceNumber)
{
  return Name.Component.fromNumberWithMarker(sequenceNumber, 0xFE);
};

/**
 * Create a component of type ImplicitSha256DigestComponent, so that
 * isImplicitSha256Digest() is true.
 * @param {Blob|Buffer} digest The SHA-256 digest value.
 * @return {Name.Component} The new Component.
 * @throws DecodingException If the digest length is not 32 bytes.
 */
Name.Component.fromImplicitSha256Digest = function(digest)
{
  digestBlob = typeof digest === 'object' && digest instanceof Blob ?
    digest : new Blob(digest, true);
  if (digestBlob.size() !== 32)
    throw new DecodingException
      ("Name.Component.fromImplicitSha256Digest: The digest length must be 32 bytes");

  var result = new Name.Component(digestBlob);
  result.type_ = Name.Component.ComponentType.IMPLICIT_SHA256_DIGEST;
  return result;
};

/**
 * Get the successor of this component, as described in Name.getSuccessor.
 * @return {Name.Component} A new Name.Component which is the successor of this.
 */
Name.Component.prototype.getSuccessor = function()
{
  // Allocate an extra byte in case the result is larger.
  var result = new Buffer(this.value_.size() + 1);

  var carry = true;
  for (var i = this.value_.size() - 1; i >= 0; --i) {
    if (carry) {
      result[i] = (this.value_.buf()[i] + 1) & 0xff;
      carry = (result[i] === 0);
    }
    else
      result[i] = this.value_.buf()[i];
  }

  if (carry)
    // Assume all the bytes were set to zero (or the component was empty). In
    // NDN ordering, carry does not mean to prepend a 1, but to make a component
    // one byte longer of all zeros.
    result[result.length - 1] = 0;
  else
    // We didn't need the extra byte.
    result = result.slice(0, this.value_.size());

  return new Name.Component(new Blob(result, false));
};

/**
 * Check if this is the same component as other.
 * @param {Name.Component} other The other Component to compare with.
 * @return {Boolean} true if the components are equal, otherwise false.
 */
Name.Component.prototype.equals = function(other)
{
  return typeof other === 'object' && other instanceof Name.Component &&
    this.value_.equals(other.value_) && this.type_ === other.type_;
};

/**
 * Compare this to the other Component using NDN canonical ordering.
 * @param {Name.Component} other The other Component to compare with.
 * @return {number} 0 if they compare equal, -1 if this comes before other in
 * the canonical ordering, or 1 if this comes after other in the canonical
 * ordering.
 *
 * @see http://named-data.net/doc/0.2/technical/CanonicalOrder.html
 */
Name.Component.prototype.compare = function(other)
{
  if (this.type_ < other.type_)
    return -1;
  if (this.type_ > other.type_)
    return 1;

  return Name.Component.compareBuffers(this.value_.buf(), other.value_.buf());
};

/**
 * Do the work of Name.Component.compare to compare the component buffers.
 * @param {Buffer} component1
 * @param {Buffer} component2
 * @return {number} 0 if they compare equal, -1 if component1 comes before
 * component2 in the canonical ordering, or 1 if component1 comes after
 * component2 in the canonical ordering.
 */
Name.Component.compareBuffers = function(component1, component2)
{
  if (component1.length < component2.length)
    return -1;
  if (component1.length > component2.length)
    return 1;

  for (var i = 0; i < component1.length; ++i) {
    if (component1[i] < component2[i])
      return -1;
    if (component1[i] > component2[i])
      return 1;
  }

  return 0;
};

/**
 * @deprecated Use toUri.
 */
Name.prototype.getName = function()
{
  return this.toUri();
};

/** Parse uri as a URI and return an array of Buffer components.
 */
Name.createNameArray = function(uri)
{
  uri = uri.trim();
  if (uri.length <= 0)
    return [];

  var iColon = uri.indexOf(':');
  if (iColon >= 0) {
    // Make sure the colon came before a '/'.
    var iFirstSlash = uri.indexOf('/');
    if (iFirstSlash < 0 || iColon < iFirstSlash)
      // Omit the leading protocol such as ndn:
      uri = uri.substr(iColon + 1, uri.length - iColon - 1).trim();
  }

  if (uri[0] == '/') {
    if (uri.length >= 2 && uri[1] == '/') {
      // Strip the authority following "//".
      var iAfterAuthority = uri.indexOf('/', 2);
      if (iAfterAuthority < 0)
        // Unusual case: there was only an authority.
        return [];
      else
        uri = uri.substr(iAfterAuthority + 1, uri.length - iAfterAuthority - 1).trim();
    }
    else
      uri = uri.substr(1, uri.length - 1).trim();
  }

  var array = uri.split('/');

  // Unescape the components.
  var sha256digestPrefix = "sha256digest=";
  for (var i = 0; i < array.length; ++i) {
    var component;
    if (array[i].substr(0, sha256digestPrefix.length) == sha256digestPrefix) {
      var hexString = array[i].substr(sha256digestPrefix.length).trim();
      component = Name.Component.fromImplicitSha256Digest
        (new Blob(new Buffer(hexString, 'hex')), false);
    }
    else
      component = new Name.Component(Name.fromEscapedString(array[i]));

    if (component.getValue().isNull()) {
      // Ignore the illegal componenent.  This also gets rid of a trailing '/'.
      array.splice(i, 1);
      --i;
      continue;
    }
    else
      array[i] = component;
  }

  return array;
};

/**
 * Parse the uri according to the NDN URI Scheme and set the name with the
 * components.
 * @param {string} uri The URI string.
 */
Name.prototype.set = function(uri)
{
  this.components = Name.createNameArray(uri);
  ++this.changeCount;
};

/**
 * Convert the component to a Buffer and append a GENERIC component to this Name.
 * Return this Name object to allow chaining calls to add.
 * @param {Name.Component|String|Array<number>|ArrayBuffer|Buffer|Name} component If a component is a string, encode as utf8 (but don't unescape).
 * @return {Name}
 */
Name.prototype.append = function(component)
{
  if (typeof component == 'object' && component instanceof Name) {
    var components;
    if (component == this)
      // special case, when we need to create a copy
      components = this.components.slice(0, this.components.length);
    else
      components = component.components;

    for (var i = 0; i < components.length; ++i)
      this.components.push(new Name.Component(components[i]));
  }
  else if (typeof component === 'object' && component instanceof Name.Component)
    // The Component is immutable, so use it as is.
    this.components.push(component);
  else
    // Just use the Name.Component constructor.
    this.components.push(new Name.Component(component));

  ++this.changeCount;
  return this;
};

/**
 * @deprecated Use append.
 */
Name.prototype.add = function(component)
{
  return this.append(component);
};

/**
 * Clear all the components.
 */
Name.prototype.clear = function()
{
  this.components = [];
  ++this.changeCount;
};

/**
 * Return the escaped name string according to NDN URI Scheme.
 * @param {boolean} includeScheme (optional) If true, include the "ndn:" scheme
 * in the URI, e.g. "ndn:/example/name". If false, just return the path, e.g.
 * "/example/name". If ommitted, then just return the path which is the default
 * case where toUri() is used for display.
 * @return {String}
 */
Name.prototype.toUri = function(includeScheme)
{
  if (this.size() == 0)
    return includeScheme ? "ndn:/" : "/";

  var result = includeScheme ? "ndn:" : "";

  for (var i = 0; i < this.size(); ++i)
    result += "/"+ this.components[i].toEscapedString();

  return result;
};

/**
 * @deprecated Use toUri.
 */
Name.prototype.to_uri = function()
{
  return this.toUri();
};

Name.prototype.toString = function() { return this.toUri(); }

/**
 * Append a component with the encoded segment number according to NDN
 * naming conventions for "Segment number" (marker 0x00).
 * http://named-data.net/doc/tech-memos/naming-conventions.pdf
 * @param {number} segment The segment number.
 * @return {Name} This name so that you can chain calls to append.
 */
Name.prototype.appendSegment = function(segment)
{
  return this.append(Name.Component.fromSegment(segment));
};

/**
 * Append a component with the encoded segment byte offset according to NDN
 * naming conventions for segment "Byte offset" (marker 0xFB).
 * http://named-data.net/doc/tech-memos/naming-conventions.pdf
 * @param {number} segmentOffset The segment byte offset.
 * @return {Name} This name so that you can chain calls to append.
 */
Name.prototype.appendSegmentOffset = function(segmentOffset)
{
  return this.append(Name.Component.fromSegmentOffset(segmentOffset));
};

/**
 * Append a component with the encoded version number according to NDN
 * naming conventions for "Versioning" (marker 0xFD).
 * http://named-data.net/doc/tech-memos/naming-conventions.pdf
 * Note that this encodes the exact value of version without converting from a time representation.
 * @param {number} version The version number.
 * @return {Name} This name so that you can chain calls to append.
 */
Name.prototype.appendVersion = function(version)
{
  return this.append(Name.Component.fromVersion(version));
};

/**
 * Append a component with the encoded timestamp according to NDN naming
 * conventions for "Timestamp" (marker 0xFC).
 * http://named-data.net/doc/tech-memos/naming-conventions.pdf
 * @param {number} timestamp The number of microseconds since the UNIX epoch (Thursday,
 * 1 January 1970) not counting leap seconds.
 * @return This name so that you can chain calls to append.
 */
Name.prototype.appendTimestamp = function(timestamp)
{
  return this.append(Name.Component.fromTimestamp(timestamp));
};

/**
 * Append a component with the encoded sequence number according to NDN naming
 * conventions for "Sequencing" (marker 0xFE).
 * http://named-data.net/doc/tech-memos/naming-conventions.pdf
 * @param {number} sequenceNumber The sequence number.
 * @return This name so that you can chain calls to append.
 */
Name.prototype.appendSequenceNumber = function(sequenceNumber)
{
  return this.append(Name.Component.fromSequenceNumber(sequenceNumber));
};

/**
 * Append a component of type ImplicitSha256DigestComponent, so that
 * isImplicitSha256Digest() is true.
 * @param {Blob|Buffer} digest The SHA-256 digest value.
 * @return This name so that you can chain calls to append.
 * @throws DecodingException If the digest length is not 32 bytes.
 */
Name.prototype.appendImplicitSha256Digest = function(digest)
{
  return this.append(Name.Component.fromImplicitSha256Digest(digest));
};

/**
 * @deprecated Use appendSegment.
 */
Name.prototype.addSegment = function(number)
{
  return this.appendSegment(number);
};

/**
 * Get a new name, constructed as a subset of components.
 * @param {number} iStartComponent The index if the first component to get. If
 * iStartComponent is -N then return return components starting from
 * name.size() - N.
 * @param {number} (optional) nComponents The number of components starting at
 * iStartComponent. If omitted or greater than the size of this name, get until
 * the end of the name.
 * @return {Name} A new name.
 */
Name.prototype.getSubName = function(iStartComponent, nComponents)
{
  if (iStartComponent < 0)
    iStartComponent = this.components.length - (-iStartComponent);

  if (nComponents == undefined)
    nComponents = this.components.length - iStartComponent;

  var result = new Name();

  var iEnd = iStartComponent + nComponents;
  for (var i = iStartComponent; i < iEnd && i < this.components.length; ++i)
    result.components.push(this.components[i]);

  return result;
};

/**
 * Return a new Name with the first nComponents components of this Name.
 * @param {number} nComponents The number of prefix components.  If nComponents is -N then return the prefix up
 * to name.size() - N. For example getPrefix(-1) returns the name without the final component.
 * @return {Name} A new name.
 */
Name.prototype.getPrefix = function(nComponents)
{
  if (nComponents < 0)
    return this.getSubName(0, this.components.length + nComponents);
  else
    return this.getSubName(0, nComponents);
};

/**
 * @deprecated Use getPrefix(-nComponents).
 */
Name.prototype.cut = function(nComponents)
{
  return new Name(this.components.slice(0, this.components.length - nComponents));
};

/**
 * Return the number of name components.
 * @return {number}
 */
Name.prototype.size = function()
{
  return this.components.length;
};

/**
 * Get a Name Component by index number.
 * @param {Number} i The index of the component, starting from 0.  However, if i is negative, return the component
 * at size() - (-i).
 * @return {Name.Component} The name component at the index. You must not
 * change the returned Name.Component object.
 */
Name.prototype.get = function(i)
{
  if (i >= 0) {
    if (i >= this.components.length)
      throw new Error("Name.get: Index is out of bounds");

    return this.components[i];
  }
  else {
    // Negative index.
    if (i < -this.components.length)
      throw new Error("Name.get: Index is out of bounds");

    return this.components[this.components.length - (-i)];
  }
};

/**
 * @deprecated Use size().
 */
Name.prototype.getComponentCount = function()
{
  return this.components.length;
};

/**
 * @deprecated To get just the component value array, use get(i).getValue().buf().
 */
Name.prototype.getComponent = function(i)
{
  return new Buffer(this.components[i].getValue().buf());
};

/**
 * The "file name" in a name is the last component that isn't blank and doesn't start with one of the
 *   special marker octets (for version, etc.).  Return the index in this.components of
 *   the file name, or -1 if not found.
 */
Name.prototype.indexOfFileName = function()
{
  for (var i = this.size() - 1; i >= 0; --i) {
    var component = this.components[i].getValue().buf();
    if (component.length <= 0)
      continue;

    if (component[0] == 0 || component[0] == 0xC0 || component[0] == 0xC1 ||
        (component[0] >= 0xF5 && component[0] <= 0xFF))
      continue;

    return i;
  }

  return -1;
};

/**
 * Encode this Name for a particular wire format.
 * @param {WireFormat} wireFormat (optional) A WireFormat object  used to encode
 * this object. If omitted, use WireFormat.getDefaultWireFormat().
 * @return {Blob} The encoded buffer in a Blob object.
 */
Name.prototype.wireEncode = function(wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
  return wireFormat.encodeName(this);
};

/**
 * Decode the input using a particular wire format and update this Name.
 * @param {Blob|Buffer} input The buffer with the bytes to decode.
 * @param {WireFormat} wireFormat (optional) A WireFormat object used to decode
 * this object. If omitted, use WireFormat.getDefaultWireFormat().
 */
Name.prototype.wireDecode = function(input, wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
  if (typeof input === 'object' && input instanceof Blob)
    // Input is a blob, so get its buf() and set copy false.
    wireFormat.decodeName(this, input.buf(), false);
  else
    wireFormat.decodeName(this, input, true);
};

/**
 * Compare this to the other Name using NDN canonical ordering.  If the first
 * components of each name are not equal, this returns -1 if the first comes
 * before the second using the NDN canonical ordering for name components, or 1
 * if it comes after. If they are equal, this compares the second components of
 * each name, etc.  If both names are the same up to the size of the shorter
 * name, this returns -1 if the first name is shorter than the second or 1 if it
 * is longer. For example, std::sort gives: /a/b/d /a/b/cc /c /c/a /bb .  This
 * is intuitive because all names with the prefix /a are next to each other.
 * But it may be also be counter-intuitive because /c comes before /bb according
 * to NDN canonical ordering since it is shorter.
 * The first form of compare is simply compare(other). The second form is
 * compare(iStartComponent, nComponents, other [, iOtherStartComponent] [, nOtherComponents])
 * which is equivalent to
 * self.getSubName(iStartComponent, nComponents).compare
 * (other.getSubName(iOtherStartComponent, nOtherComponents)) .
 * @param {number} iStartComponent The index if the first component of this name
 * to get. If iStartComponent is -N then compare components starting from
 * name.size() - N.
 * @param {number} nComponents The number of components starting at
 * iStartComponent. If greater than the size of this name, compare until the end
 * of the name.
 * @param {Name} other The other Name to compare with.
 * @param {number} iOtherStartComponent (optional) The index if the first
 * component of the other name to compare. If iOtherStartComponent is -N then
 * compare components starting from other.size() - N. If omitted, compare
 * starting from index 0.
 * @param {number} nOtherComponents (optional) The number of components
 * starting at iOtherStartComponent. If omitted or greater than the size of this
 * name, compare until the end of the name.
 * @return {number} 0 If they compare equal, -1 if self comes before other in
 * the canonical ordering, or 1 if self comes after other in the canonical
 * ordering.
 * @see http://named-data.net/doc/0.2/technical/CanonicalOrder.html
 */
Name.prototype.compare = function
  (iStartComponent, nComponents, other, iOtherStartComponent, nOtherComponents)
{
  if (iStartComponent instanceof Name) {
    // compare(other)
    other = iStartComponent;
    iStartComponent = 0;
    nComponents = this.size();
  }

  if (iOtherStartComponent == undefined)
    iOtherStartComponent = 0;
  if (nOtherComponents == undefined)
    nOtherComponents = other.size();

  if (iStartComponent < 0)
    iStartComponent = this.size() - (-iStartComponent);
  if (iOtherStartComponent < 0)
    iOtherStartComponent = other.size() - (-iOtherStartComponent);

  nComponents = Math.min(nComponents, this.size() - iStartComponent);
  nOtherComponents = Math.min(nOtherComponents, other.size() - iOtherStartComponent);

  var count = Math.min(nComponents, nOtherComponents);
  for (var i = 0; i < count; ++i) {
    var comparison = this.components[iStartComponent + i].compare
      (other.components[iOtherStartComponent + i]);
    if (comparison == 0)
      // The components at this index are equal, so check the next components.
      continue;

    // Otherwise, the result is based on the components at this index.
    return comparison;
  }

  // The components up to min(this.size(), other.size()) are equal, so the
  // shorter name is less.
  if (nComponents < nOtherComponents)
    return -1;
  else if (nComponents > nOtherComponents)
    return 1;
  else
    return 0;
};

/**
 * Return true if this Name has the same components as name.
 */
Name.prototype.equals = function(name)
{
  if (this.components.length != name.components.length)
    return false;

  // Start from the last component because they are more likely to differ.
  for (var i = this.components.length - 1; i >= 0; --i) {
    if (!this.components[i].equals(name.components[i]))
      return false;
  }

  return true;
};

/**
 * @deprecated Use equals.
 */
Name.prototype.equalsName = function(name)
{
  return this.equals(name);
};

/**
 * Find the last component in name that has a ContentDigest and return the digest value as Buffer,
 *   or null if not found.  See Name.getComponentContentDigestValue.
 */
Name.prototype.getContentDigestValue = function()
{
  for (var i = this.size() - 1; i >= 0; --i) {
    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 Buffer slice (don't modify!).
 * If not a ContentDigest, return null.
 * A ContentDigest component is Name.ContentDigestPrefix + 32 bytes + Name.ContentDigestSuffix.
 */
Name.getComponentContentDigestValue = function(component)
{
  if (typeof component == 'object' && component instanceof Name.Component)
    component = component.getValue().buf();

  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.slice(0, Name.ContentDigestPrefix.length),
                            Name.ContentDigestPrefix) &&
      DataUtils.arraysEqual(component.slice
         (component.length - Name.ContentDigestSuffix.length, component.length),
                            Name.ContentDigestSuffix))
   return component.slice(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 Buffer([0xc1, 0x2e, 0x4d, 0x2e, 0x47, 0xc1, 0x01, 0xaa, 0x02, 0x85]);
Name.ContentDigestSuffix = new Buffer([0x00]);


/**
 * Return value as an escaped string according to NDN URI Scheme.
 * We can't use encodeURIComponent because that doesn't encode all the 
 * characters we want to.
 * This does not add a type code prefix such as "sha256digest=".
 * @param {Buffer|Name.Component} value The value or Name.Component to escape.
 * @return {string} The escaped string.
 */
Name.toEscapedString = function(value)
{
  if (typeof value == 'object' && value instanceof Name.Component)
    value = value.getValue().buf();
  else if (typeof value === 'object' && value instanceof Blob)
    value = value.buf();

  var result = "";
  var gotNonDot = false;
  for (var i = 0; i < value.length; ++i) {
    if (value[i] != 0x2e) {
      gotNonDot = true;
      break;
    }
  }
  if (!gotNonDot) {
    // Special case for component of zero or more periods.  Add 3 periods.
    result = "...";
    for (var i = 0; i < value.length; ++i)
      result += ".";
  }
  else {
    for (var i = 0; i < value.length; ++i) {
      var x = value[i];
      // Check for 0-9, A-Z, a-z, (+), (-), (.), (_)
      if (x >= 0x30 && x <= 0x39 || x >= 0x41 && x <= 0x5a ||
          x >= 0x61 && x <= 0x7a || x == 0x2b || x == 0x2d ||
          x == 0x2e || x == 0x5f)
        result += String.fromCharCode(x);
      else
        result += "%" + (x < 16 ? "0" : "") + x.toString(16).toUpperCase();
    }
  }
  return result;
};

/**
 * Make a blob value by decoding the escapedString according to NDN URI Scheme.
 * If escapedString is "", "." or ".." then return null, which means to skip the 
 * component in the name.
 * This does not check for a type code prefix such as "sha256digest=".
 * @param {string} escapedString The escaped string to decode.
 * @return {Blob} The unescaped Blob value. If the escapedString is not a valid
 * escaped component, then the Blob isNull().
 */
Name.fromEscapedString = function(escapedString)
{
  var value = unescape(escapedString.trim());

  if (value.match(/[^.]/) == null) {
    // Special case for value of only periods.
    if (value.length <= 2)
      // Zero, one or two periods is illegal.  Ignore this componenent to be
      //   consistent with the C implementation.
      return new Blob();
    else
      // Remove 3 periods.
      return new Blob
        (DataUtils.toNumbersFromString(value.substr(3, value.length - 3)), false);
  }
  else
    return new Blob(DataUtils.toNumbersFromString(value), false);
};

/**
 * @deprecated Use fromEscapedString. This method returns a Buffer which is the former
 * behavior of fromEscapedString, and should only be used while updating your code.
 */
Name.fromEscapedStringAsBuffer = function(escapedString)
{
  return Name.fromEscapedString(escapedString).buf();
};

/**
 * Get the successor of this name which is defined as follows.
 *
 *     N represents the set of NDN Names, and X,Y ∈ N.
 *     Operator < is defined by the NDN canonical order on N.
 *     Y is the successor of X, if (a) X < Y, and (b) ∄ Z ∈ N s.t. X < Z < Y.
 *
 * In plain words, the successor of a name is the same name, but with its last
 * component advanced to a next possible value.
 *
 * Examples:
 *
 * - The successor of / is /%00
 * - The successor of /%00%01/%01%02 is /%00%01/%01%03
 * - The successor of /%00%01/%01%FF is /%00%01/%02%00
 * - The successor of /%00%01/%FF%FF is /%00%01/%00%00%00
 *
 * @return {Name} A new name which is the successor of this.
 */
Name.prototype.getSuccessor = function()
{
  if (this.size() == 0) {
    // Return "/%00".
    var result = new Name();
    result.append(new Blob(new Buffer([0]), false));
    return result;
  }
  else
    return this.getPrefix(-1).append(this.get(-1).getSuccessor());
};

/**
 * Return true if the N components of this name are the same as the first N
 * components of the given name.
 * @param {Name} name The name to check.
 * @return {Boolean} true if this matches the given name. This always returns
 * true if this name is empty.
 */
Name.prototype.match = function(name)
{
  var i_name = this.components;
  var o_name = name.components;

  // This name is longer than the name we are checking it against.
  if (i_name.length > o_name.length)
    return false;

  // Check if at least one of given components doesn't match. Check from last to
  // first since the last components are more likely to differ.
  for (var i = i_name.length - 1; i >= 0; --i) {
    if (!i_name[i].equals(o_name[i]))
      return false;
  }

  return true;
};

/**
 * Return true if the N components of this name are the same as the first N
 * components of the given name.
 * @param {Name} name The name to check.
 * @return {Boolean} true if this matches the given name. This always returns
 * true if this name is empty.
 */
Name.prototype.isPrefixOf = function(name) { return this.match(name); }

/**
 * Get the change count, which is incremented each time this object is changed.
 * @return {number} The change count.
 */
Name.prototype.getChangeCount = function()
{
  return this.changeCount;
};

// Put these requires at the bottom to avoid circular references.
var TlvEncoder = require('./encoding/tlv/tlv-encoder.js').TlvEncoder;
var WireFormat = require('./encoding/wire-format.js').WireFormat;
/**
 * This class represents an NDN KeyLocator object.
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Meki Cheraoui
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var Blob = require('./util/blob.js').Blob; /** @ignore */
var ChangeCounter = require('./util/change-counter.js').ChangeCounter; /** @ignore */
var Name = require('./name.js').Name;

/**
 * KeyLocator
 */
var KeyLocatorType = {
  KEYNAME: 1,
  KEY_LOCATOR_DIGEST: 2
};

exports.KeyLocatorType = KeyLocatorType;

/**
 * @constructor
 */
var KeyLocator = function KeyLocator(input, type)
{
  if (typeof input === 'object' && input instanceof KeyLocator) {
    // Copy from the input KeyLocator.
    this.type_ = input.type_;
    this.keyName_ = new ChangeCounter(new Name(input.getKeyName()));
    this.keyData_ = input.keyData_;
  }
  else {
    this.type_ = type;
    this.keyName_ = new ChangeCounter(new Name());
    this.keyData_ = new Blob();

    if (type == KeyLocatorType.KEYNAME)
      this.keyName_.set(typeof input === 'object' && input instanceof Name ?
        new Name(input) : new Name());
    else if (type == KeyLocatorType.KEY_LOCATOR_DIGEST)
      this.keyData_ = new Blob(input);
  }

  this.changeCount_ = 0;
};

exports.KeyLocator = KeyLocator;

/**
 * Get the key locator type. If KeyLocatorType.KEYNAME, you may also
 * getKeyName().  If KeyLocatorType.KEY_LOCATOR_DIGEST, you may also
 * getKeyData() to get the digest.
 * @return {number} The key locator type as a KeyLocatorType enum value,
 * or null if not specified.
 */
KeyLocator.prototype.getType = function() { return this.type_; };

/**
 * Get the key name.  This is meaningful if getType() is KeyLocatorType.KEYNAME.
 * @return {Name} The key name. If not specified, the Name is empty.
 */
KeyLocator.prototype.getKeyName = function()
{
  return this.keyName_.get();
};

/**
 * Get the key data. If getType() is KeyLocatorType.KEY_LOCATOR_DIGEST, this is
 * the digest bytes.
 * @return {Blob} The key data, or an isNull Blob if not specified.
 */
KeyLocator.prototype.getKeyData = function()
{
  return this.keyData_;
};

/**
 * @deprecated Use getKeyData. This method returns a Buffer which is the former
 * behavior of getKeyData, and should only be used while updating your code.
 */
KeyLocator.prototype.getKeyDataAsBuffer = function()
{
  return this.getKeyData().buf();
};

/**
 * Set the key locator type.  If KeyLocatorType.KEYNAME, you must also
 * setKeyName().  If KeyLocatorType.KEY_LOCATOR_DIGEST, you must also
 * setKeyData() to the digest.
 * @param {number} type The key locator type as a KeyLocatorType enum value.  If
 * null, the type is unspecified.
 */
KeyLocator.prototype.setType = function(type)
{
  this.type_ = type;
  ++this.changeCount_;
};

/**
 * Set key name to a copy of the given Name.  This is the name if getType()
 * is KeyLocatorType.KEYNAME.
 * @param {Name} name The key name which is copied.
 */
KeyLocator.prototype.setKeyName = function(name)
{
  this.keyName_.set(typeof name === 'object' && name instanceof Name ?
    new Name(name) : new Name());
  ++this.changeCount_;
};

/**
 * Set the key data to the given value. This is the digest bytes if getType() is
 * KeyLocatorType.KEY_LOCATOR_DIGEST.
 * @param {Blob} keyData A Blob with the key data bytes.
 */
KeyLocator.prototype.setKeyData = function(keyData)
{
  this.keyData_ = typeof keyData === 'object' && keyData instanceof Blob ?
    keyData : new Blob(keyData);
  ++this.changeCount_;
};

/**
 * Clear the keyData and set the type to not specified.
 */
KeyLocator.prototype.clear = function()
{
  this.type_ = null;
  this.keyName_.set(new Name());
  this.keyData_ = new Blob();
  ++this.changeCount_;
};

/**
 * Check if this key locator has the same values as the given key locator.
 * @param {KeyLocator} other The other key locator to check.
 * @return {boolean} true if the key locators are equal, otherwise false.
 */
KeyLocator.prototype.equals = function(other)
{
    if (this.type_ != other.type_)
      return false;

    if (this.type_ == KeyLocatorType.KEYNAME) {
      if (!this.getKeyName().equals(other.getKeyName()))
        return false;
    }
    else if (this.type_ == KeyLocatorType.KEY_LOCATOR_DIGEST) {
      if (!this.getKeyData().equals(other.getKeyData()))
        return false;
    }

    return true;
};

/**
 * If the signature is a type that has a KeyLocator (so that,
 * getFromSignature will succeed), return true.
 * Note: This is a static method of KeyLocator instead of a method of
 * Signature so that the Signature base class does not need to be overloaded
 * with all the different kinds of information that various signature
 * algorithms may use.
 * @param {Signature} signature An object of a subclass of Signature.
 * @return {boolean} True if the signature is a type that has a KeyLocator,
 * otherwise false.
 */
KeyLocator.canGetFromSignature = function(signature)
{
  return signature instanceof Sha256WithRsaSignature ||
         signature instanceof Sha256WithEcdsaSignature ||
         signature instanceof HmacWithSha256Signature;
}

/**
 * If the signature is a type that has a KeyLocator, then return it. Otherwise
 * throw an error.
 * @param {Signature} signature An object of a subclass of Signature.
 * @return {KeyLocator} The signature's KeyLocator. It is an error if signature
 * doesn't have a KeyLocator.
 */
KeyLocator.getFromSignature = function(signature)
{
  if (signature instanceof Sha256WithRsaSignature ||
      signature instanceof Sha256WithEcdsaSignature ||
      signature instanceof HmacWithSha256Signature)
    return signature.getKeyLocator();
  else
    throw new Error
      ("KeyLocator.getFromSignature: Signature type does not have a KeyLocator");
}

/**
 * Get the change count, which is incremented each time this object (or a child
 * object) is changed.
 * @return {number} The change count.
 */
KeyLocator.prototype.getChangeCount = function()
{
  // Make sure each of the checkChanged is called.
  var changed = this.keyName_.checkChanged();
  if (changed)
    // A child object has changed, so update the change count.
    ++this.changeCount_;

  return this.changeCount_;
};

// Define properties so we can change member variable types and implement changeCount_.
Object.defineProperty(KeyLocator.prototype, "type",
  { get: function() { return this.getType(); },
    set: function(val) { this.setType(val); } });
/**
 * @@deprecated Use getKeyData and setKeyData.
 */
Object.defineProperty(KeyLocator.prototype, "keyData",
  { get: function() { return this.getKeyDataAsBuffer(); },
    set: function(val) { this.setKeyData(val); } });

// Put this last to avoid a require loop.
var Sha256WithRsaSignature = require('./sha256-with-rsa-signature.js').Sha256WithRsaSignature;
var Sha256WithEcdsaSignature = require('./sha256-with-ecdsa-signature.js').Sha256WithEcdsaSignature;
var HmacWithSha256Signature = require('./hmac-with-sha256-signature.js').HmacWithSha256Signature;
/**
 * This class represents an NDN Data MetaInfo object.
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Meki Cheraoui
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var Name = require('./name.js').Name;

/**
 * A ContentType specifies the content type in a MetaInfo object. If the
 * content type in the packet is not a recognized enum value, then we use
 * ContentType.OTHER_CODE and you can call MetaInfo.getOtherTypeCode(). We do
 * this to keep the recognized content type values independent of packet
 * encoding formats.
 */
var ContentType = {
  BLOB:0,
  LINK:1,
  KEY: 2,
  NACK:3,
  OTHER_CODE: 0x7fff
};

exports.ContentType = ContentType;

/**
 * Create a new MetaInfo with the optional values.
 * @constructor
 */
var MetaInfo = function MetaInfo(publisherOrMetaInfo, timestamp, type, locator, freshnessSeconds, finalBlockId)
{
  if (timestamp)
    throw new Error
      ("MetaInfo constructor: timestamp support has been removed.");
  if (locator)
    throw new Error
      ("MetaInfo constructor: locator support has been removed.");

  if (typeof publisherOrMetaInfo === 'object' &&
      publisherOrMetaInfo instanceof MetaInfo) {
    // Copy values.
    var metaInfo = publisherOrMetaInfo;
    this.publisher_ = metaInfo.publisher_;
    this.type_ = metaInfo.type_;
    this.otherTypeCode_ = metaInfo.otherTypeCode_;
    this.freshnessPeriod_ = metaInfo.freshnessPeriod_;
    this.finalBlockId_ = metaInfo.finalBlockId_;
  }
  else {
    if (publisherOrMetaInfo)
      throw new Error
        ("MetaInfo constructor: publisher support has been removed.");

    this.type = type == null || type < 0 ? ContentType.BLOB : type;
    this.otherTypeCode_ = -1;
    this.freshnessSeconds = freshnessSeconds; // deprecated
    this.finalBlockID = finalBlockId; // byte array // deprecated
  }

  this.changeCount_ = 0;
};

exports.MetaInfo = MetaInfo;

/**
 * Get the content type.
 * @return {number} The content type as an int from ContentType. If this is
 * ContentType.OTHER_CODE, then call getOtherTypeCode() to get the unrecognized
 * content type code.
 */
MetaInfo.prototype.getType = function()
{
  return this.type_;
};

/**
 * Get the content type code from the packet which is other than a recognized
 * ContentType enum value. This is only meaningful if getType() is
 * ContentType.OTHER_CODE.
 * @return {number} The type code.
 */
MetaInfo.prototype.getOtherTypeCode = function()
{
  return this.otherTypeCode_;
};

/**
 * Get the freshness period.
 * @return {number} The freshness period in milliseconds, or null if not
 * specified.
 */
MetaInfo.prototype.getFreshnessPeriod = function()
{
  return this.freshnessPeriod_;
};

/**
 * Get the final block ID.
 * @return {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. If the packet's content type is not a recognized
 * ContentType enum value, use ContentType.OTHER_CODE and call setOtherTypeCode().
 */
MetaInfo.prototype.setType = function(type)
{
  this.type_ = type == null || type < 0 ? ContentType.BLOB : type;
  ++this.changeCount_;
};

/**
 * Set the packet’s content type code to use when the content type enum is
 * ContentType.OTHER_CODE. If the packet’s content type code is a recognized
 * enum value, just call setType().
 * @param {number} otherTypeCode The packet’s unrecognized content type code,
 * which must be non-negative.
 */
MetaInfo.prototype.setOtherTypeCode = function(otherTypeCode)
{
  if (otherTypeCode < 0)
    throw new Error("MetaInfo other type code must be non-negative");

  this.otherTypeCode_ = otherTypeCode;
  ++this.changeCount_;
};

/**
 * Set the freshness period.
 * @param {number} freshnessPeriod The freshness period in milliseconds, or null
 * for not specified.
 */
MetaInfo.prototype.setFreshnessPeriod = function(freshnessPeriod)
{
  if (freshnessPeriod == null || freshnessPeriod < 0)
    this.freshnessPeriod_ = null;
  else
    this.freshnessPeriod_ = freshnessPeriod;
  ++this.changeCount_;
};

/**
 * Set the final block ID.
 * @param {Name.Component} finalBlockId The final block ID as a Name.Component.
 * If not specified, set to a new default Name.Component(), or to a
 * Name.Component where getValue().size() is 0.
 */
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);
};

/**
 * Get the change count, which is incremented each time this object is changed.
 * @return {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 getFinalBlockId and setFinalBlockId.
 */
Object.defineProperty(MetaInfo.prototype, "finalBlockID",
  { get: function() { return this.getFinalBlockIDAsBuffer(); },
    set: function(val) { this.setFinalBlockId(val); } });
/**
 * This class represents an NDN Data Signature object.
 * Copyright (C) 2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var Blob = require('./util/blob.js').Blob; /** @ignore */
var ChangeCounter = require('./util/change-counter.js').ChangeCounter; /** @ignore */
var KeyLocator = require('./key-locator.js').KeyLocator;

/**
 * Create a new Sha256WithEcdsaSignature object, possibly copying values from
 * another object.
 *
 * @param {Sha256WithEcdsaSignature} value (optional) If value is a
 * Sha256WithEcdsaSignature, copy its values.  If value is omitted, the 
 * keyLocator is the default with unspecified values and the signature is
 * unspecified.
 * @constructor
 */
var Sha256WithEcdsaSignature = function Sha256WithEcdsaSignature(value)
{
  if (typeof value === 'object' && value instanceof Sha256WithEcdsaSignature) {
    // Copy the values.
    this.keyLocator_ = new ChangeCounter(new KeyLocator(value.getKeyLocator()));
    this.signature_ = value.signature_;
  }
  else {
    this.keyLocator_ = new ChangeCounter(new KeyLocator());
    this.signature_ = new Blob();
  }

  this.changeCount_ = 0;
};

exports.Sha256WithEcdsaSignature = Sha256WithEcdsaSignature;

/**
 * Create a new Sha256WithEcdsaSignature which is a copy of this object.
 * @return {Sha256WithEcdsaSignature} A new object which is a copy of this
 * object.
 */
Sha256WithEcdsaSignature.prototype.clone = function()
{
  return new Sha256WithEcdsaSignature(this);
};

/**
 * Get the key locator.
 * @return {KeyLocator} The key locator.
 */
Sha256WithEcdsaSignature.prototype.getKeyLocator = function()
{
  return this.keyLocator_.get();
};

/**
 * Get the data packet's signature bytes.
 * @return {Blob} The signature bytes. If not specified, the value isNull().
 */
Sha256WithEcdsaSignature.prototype.getSignature = function()
{
  return this.signature_;
};

/**
 * Set the key locator to a copy of the given keyLocator.
 * @param {KeyLocator} keyLocator The KeyLocator to copy.
 */
Sha256WithEcdsaSignature.prototype.setKeyLocator = function(keyLocator)
{
  this.keyLocator_.set(typeof keyLocator === 'object' &&
                       keyLocator instanceof KeyLocator ?
    new KeyLocator(keyLocator) : new KeyLocator());
  ++this.changeCount_;
};

/**
 * Set the data packet's signature bytes.
 * @param {Blob} signature
 */
Sha256WithEcdsaSignature.prototype.setSignature = function(signature)
{
  this.signature_ = typeof signature === 'object' && signature instanceof Blob ?
    signature : new Blob(signature);
  ++this.changeCount_;
};

/**
 * Get the change count, which is incremented each time this object (or a child
 * object) is changed.
 * @return {number} The change count.
 */
Sha256WithEcdsaSignature.prototype.getChangeCount = function()
{
  // Make sure each of the checkChanged is called.
  var changed = this.keyLocator_.checkChanged();
  if (changed)
    // A child object has changed, so update the change count.
    ++this.changeCount_;

  return this.changeCount_;
};
/**
 * This class represents an NDN Data Signature object.
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Meki Cheraoui
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var Blob = require('./util/blob.js').Blob; /** @ignore */
var ChangeCounter = require('./util/change-counter.js').ChangeCounter; /** @ignore */
var KeyLocator = require('./key-locator.js').KeyLocator;

/**
 * Create a new Sha256WithRsaSignature object, possibly copying values from
 * another object.
 *
 * @param {Sha256WithRsaSignature} value (optional) If value is a
 * Sha256WithRsaSignature, copy its values.  If value is omitted, the keyLocator
 * is the default with unspecified values and the signature is unspecified.
 * @constructor
 */
var Sha256WithRsaSignature = function Sha256WithRsaSignature(value)
{
  if (typeof value === 'object' && value instanceof Sha256WithRsaSignature) {
    // Copy the values.
    this.keyLocator_ = new ChangeCounter(new KeyLocator(value.getKeyLocator()));
    this.signature_ = value.signature_;
  }
  else {
    this.keyLocator_ = new ChangeCounter(new KeyLocator());
    this.signature_ = new Blob();
  }

  this.changeCount_ = 0;
};

exports.Sha256WithRsaSignature = Sha256WithRsaSignature;

/**
 * Create a new Sha256WithRsaSignature which is a copy of this object.
 * @return {Sha256WithRsaSignature} A new object which is a copy of this object.
 */
Sha256WithRsaSignature.prototype.clone = function()
{
  return new Sha256WithRsaSignature(this);
};

/**
 * Get the key locator.
 * @return {KeyLocator} The key locator.
 */
Sha256WithRsaSignature.prototype.getKeyLocator = function()
{
  return this.keyLocator_.get();
};

/**
 * Get the data packet's signature bytes.
 * @return {Blob} The signature bytes. If not specified, the value isNull().
 */
Sha256WithRsaSignature.prototype.getSignature = function()
{
  return this.signature_;
};

/**
 * @deprecated Use getSignature. This method returns a Buffer which is the former
 * behavior of getSignature, and should only be used while updating your code.
 */
Sha256WithRsaSignature.prototype.getSignatureAsBuffer = function()
{
  return this.signature_.buf();
};

/**
 * Set the key locator to a copy of the given keyLocator.
 * @param {KeyLocator} keyLocator The KeyLocator to copy.
 */
Sha256WithRsaSignature.prototype.setKeyLocator = function(keyLocator)
{
  this.keyLocator_.set(typeof keyLocator === 'object' &&
                       keyLocator instanceof KeyLocator ?
    new KeyLocator(keyLocator) : new KeyLocator());
  ++this.changeCount_;
};

/**
 * Set the data packet's signature bytes.
 * @param {Blob} signature
 */
Sha256WithRsaSignature.prototype.setSignature = function(signature)
{
  this.signature_ = typeof signature === 'object' && signature instanceof Blob ?
    signature : new Blob(signature);
  ++this.changeCount_;
};

/**
 * Get the change count, which is incremented each time this object (or a child
 * object) is changed.
 * @return {number} The change count.
 */
Sha256WithRsaSignature.prototype.getChangeCount = function()
{
  // Make sure each of the checkChanged is called.
  var changed = this.keyLocator_.checkChanged();
  if (changed)
    // A child object has changed, so update the change count.
    ++this.changeCount_;

  return this.changeCount_;
};

// Define properties so we can change member variable types and implement changeCount_.
Object.defineProperty(Sha256WithRsaSignature.prototype, "keyLocator",
  { get: function() { return this.getKeyLocator(); },
    set: function(val) { this.setKeyLocator(val); } });
/**
 * @@deprecated Use getSignature and setSignature.
 */
Object.defineProperty(Sha256WithRsaSignature.prototype, "signature",
  { get: function() { return this.getSignatureAsBuffer(); },
    set: function(val) { this.setSignature(val); } });
/**
 * This class represents an NDN Data Signature object.
 * Copyright (C) 2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var Blob = require('./util/blob.js').Blob;

/**
 * A GenericSignature extends Signature and holds the encoding bytes of the
 * SignatureInfo so that the application can process experimental signature
 * types. When decoding a packet, if the type of SignatureInfo is not
 * recognized, the library creates a GenericSignature.
 * Create a new GenericSignature object, possibly copying values from another
 * object.
 *
 * @param {GenericSignature} value (optional) If value is a GenericSignature,
 * copy its values.
 * @constructor
 */
var GenericSignature = function GenericSignature(value)
{
  if (typeof value === 'object' && value instanceof GenericSignature) {
    // Copy the values.
    this.signature_ = value.signature_;
    this.signatureInfoEncoding_ = value.signatureInfoEncoding_;
    this.typeCode_ = value.typeCode_;
  }
  else {
    this.signature_ = new Blob();
    this.signatureInfoEncoding_ = new Blob();
    this.typeCode_ = null;
  }

  this.changeCount_ = 0;
};

exports.GenericSignature = GenericSignature;

/**
 * Create a new GenericSignature which is a copy of this object.
 * @return {GenericSignature} A new object which is a copy of this object.
 */
GenericSignature.prototype.clone = function()
{
  return new GenericSignature(this);
};

/**
 * Get the data packet's signature bytes.
 * @return {Blob} The signature bytes. If not specified, the value isNull().
 */
GenericSignature.prototype.getSignature = function()
{ 
  return this.signature_;
};

/**
 * @deprecated Use getSignature. This method returns a Buffer which is the former
 * behavior of getSignature, and should only be used while updating your code.
 */
GenericSignature.prototype.getSignatureAsBuffer = function()
{
  return this.signature_.buf();
};

/**
 * Get the bytes of the entire signature info encoding (including the type
 * code).
 * @return {Blob} The encoding bytes. If not specified, the value isNull().
 */
GenericSignature.prototype.getSignatureInfoEncoding = function()
{
  return this.signatureInfoEncoding_;
};

/**
 * Get the type code of the signature type. When wire decode calls
 * setSignatureInfoEncoding, it sets the type code. Note that the type code
 * is ignored during wire encode, which simply uses getSignatureInfoEncoding()
 * where the encoding already has the type code.
 * @return {number} The type code, or null if not known.
 */
GenericSignature.prototype.getTypeCode = function() { return this.typeCode_; };

/**
 * Set the data packet's signature bytes.
 * @param {Blob} signature
 */
GenericSignature.prototype.setSignature = function(signature)
{
  this.signature_ = typeof signature === 'object' && signature instanceof Blob ?
    signature : new Blob(signature);
  ++this.changeCount_;
};

/**
 * Set the bytes of the entire signature info encoding (including the type
 * code).
 * @param {Blob} signatureInfoEncoding A Blob with the encoding bytes.
 * @param {number} (optional) The type code of the signature type, or null if
 * not known. (When a GenericSignature is created by wire decoding, it sets
 * the typeCode.)
 */
GenericSignature.prototype.setSignatureInfoEncoding = function
  (signatureInfoEncoding, typeCode)
{
  this.signatureInfoEncoding_ =
    typeof signatureInfoEncoding === 'object' && signatureInfoEncoding instanceof Blob ?
      signatureInfoEncoding : new Blob(signatureInfoEncoding);
  this.typeCode_ = typeCode;
  ++this.changeCount_;
};

/**
 * Get the change count, which is incremented each time this object (or a child
 * object) is changed.
 * @return {number} The change count.
 */
GenericSignature.prototype.getChangeCount = function()
{
  return this.changeCount_;
};

/**
 * @@deprecated Use getSignature and setSignature.
 */
Object.defineProperty(GenericSignature.prototype, "signature",
  { get: function() { return this.getSignatureAsBuffer(); },
    set: function(val) { this.setSignature(val); } });
/**
 * This class represents an NDN Data Signature object.
 * Copyright (C) 2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var Blob = require('./util/blob.js').Blob; /** @ignore */
var ChangeCounter = require('./util/change-counter.js').ChangeCounter; /** @ignore */
var KeyLocator = require('./key-locator.js').KeyLocator;

/**
 * An HmacWithSha256Signature holds the signature bits and other info
 * representing an HmacWithSha256 signature in a packet.
 * Create a new HmacWithSha256Signature object, possibly copying values from
 * another object.
 *
 * @param {HmacWithSha256Signature} value (optional) If value is a
 * HmacWithSha256Signature, copy its values.  If value is omitted, the keyLocator
 * is the default with unspecified values and the signature is unspecified.
 * @constructor
 */
var HmacWithSha256Signature = function HmacWithSha256Signature(value)
{
  if (typeof value === 'object' && value instanceof HmacWithSha256Signature) {
    // Copy the values.
    this.keyLocator_ = new ChangeCounter(new KeyLocator(value.getKeyLocator()));
    this.signature_ = value.signature_;
  }
  else {
    this.keyLocator_ = new ChangeCounter(new KeyLocator());
    this.signature_ = new Blob();
  }

  this.changeCount_ = 0;
};

exports.HmacWithSha256Signature = HmacWithSha256Signature;

/**
 * Create a new HmacWithSha256Signature which is a copy of this object.
 * @return {HmacWithSha256Signature} A new object which is a copy of this object.
 */
HmacWithSha256Signature.prototype.clone = function()
{
  return new HmacWithSha256Signature(this);
};

/**
 * Get the key locator.
 * @return {KeyLocator} The key locator.
 */
HmacWithSha256Signature.prototype.getKeyLocator = function()
{
  return this.keyLocator_.get();
};

/**
 * Get the data packet's signature bytes.
 * @return {Blob} The signature bytes. If not specified, the value isNull().
 */
HmacWithSha256Signature.prototype.getSignature = function()
{
  return this.signature_;
};

/**
 * @deprecated Use getSignature. This method returns a Buffer which is the former
 * behavior of getSignature, and should only be used while updating your code.
 */
HmacWithSha256Signature.prototype.getSignatureAsBuffer = function()
{
  return this.signature_.buf();
};

/**
 * Set the key locator to a copy of the given keyLocator.
 * @param {KeyLocator} keyLocator The KeyLocator to copy.
 */
HmacWithSha256Signature.prototype.setKeyLocator = function(keyLocator)
{
  this.keyLocator_.set(typeof keyLocator === 'object' &&
                       keyLocator instanceof KeyLocator ?
    new KeyLocator(keyLocator) : new KeyLocator());
  ++this.changeCount_;
};

/**
 * Set the data packet's signature bytes.
 * @param {Blob} signature
 */
HmacWithSha256Signature.prototype.setSignature = function(signature)
{
  this.signature_ = typeof signature === 'object' && signature instanceof Blob ?
    signature : new Blob(signature);
  ++this.changeCount_;
};

/**
 * Get the change count, which is incremented each time this object (or a child
 * object) is changed.
 * @return {number} The change count.
 */
HmacWithSha256Signature.prototype.getChangeCount = function()
{
  // Make sure each of the checkChanged is called.
  var changed = this.keyLocator_.checkChanged();
  if (changed)
    // A child object has changed, so update the change count.
    ++this.changeCount_;

  return this.changeCount_;
};

// Define properties so we can change member variable types and implement changeCount_.
Object.defineProperty(HmacWithSha256Signature.prototype, "keyLocator",
  { get: function() { return this.getKeyLocator(); },
    set: function(val) { this.setKeyLocator(val); } });
/**
 * @@deprecated Use getSignature and setSignature.
 */
Object.defineProperty(HmacWithSha256Signature.prototype, "signature",
  { get: function() { return this.getSignatureAsBuffer(); },
    set: function(val) { this.setSignature(val); } });
/**
 * This class represents an NDN Data Signature object.
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var Blob = require('./util/blob.js').Blob;

/**
 * A DigestSha256Signature extends Signature and holds the signature bits (which
 * are only the SHA256 digest) and an empty SignatureInfo for a data packet or
 * signed interest.
 *
 * Create a new DigestSha256Signature object, possibly copying values from
 * another object.
 *
 * @param {DigestSha256Signature} value (optional) If value is a
 * DigestSha256Signature, copy its values.  If value is omitted, the signature
 * is unspecified.
 * @constructor
 */
var DigestSha256Signature = function DigestSha256Signature(value)
{
  if (typeof value === 'object' && value instanceof DigestSha256Signature)
    // Copy the values.
    this.signature_ = value.signature_;
  else
    this.signature_ = new Blob();

  this.changeCount_ = 0;
};

exports.DigestSha256Signature = DigestSha256Signature;

/**
 * Create a new DigestSha256Signature which is a copy of this object.
 * @return {DigestSha256Signature} A new object which is a copy of this object.
 */
DigestSha256Signature.prototype.clone = function()
{
  return new DigestSha256Signature(this);
};

/**
 * Get the signature bytes (which are only the digest).
 * @return {Blob} The signature bytes. If not specified, the value isNull().
 */
DigestSha256Signature.prototype.getSignature = function()
{
  return this.signature_;
};

/**
 * Set the signature bytes to the given value.
 * @param {Blob} signature
 */
DigestSha256Signature.prototype.setSignature = function(signature)
{
  this.signature_ = typeof signature === 'object' && signature instanceof Blob ?
    signature : new Blob(signature);
  ++this.changeCount_;
};

/**
 * Get the change count, which is incremented each time this object is changed.
 * @return {number} The change count.
 */
DigestSha256Signature.prototype.getChangeCount = function()
{
  return this.changeCount_;
};

// Define properties so we can change member variable types and implement changeCount_.
/**
 * @@deprecated Use getSignature and setSignature.
 */
Object.defineProperty(DigestSha256Signature.prototype, "signature",
  { get: function() { return this.getSignature(); },
    set: function(val) { this.setSignature(val); } });
/**
 * This class represents an NDN Data object.
 * Copyright (C) 2013-2016 Regents of the University of California.
 * @author: Meki Cheraoui
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var Blob = require('./util/blob.js').Blob; /** @ignore */
var SignedBlob = require('./util/signed-blob.js').SignedBlob; /** @ignore */
var ChangeCounter = require('./util/change-counter.js').ChangeCounter; /** @ignore */
var Name = require('./name.js').Name; /** @ignore */
var Sha256WithRsaSignature = require('./sha256-with-rsa-signature.js').Sha256WithRsaSignature; /** @ignore */
var MetaInfo = require('./meta-info.js').MetaInfo; /** @ignore */
var IncomingFaceId = require('./lp/incoming-face-id.js').IncomingFaceId; /** @ignore */
var WireFormat = require('./encoding/wire-format.js').WireFormat; /** @ignore */
var Crypto = require('./crypto.js');

/**
 * Create a new Data with the optional values.  There are 2 forms of constructor:
 * new Data([name] [, content]);
 * new Data(name, metaInfo [, content]);
 *
 * @constructor
 * @param {Name} name
 * @param {MetaInfo} metaInfo
 * @param {Buffer} content
 */
var Data = function Data(nameOrData, metaInfoOrContent, arg3)
{
  if (nameOrData instanceof Data) {
    // The copy constructor.
    var data = nameOrData;

    // Copy the Data object.
    this.name_ = new ChangeCounter(new Name(data.getName()));
    this.metaInfo_ = new ChangeCounter(new MetaInfo(data.getMetaInfo()));
    this.signature_ = new ChangeCounter(data.getSignature().clone());
    this.content_ = data.content_;
    this.defaultWireEncoding_ = data.getDefaultWireEncoding();
    this.defaultFullName_ = data.defaultFullName_;
    this.defaultWireEncodingFormat_ = data.defaultWireEncodingFormat_;
  }
  else {
    var name = nameOrData;
    if (typeof name === 'string')
      this.name_ = new ChangeCounter(new Name(name));
    else
      this.name_ = new ChangeCounter(typeof name === 'object' && name instanceof Name ?
         new Name(name) : new Name());

    var metaInfo;
    var content;
    if (typeof metaInfoOrContent === 'object' &&
        metaInfoOrContent instanceof MetaInfo) {
      metaInfo = metaInfoOrContent;
      content = arg3;
    }
    else {
      metaInfo = null;
      content = metaInfoOrContent;
    }

    this.metaInfo_ = new ChangeCounter(typeof metaInfo === 'object' && metaInfo instanceof MetaInfo ?
      new MetaInfo(metaInfo) : new MetaInfo());

    this.content_ = typeof content === 'object' && content instanceof Blob ?
      content : new Blob(content, true);

    this.signature_ = new ChangeCounter(new Sha256WithRsaSignature());
    this.defaultWireEncoding_ = new SignedBlob();
    this.defaultFullName_ = new Name();
    this.defaultWireEncodingFormat_ = null;
  }

  this.getDefaultWireEncodingChangeCount_ = 0;
  this.changeCount_ = 0;
  this.lpPacket_ = null;
};

exports.Data = Data;

/**
 * Get the data packet's name.
 * @return {Name} The name. If not specified, the name size() is 0.
 */
Data.prototype.getName = function()
{
  return this.name_.get();
};

/**
 * Get the data packet's meta info.
 * @return {MetaInfo} The meta info.
 */
Data.prototype.getMetaInfo = function()
{
  return this.metaInfo_.get();
};

/**
 * Get the data packet's signature object.
 * @return {Signature} The signature object.
 */
Data.prototype.getSignature = function()
{
  return this.signature_.get();
};

/**
 * Get the data packet's content.
 * @return {Blob} The content as a Blob, which isNull() if unspecified.
 */
Data.prototype.getContent = function()
{
  return this.content_;
};

/**
 * @deprecated Use getContent. This method returns a Buffer which is the former
 * behavior of getContent, and should only be used while updating your code.
 */
Data.prototype.getContentAsBuffer = function()
{
  return this.content_.buf();
};

/**
 * Return the default wire encoding, which was encoded with
 * getDefaultWireEncodingFormat().
 * @return {SignedBlob} The default wire encoding, whose isNull() may be true
 * if there is no default wire encoding.
 */
Data.prototype.getDefaultWireEncoding = function()
{
  if (this.getDefaultWireEncodingChangeCount_ != this.getChangeCount()) {
    // The values have changed, so the default wire encoding is invalidated.
    this.defaultWireEncoding_ = new SignedBlob();
    this.defaultWireEncodingFormat_ = null;
    this.getDefaultWireEncodingChangeCount_ = this.getChangeCount();
  }

  return this.defaultWireEncoding_;
};

/**
 * Get the WireFormat which is used by getDefaultWireEncoding().
 * @return {WireFormat} The WireFormat, which is only meaningful if the
 * getDefaultWireEncoding() is not isNull().
 */
Data.prototype.getDefaultWireEncodingFormat = function()
{
  return this.defaultWireEncodingFormat_;
};

/**
 * Get the incoming face ID according to the incoming packet header.
 * @return {number} The incoming face ID. If not specified, return null.
 */
Data.prototype.getIncomingFaceId = function()
{
  var field =
    this.lpPacket_ === null ? null : IncomingFaceId.getFirstHeader(this.lpPacket_);
  return field === null ? null : field.getFaceId();
};

/**
 * Get the Data packet's full name, which includes the final
 * ImplicitSha256Digest component based on the wire encoding for a particular
 * wire format.
 * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
 * this object. If omitted, use WireFormat.getDefaultWireFormat().
 * @return {Name} The full name. You must not change the Name object - if you
 * need to change it then make a copy.
 */
Data.prototype.getFullName = function(wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());

  // The default full name depends on the default wire encoding.
  if (!this.getDefaultWireEncoding().isNull() &&
      this.defaultFullName_.size() > 0 &&
      this.getDefaultWireEncodingFormat() == wireFormat)
    // We already have a full name. A non-null default wire encoding means
    // that the Data packet fields have not changed.
    return this.defaultFullName_;

  var fullName = new Name(this.getName());
  var hash = Crypto.createHash('sha256');
  // wireEncode will use the cached encoding if possible.
  hash.update(this.wireEncode(wireFormat).buf());
  fullName.appendImplicitSha256Digest(new Blob(hash.digest(), false));

  if (wireFormat == WireFormat.getDefaultWireFormat())
    // wireEncode has already set defaultWireEncodingFormat_.
    this.defaultFullName_ = fullName;

  return fullName;
};

/**
 * Set name to a copy of the given Name.
 * @param {Name} name The Name which is copied.
 * @return {Data} This Data so that you can chain calls to update values.
 */
Data.prototype.setName = function(name)
{
  this.name_.set(typeof name === 'object' && name instanceof Name ?
    new Name(name) : new Name());
  ++this.changeCount_;
  return this;
};

/**
 * Set metaInfo to a copy of the given MetaInfo.
 * @param {MetaInfo} metaInfo The MetaInfo which is copied.
 * @return {Data} This Data so that you can chain calls to update values.
 */
Data.prototype.setMetaInfo = function(metaInfo)
{
  this.metaInfo_.set(typeof metaInfo === 'object' && metaInfo instanceof MetaInfo ?
    new MetaInfo(metaInfo) : new MetaInfo());
  ++this.changeCount_;
  return this;
};

/**
 * Set the signature to a copy of the given signature.
 * @param {Signature} signature The signature object which is cloned.
 * @return {Data} This Data so that you can chain calls to update values.
 */
Data.prototype.setSignature = function(signature)
{
  this.signature_.set(signature == null ?
    new Sha256WithRsaSignature() : signature.clone());
  ++this.changeCount_;
  return this;
};

/**
 * Set the content to the given value.
 * @param {Blob|Buffer} content The content bytes. If content is not a Blob,
 * then create a new Blob to copy the bytes (otherwise take another pointer to
 * the same Blob).
 * @return {Data} This Data so that you can chain calls to update values.
 */
Data.prototype.setContent = function(content)
{
  this.content_ = typeof content === 'object' && content instanceof Blob ?
    content : new Blob(content, true);
  ++this.changeCount_;
  return this;
};

/**
 * Encode this Data for a particular wire format. If wireFormat is the default
 * wire format, also set the defaultWireEncoding field to the encoded result.
 * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
 * this object. If omitted, use WireFormat.getDefaultWireFormat().
 * @return {SignedBlob} The encoded buffer in a SignedBlob object.
 */
Data.prototype.wireEncode = function(wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());

  if (!this.getDefaultWireEncoding().isNull() &&
      this.getDefaultWireEncodingFormat() == wireFormat)
    // We already have an encoding in the desired format.
    return this.getDefaultWireEncoding();

  var result = wireFormat.encodeData(this);
  var wireEncoding = new SignedBlob
    (result.encoding, result.signedPortionBeginOffset,
     result.signedPortionEndOffset);

  if (wireFormat == WireFormat.getDefaultWireFormat())
    // This is the default wire encoding.
    this.setDefaultWireEncoding
      (wireEncoding, WireFormat.getDefaultWireFormat());
  return wireEncoding;
};

/**
 * Decode the input using a particular wire format and update this Data. If
 * wireFormat is the default wire format, also set the defaultWireEncoding to
 * another pointer to the input.
 * @param {Blob|Buffer} input The buffer with the bytes to decode.
 * @param {WireFormat} wireFormat (optional) A WireFormat object used to decode
 * this object. If omitted, use WireFormat.getDefaultWireFormat().
 */
Data.prototype.wireDecode = function(input, wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());

  var result;
  if (typeof input === 'object' && input instanceof Blob)
    // Input is a blob, so get its buf() and set copy false.
    result = wireFormat.decodeData(this, input.buf(), false);
  else
    result = wireFormat.decodeData(this, input, true);

  if (wireFormat == WireFormat.getDefaultWireFormat())
    // This is the default wire encoding.  In the Blob constructor, set copy
    // true, but if input is already a Blob, it won't copy.
    this.setDefaultWireEncoding(new SignedBlob
      (new Blob(input, true), result.signedPortionBeginOffset,
       result.signedPortionEndOffset),
      WireFormat.getDefaultWireFormat());
  else
    this.setDefaultWireEncoding(new SignedBlob(), null);
};

/**
 * An internal library method to set the LpPacket for an incoming packet. The
 * application should not call this.
 * @param {LpPacket} lpPacket The LpPacket. This does not make a copy.
 * @return {Data} This Data so that you can chain calls to update values.
 * @note This is an experimental feature. This API may change in the future.
 */
Data.prototype.setLpPacket = function(lpPacket)
{
  this.lpPacket_ = lpPacket;
  // Don't update changeCount_ since this doesn't affect the wire encoding.
  return this;
}

/**
 * Get the change count, which is incremented each time this object (or a child
 * object) is changed.
 * @return {number} The change count.
 */
Data.prototype.getChangeCount = function()
{
  // Make sure each of the checkChanged is called.
  var changed = this.name_.checkChanged();
  changed = this.metaInfo_.checkChanged() || changed;
  changed = this.signature_.checkChanged() || changed;
  if (changed)
    // A child object has changed, so update the change count.
    ++this.changeCount_;

  return this.changeCount_;
};

Data.prototype.setDefaultWireEncoding = function
  (defaultWireEncoding, defaultWireEncodingFormat)
{
  this.defaultWireEncoding_ = defaultWireEncoding;
  this.defaultWireEncodingFormat_ = defaultWireEncodingFormat;
  // Set getDefaultWireEncodingChangeCount_ so that the next call to
  // getDefaultWireEncoding() won't clear _defaultWireEncoding.
  this.getDefaultWireEncodingChangeCount_ = this.getChangeCount();
};

// Define properties so we can change member variable types and implement changeCount_.
Object.defineProperty(Data.prototype, "name",
  { get: function() { return this.getName(); },
    set: function(val) { this.setName(val); } });
Object.defineProperty(Data.prototype, "metaInfo",
  { get: function() { return this.getMetaInfo(); },
    set: function(val) { this.setMetaInfo(val); } });
Object.defineProperty(Data.prototype, "signature",
  { get: function() { return this.getSignature(); },
    set: function(val) { this.setSignature(val); } });
/**
 * @deprecated Use getContent and setContent.
 */
Object.defineProperty(Data.prototype, "content",
  { get: function() { return this.getContentAsBuffer(); },
    set: function(val) { this.setContent(val); } });
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/**
 * Create a new SecurityException to report an exception from the security
 * library, wrapping the given error object.
 * Call with: throw new SecurityException(new Error("message")).
 * @constructor
 * @param {Error} error The exception created with new Error.
 */
function SecurityException(error)
{
  if (error) {
    error.__proto__ = SecurityException.prototype;
    return error;
  }
}

SecurityException.prototype = new Error();
SecurityException.prototype.name = "SecurityException";

exports.SecurityException = SecurityException;

function UnrecognizedKeyFormatException(error)
{
  // Call the base constructor.
  SecurityException.call(this, error);
}
UnrecognizedKeyFormatException.prototype = new SecurityException();
UnrecognizedKeyFormatException.prototype.name = "UnrecognizedKeyFormatException";

exports.UnrecognizedKeyFormatException = UnrecognizedKeyFormatException;

function UnrecognizedDigestAlgorithmException(error)
{
  // Call the base constructor.
  SecurityException.call(this, error);
}
UnrecognizedDigestAlgorithmException.prototype = new SecurityException();
UnrecognizedDigestAlgorithmException.prototype.name = "UnrecognizedDigestAlgorithmException";

exports.UnrecognizedDigestAlgorithmException = UnrecognizedDigestAlgorithmException;
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
 *
 * 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.
 */

/**
 * This module defines constants used by the security library.
 */

/**
 * The KeyType integer is used by the Sqlite key storage, so don't change them.
 * Make these the same as ndn-cxx in case the storage file is shared.
 * @constructor
 */
var KeyType = function KeyType()
{
}

exports.KeyType = KeyType;

KeyType.RSA = 0;
KeyType.ECDSA = 1;
KeyType.AES = 128;

var KeyClass = function KeyClass()
{
};

exports.KeyClass = KeyClass;

KeyClass.PUBLIC = 1;
KeyClass.PRIVATE = 2;
KeyClass.SYMMETRIC = 3;

var DigestAlgorithm = function DigestAlgorithm()
{
};

exports.DigestAlgorithm = DigestAlgorithm;

DigestAlgorithm.SHA256 = 1;
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
 *
 * 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.
 */

/** @ignore */
var KeyType = require('./security-types.js').KeyType;

/**
 * KeyParams is a base class for key parameters. Its subclasses are used to
 * store parameters for key generation. You should create one of the subclasses,
 * for example RsaKeyParams.
 * @constructor
 */
var KeyParams = function KeyParams(keyType)
{
  this.keyType = keyType;
};

exports.KeyParams = KeyParams;

KeyParams.prototype.getKeyType = function()
{
  return this.keyType;
};

var RsaKeyParams = function RsaKeyParams(size)
{
  // Call the base constructor.
  KeyParams.call(this, RsaKeyParams.getType());

  if (size == null)
    size = RsaKeyParams.getDefaultSize();
  this.size = size;
};

RsaKeyParams.prototype = new KeyParams();
RsaKeyParams.prototype.name = "RsaKeyParams";

exports.RsaKeyParams = RsaKeyParams;

RsaKeyParams.prototype.getKeySize = function()
{
  return this.size;
};

RsaKeyParams.getDefaultSize = function() { return 2048; };

RsaKeyParams.getType = function() { return KeyType.RSA; };

var EcdsaKeyParams = function EcdsaKeyParams(size)
{
  // Call the base constructor.
  KeyParams.call(this, EcdsaKeyParams.getType());

  if (size == null)
    size = EcdsaKeyParams.getDefaultSize();
  this.size = size;
};

EcdsaKeyParams.prototype = new KeyParams();
EcdsaKeyParams.prototype.name = "EcdsaKeyParams";

exports.EcdsaKeyParams = EcdsaKeyParams;

EcdsaKeyParams.prototype.getKeySize = function()
{
  return this.size;
};

EcdsaKeyParams.getDefaultSize = function() { return 256; };

EcdsaKeyParams.getType = function() { return KeyType.ECDSA; };

var AesKeyParams = function AesKeyParams(size)
{
  // Call the base constructor.
  KeyParams.call(this, AesKeyParams.getType());

  if (size == null)
    size = AesKeyParams.getDefaultSize();
  this.size = size;
};

AesKeyParams.prototype = new KeyParams();
AesKeyParams.prototype.name = "AesKeyParams";

exports.AesKeyParams = AesKeyParams;

AesKeyParams.prototype.getKeySize = function()
{
  return this.size;
};

AesKeyParams.getDefaultSize = function() { return 64; };

AesKeyParams.getType = function() { return KeyType.AES; };
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
 *
 * 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.
 */

// Use capitalized Crypto to not clash with the browser's crypto.subtle.
/** @ignore */
var Crypto = require('../../crypto.js'); /** @ignore */
var Blob = require('../../util/blob.js').Blob; /** @ignore */
var DerDecodingException = require('../../encoding/der/der-decoding-exception.js').DerDecodingException; /** @ignore */
var DerNode = require('../../encoding/der/der-node.js').DerNode; /** @ignore */
var SecurityException = require('../security-exception.js').SecurityException; /** @ignore */
var UnrecognizedKeyFormatException = require('../security-exception.js').UnrecognizedKeyFormatException; /** @ignore */
var KeyType = require('../security-types.js').KeyType; /** @ignore */
var DigestAlgorithm = require('../security-types.js').DigestAlgorithm;

/**
 * Create a new PublicKey by decoding the keyDer. Set the key type from the
 * decoding.
 * @param {Blob} keyDer The blob of the SubjectPublicKeyInfo DER.
 * @throws UnrecognizedKeyFormatException if can't decode the key DER.
 * @constructor
 */
var PublicKey = function PublicKey(keyDer)
{
  if (!keyDer) {
    this.keyDer = new Blob();
    this.keyType = null;
    return;
  }

  this.keyDer = keyDer;

  // Get the public key OID.
  var oidString = null;
  try {
    var parsedNode = DerNode.parse(keyDer.buf(), 0);
    var rootChildren = parsedNode.getChildren();
    var algorithmIdChildren = DerNode.getSequence(rootChildren, 0).getChildren();
    oidString = algorithmIdChildren[0].toVal();
  }
  catch (ex) {
    throw new UnrecognizedKeyFormatException(new Error
      ("PublicKey.decodeKeyType: Error decoding the public key: " + ex.message));
  }

  // Verify that the we can decode.
  if (oidString == PublicKey.RSA_ENCRYPTION_OID) {
    this.keyType = KeyType.RSA;
    // TODO: Check RSA decoding.
  }
  else if (oidString == PublicKey.EC_ENCRYPTION_OID) {
    this.keyType = KeyType.ECDSA;
    // TODO: Check EC decoding.
  }
};

exports.PublicKey = PublicKey;

/**
 * Encode the public key into DER.
 * @return {DerNode} The encoded DER syntax tree.
 */
PublicKey.prototype.toDer = function()
{
  return DerNode.parse(this.keyDer.buf());
};

/**
 * Get the key type.
 * @return {number} The key type as an int from KeyType.
 */
PublicKey.prototype.getKeyType = function()
{
  return this.keyType;
};

/**
 * Get the digest of the public key.
 * @param {number} digestAlgorithm (optional) The integer from DigestAlgorithm,
 * such as DigestAlgorithm.SHA256. If omitted, use DigestAlgorithm.SHA256 .
 * @return {Blob} The digest value.
 */
PublicKey.prototype.getDigest = function(digestAlgorithm)
{
  if (digestAlgorithm == undefined)
    digestAlgorithm = DigestAlgorithm.SHA256;

  if (digestAlgorithm == DigestAlgorithm.SHA256) {
    var hash = Crypto.createHash('sha256');
    hash.update(this.keyDer.buf());
    return new Blob(hash.digest(), false);
  }
  else
    throw new SecurityException(new Error("Wrong format!"));
};

/**
 * Get the raw bytes of the public key in DER format.
 * @return {Blob} The public key DER.
 */
PublicKey.prototype.getKeyDer = function()
{
  return this.keyDer;
};

PublicKey.RSA_ENCRYPTION_OID = "1.2.840.113549.1.1.1";
PublicKey.EC_ENCRYPTION_OID = "1.2.840.10045.2.1";
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
 *
 * 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.
 */

/** @ignore */
var DerNode = require('../../encoding/der/der-node.js').DerNode; /** @ignore */
var OID = require('../../encoding/oid.js').OID;

/**
 * A CertificateExtension represents the Extension entry in a certificate.
 * Create a new CertificateExtension.
 * @param {string|OID} oid The oid of subject description entry.
 * @param {boolean} isCritical If true, the extension must be handled.
 * @param {Blob} value The extension value.
 * @constructor
 */
var CertificateExtension = function CertificateExtension(oid, isCritical, value)
{
  if (typeof oid === 'string')
    this.extensionId = new OID(oid);
  else
    // Assume oid is already an OID.
    this.extensionId = oid;

  this.isCritical = isCritical;
  this.extensionValue = value;
};

exports.CertificateExtension = CertificateExtension;

/**
 * Encode the object into a DER syntax tree.
 * @return {DerNode} The encoded DER syntax tree.
 */
CertificateExtension.prototype.toDer = function()
{
  var root = new DerNode.DerSequence();

  var extensionId = new DerNode.DerOid(this.extensionId);
  var isCritical = new DerNode.DerBoolean(this.isCritical);
  var extensionValue = new DerNode.DerOctetString(this.extensionValue.buf());

  root.addChild(extensionId);
  root.addChild(isCritical);
  root.addChild(extensionValue);

  root.getSize();

  return root;
};

CertificateExtension.prototype.toDerBlob = function()
{
  return this.toDer().encode();
};

CertificateExtension.prototype.getOid = function()
{
  return this.extensionId;
};

CertificateExtension.prototype.getIsCritical = function()
{
  return this.isCritical;
};

CertificateExtension.prototype.getValue = function()
{
  return this.extensionValue;
};
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
 *
 * 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.
 */

/** @ignore */
var Blob = require('../../util/blob.js').Blob; /** @ignore */
var OID = require('../../encoding/oid.js').OID; /** @ignore */
var DerNode = require('../../encoding/der/der-node.js').DerNode;

/**
 * A CertificateSubjectDescription represents the SubjectDescription entry in a
 * Certificate.
 * Create a new CertificateSubjectDescription.
 * @param {string|OID} oid The oid of the subject description entry.
 * @param {string} value The value of the subject description entry.
 * @constructor
 */
var CertificateSubjectDescription = function CertificateSubjectDescription
  (oid, value)
{
  if (typeof oid === 'string')
    this.oid = new OID(oid);
  else
    // Assume oid is already an OID.
    this.oid = oid;

  this.value = value;
};

exports.CertificateSubjectDescription = CertificateSubjectDescription;

/**
 * Encode the object into a DER syntax tree.
 * @return {DerNode} The encoded DER syntax tree.
 */
CertificateSubjectDescription.prototype.toDer = function()
{
  var root = new DerNode.DerSequence();

  var oid = new DerNode.DerOid(this.oid);
  // Use Blob to convert the String to a ByteBuffer.
  var value = new DerNode.DerPrintableString(new Blob(this.value).buf());

  root.addChild(oid);
  root.addChild(value);

  return root;
};

CertificateSubjectDescription.prototype.getOidString = function()
{
  return this.oid.toString();
};

CertificateSubjectDescription.prototype.getValue = function()
{
  return this.value;
};
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
 *
 * 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.
 */

/** @ignore */
var Data = require('../../data.js').Data; /** @ignore */
var ContentType = require('../../meta-info.js').ContentType; /** @ignore */
var WireFormat = require('../../encoding/wire-format.js').WireFormat; /** @ignore */
var DerNode = require('../../encoding/der/der-node.js').DerNode; /** @ignore */
var KeyType = require('../../security/security-types.js').KeyType; /** @ignore */
var PublicKey = require('./public-key.js').PublicKey; /** @ignore */
var CertificateSubjectDescription = require('./certificate-subject-description.js').CertificateSubjectDescription; /** @ignore */
var CertificateExtension = require('./certificate-extension.js').CertificateExtension;

/**
 * Create a Certificate from the content in the data packet (if not omitted).
 * @param {Data} data (optional) The data packet with the content to decode.
 * If omitted, create a Certificate with default values and the Data content
 * is empty.
 * @constructor
 */
var Certificate = function Certificate(data)
{
  // Call the base constructor.
  if (data != undefined)
    Data.call(this, data);
  else
    Data.call(this);

  this.subjectDescriptionList = [];  // of CertificateSubjectDescription
  this.extensionList = [];           // of CertificateExtension
  this.notBefore = Number.MAX_VALUE; // MillisecondsSince1970
  this.notAfter = -Number.MAX_VALUE; // MillisecondsSince1970
  this.key = new PublicKey();

  if (data != undefined)
    this.decode();
};
Certificate.prototype = new Data();
Certificate.prototype.name = "Certificate";

exports.Certificate = Certificate;

/**
 * Encode the contents of the certificate in DER format and set the Content
 * and MetaInfo fields.
 */
Certificate.prototype.encode = function()
{
  var root = this.toDer();
  this.setContent(root.encode());
  this.getMetaInfo().setType(ContentType.KEY);
};

/**
 * Add a subject description.
 * @param {CertificateSubjectDescription} description The description to be added.
 */
Certificate.prototype.addSubjectDescription = function(description)
{
  this.subjectDescriptionList.push(description);
};

/**
 * Get the subject description list.
 * @return {Array<CertificateSubjectDescription>} The subject description list.
 */
Certificate.prototype.getSubjectDescriptionList = function()
{
  return this.subjectDescriptionList;
};

/**
 * Add a certificate extension.
 * @param {CertificateSubjectDescription} extension The extension to be added.
 */
Certificate.prototype.addExtension = function(extension)
{
  this.extensionList.push(extension);
};

/**
 * Get the certificate extension list.
 * @return {Array<CertificateExtension>} The extension list.
 */
Certificate.prototype.getExtensionList = function()
{
  return this.extensionList;
};

Certificate.prototype.setNotBefore = function(notBefore)
{
  this.notBefore = notBefore;
};

Certificate.prototype.getNotBefore = function()
{
  return this.notBefore;
};

Certificate.prototype.setNotAfter = function(notAfter)
{
  this.notAfter = notAfter;
};

Certificate.prototype.getNotAfter = function()
{
  return this.notAfter;
};

Certificate.prototype.setPublicKeyInfo = function(key)
{
  this.key = key;
};

Certificate.prototype.getPublicKeyInfo = function()
{
  return this.key;
};

/**
 * Check if the certificate is valid.
 * @return {Boolean} True if the current time is earlier than notBefore.
 */
Certificate.prototype.isTooEarly = function()
{
  var now = new Date().getTime();
  return now < this.notBefore;
};

/**
 * Check if the certificate is valid.
 * @return {Boolean} True if the current time is later than notAfter.
 */
Certificate.prototype.isTooLate = function()
{
  var now = new Date().getTime();
  return now > this.notAfter;
};

/**
 * Encode the certificate fields in DER format.
 * @return {DerSequence} The DER encoded contents of the certificate.
 */
Certificate.prototype.toDer = function()
{
  var root = new DerNode.DerSequence();
  var validity = new DerNode.DerSequence();
  var notBefore = new DerNode.DerGeneralizedTime(this.notBefore);
  var notAfter = new DerNode.DerGeneralizedTime(this.notAfter);

  validity.addChild(notBefore);
  validity.addChild(notAfter);

  root.addChild(validity);

  var subjectList = new DerNode.DerSequence();
  for (var i = 0; i < this.subjectDescriptionList.length; ++i)
    subjectList.addChild(this.subjectDescriptionList[i].toDer());

  root.addChild(subjectList);
  root.addChild(this.key.toDer());

  if (this.extensionList.length > 0) {
    var extensionList = new DerNode.DerSequence();
    for (var i = 0; i < this.extensionList.length; ++i)
      extensionList.addChild(this.extensionList[i].toDer());
    root.addChild(extensionList);
  }

  return root;
};

/**
 * Populate the fields by the decoding DER data from the Content.
 */
Certificate.prototype.decode = function()
{
  var root = DerNode.parse(this.getContent().buf());

  // We need to ensure that there are:
  //   validity (notBefore, notAfter)
  //   subject list
  //   public key
  //   (optional) extension list

  var rootChildren = root.getChildren();
  // 1st: validity info
  var validityChildren = DerNode.getSequence(rootChildren, 0).getChildren();
  this.notBefore = validityChildren[0].toVal();
  this.notAfter = validityChildren[1].toVal();

  // 2nd: subjectList
  var subjectChildren = DerNode.getSequence(rootChildren, 1).getChildren();
  for (var i = 0; i < subjectChildren.length; ++i) {
    var sd = DerNode.getSequence(subjectChildren, i);
    var descriptionChildren = sd.getChildren();
    var oidStr = descriptionChildren[0].toVal();
    var value = descriptionChildren[1].toVal().buf().toString('binary');

    this.addSubjectDescription(new CertificateSubjectDescription(oidStr, value));
  }

  // 3rd: public key
  var publicKeyInfo = rootChildren[2].encode();
  this.key =  new PublicKey(publicKeyInfo);

  if (rootChildren.length > 3) {
    var extensionChildren = DerNode.getSequence(rootChildren, 3).getChildren();
    for (var i = 0; i < extensionChildren.length; ++i) {
      var extInfo = DerNode.getSequence(extensionChildren, i);

      var children = extInfo.getChildren();
      var oidStr = children[0].toVal();
      var isCritical = children[1].toVal();
      var value = children[2].toVal();
      this.addExtension(new CertificateExtension(oidStr, isCritical, value));
    }
  }
};

/**
 * Override to call the base class wireDecode then populate the certificate
 * fields.
 * @param {Blob|Buffer} input The buffer with the bytes to decode.
 * @param {WireFormat} wireFormat (optional) A WireFormat object used to decode
 * this object. If omitted, use WireFormat.getDefaultWireFormat().
 */
Certificate.prototype.wireDecode = function(input, wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());

  Data.prototype.wireDecode.call(this, input, wireFormat);
  this.decode();
};

Certificate.prototype.toString = function()
{
  var s = "Certificate name:\n";
  s += "  " + this.getName().toUri() + "\n";
  s += "Validity:\n";

  var notBeforeStr = Certificate.toIsoString(Math.round(this.notBefore));
  var notAfterStr = Certificate.toIsoString(Math.round(this.notAfter));

  s += "  NotBefore: " + notBeforeStr + "\n";
  s += "  NotAfter: " + notAfterStr + "\n";
  for (var i = 0; i < this.subjectDescriptionList.length; ++i) {
    var sd = this.subjectDescriptionList[i];
    s += "Subject Description:\n";
    s += "  " + sd.getOidString() + ": " + sd.getValue() + "\n";
  }

  s += "Public key bits:\n";
  var keyDer = this.key.getKeyDer();
  var encodedKey = keyDer.buf().toString('base64');
  for (var i = 0; i < encodedKey.length; i += 64)
    s += encodedKey.substring(i, Math.min(i + 64, encodedKey.length)) + "\n";

  if (this.extensionList.length > 0) {
    s += "Extensions:\n";
    for (var i = 0; i < this.extensionList.length; ++i) {
      var ext = this.extensionList[i];
      s += "  OID: " + ext.getOid() + "\n";
      s += "  Is critical: " + (ext.getIsCritical() ? 'Y' : 'N') + "\n";

      s += "  Value: " + ext.getValue().toHex() + "\n" ;
    }
  }

  return s;
};

/**
 * Convert a UNIX timestamp to ISO time representation with the "T" in the middle.
 * @param {type} msSince1970 Timestamp as milliseconds since Jan 1, 1970.
 * @return {string} The string representation.
 */
Certificate.toIsoString = function(msSince1970)
{
  var utcTime = new Date(Math.round(msSince1970));
  return utcTime.getUTCFullYear() +
         Certificate.to2DigitString(utcTime.getUTCMonth() + 1) +
         Certificate.to2DigitString(utcTime.getUTCDate()) +
         "T" +
         Certificate.to2DigitString(utcTime.getUTCHours()) +
         Certificate.to2DigitString(utcTime.getUTCMinutes()) +
         Certificate.to2DigitString(utcTime.getUTCSeconds());
};

/**
 * A private method to zero pad an integer to 2 digits.
 * @param {number} x The number to pad.  Assume it is a non-negative integer.
 * @return {string} The padded string.
 */
Certificate.to2DigitString = function(x)
{
  var result = x.toString();
  return result.length === 1 ? "0" + result : result;
};
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
 *
 * 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.
 */

/** @ignore */
var Data = require('../../data.js').Data; /** @ignore */
var Name = require('../../name.js').Name; /** @ignore */
var SecurityException = require('../../security//security-exception.js').SecurityException; /** @ignore */
var Certificate = require('./certificate.js').Certificate; /** @ignore */
var WireFormat = require('../../encoding/wire-format.js').WireFormat;

/**
 * @constructor
 */
var IdentityCertificate = function IdentityCertificate(data)
{
  // Call the base constructor.
  if (data != undefined)
    // This works if data is Data or IdentityCertificate.
    Certificate.call(this, data);
  else
    Certificate.call(this);

  this.publicKeyName = new Name();

  if (data instanceof IdentityCertificate) {
    // The copy constructor.
    this.publicKeyName = new Name(data.publicKeyName);
  }
  else if (data instanceof Data) {
    if (!IdentityCertificate.isCorrectName(data.getName()))
      throw new SecurityException(new Error("Wrong Identity Certificate Name!"));

    this.setPublicKeyName();
  }
};
IdentityCertificate.prototype = new Certificate();
IdentityCertificate.prototype.name = "IdentityCertificate";

exports.IdentityCertificate = IdentityCertificate;

/**
 * Override the base class method to check that the name is a valid identity
 * certificate name.
 * @param {Name} name The identity certificate name which is copied.
 * @return {Data} This Data so that you can chain calls to update values.
 */
IdentityCertificate.prototype.setName = function(name)
{
  if (!IdentityCertificate.isCorrectName(name))
    throw new SecurityException(new Error("Wrong Identity Certificate Name!"));

  // Call the super class method.
  Certificate.prototype.setName.call(this, name);
  this.setPublicKeyName();
  return this;
};

/**
 * Override to call the base class wireDecode then update the public key name.
 * @param {Blob|Buffer} input The buffer with the bytes to decode.
 * @param {WireFormat} wireFormat (optional) A WireFormat object used to decode
 * this object. If omitted, use WireFormat.getDefaultWireFormat().
 */
IdentityCertificate.prototype.wireDecode = function(input, wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());

  Certificate.prototype.wireDecode.call(this, input, wireFormat);
  this.setPublicKeyName();
};

IdentityCertificate.prototype.getPublicKeyName = function()
{
  return this.publicKeyName;
};

IdentityCertificate.isIdentityCertificate = function(certificate)
{
  return IdentityCertificate.isCorrectName(certificate.getName());
};

/**
 * Get the public key name from the full certificate name.
 * @param {Name} certificateName The full certificate name.
 * @return {Name} The related public key name.
 */
IdentityCertificate.certificateNameToPublicKeyName = function(certificateName)
{
  var idString = "ID-CERT";
  var foundIdString = false;
  var idCertComponentIndex = certificateName.size() - 1;
  for (; idCertComponentIndex + 1 > 0; --idCertComponentIndex) {
    if (certificateName.get(idCertComponentIndex).toEscapedString() == idString) {
      foundIdString = true;
      break;
    }
  }

  if (!foundIdString)
    throw new Error
      ("Incorrect identity certificate name " + certificateName.toUri());

  var tempName = certificateName.getSubName(0, idCertComponentIndex);
  var keyString = "KEY";
  var foundKeyString = false;
  var keyComponentIndex = 0;
  for (; keyComponentIndex < tempName.size(); keyComponentIndex++) {
    if (tempName.get(keyComponentIndex).toEscapedString() == keyString) {
      foundKeyString = true;
      break;
    }
  }

  if (!foundKeyString)
    throw new Error
      ("Incorrect identity certificate name " + certificateName.toUri());

  return tempName
    .getSubName(0, keyComponentIndex)
    .append(tempName.getSubName
            (keyComponentIndex + 1, tempName.size() - keyComponentIndex - 1));
};

IdentityCertificate.isCorrectName = function(name)
{
  var i = name.size() - 1;

  var idString = "ID-CERT";
  for (; i >= 0; i--) {
    if (name.get(i).toEscapedString() == idString)
      break;
  }

  if (i < 0)
    return false;

  var keyIdx = 0;
  var keyString = "KEY";
  for (; keyIdx < name.size(); keyIdx++) {
    if(name.get(keyIdx).toEscapedString() == keyString)
      break;
  }

  if (keyIdx >= name.size())
    return false;

  return true;
};

IdentityCertificate.prototype.setPublicKeyName = function()
{
  this.publicKeyName = IdentityCertificate.certificateNameToPublicKeyName
    (this.getName());
};

/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
 *
 * 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.
 */

/** @ignore */
var Name = require('../../name.js').Name; /** @ignore */
var SecurityException = require('../security-exception.js').SecurityException; /** @ignore */
var SyncPromise = require('../../util/sync-promise.js').SyncPromise;

/**
 * IdentityStorage is a base class for the storage of identity, public keys and
 * certificates. Private keys are stored in PrivateKeyStorage.
 * This is an abstract base class.  A subclass must implement the methods.
 * @constructor
 */
var IdentityStorage = function IdentityStorage()
{
};

exports.IdentityStorage = IdentityStorage;

/**
 * Check if the specified identity already exists.
 * @param {Name} identityName The identity name.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which returns true if the identity
 * exists.
 */
IdentityStorage.prototype.doesIdentityExistPromise = function
  (identityName, useSync)
{
  return SyncPromise.reject(new Error
    ("IdentityStorage.doesIdentityExistPromise is not implemented"));
};

/**
 * Check if the specified identity already exists.
 * @param {Name} identityName The identity name.
 * @return {boolean} true if the identity exists, otherwise false.
 * @throws Error If doesIdentityExistPromise doesn't return a SyncPromise which
 * is already fulfilled.
 */
IdentityStorage.prototype.doesIdentityExist = function(identityName)
{
  return SyncPromise.getValue(this.doesIdentityExistPromise(identityName, true));
};

/**
 * Add a new identity. Do nothing if the identity already exists.
 * @param {Name} identityName The identity name to be added.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which fulfills when the identity is
 * added.
 */
IdentityStorage.prototype.addIdentityPromise = function(identityName, useSync)
{
  return SyncPromise.reject(new Error
    ("IdentityStorage.addIdentityPromise is not implemented"));
};

/**
 * Add a new identity. Do nothing if the identity already exists.
 * @param {Name} identityName The identity name to be added.
 * @throws Error If addIdentityPromise doesn't return a SyncPromise which
 * is already fulfilled.
 */
IdentityStorage.prototype.addIdentity = function(identityName)
{
  return SyncPromise.getValue(this.addIdentityPromise(identityName, true));
};

/**
 * Revoke the identity.
 * @return {boolean} true if the identity was revoked, false if not.
 */
IdentityStorage.prototype.revokeIdentity = function()
{
  return SyncPromise.reject(new Error
    ("IdentityStorage.revokeIdentity is not implemented"));
};

/**
 * Generate a name for a new key belonging to the identity.
 * @param {Name} identityName The identity name.
 * @param {boolean} useKsk If true, generate a KSK name, otherwise a DSK name.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that returns the generated key Name.
 */
IdentityStorage.prototype.getNewKeyNamePromise = function
  (identityName, useKsk, useSync)
{
  var timestamp = Math.floor(new Date().getTime() / 1000.0);
  while (timestamp <= IdentityStorage.lastTimestamp)
    // Make the timestamp unique.
    timestamp += 1;
  IdentityStorage.lastTimestamp = timestamp;

  // Get the number of seconds as a string.
  var seconds = "" + timestamp;

  var keyIdStr;
  if (useKsk)
    keyIdStr = "ksk-" + seconds;
  else
    keyIdStr = "dsk-" + seconds;

  var keyName = new Name(identityName).append(keyIdStr);

  return this.doesKeyExistPromise(keyName, useSync)
  .then(function(exists) {
    if (exists)
      throw new SecurityException(new Error("Key name already exists"));

    return SyncPromise.resolve(keyName);
  });
};

/**
 * Generate a name for a new key belonging to the identity.
 * @param {Name} identityName The identity name.
 * @param {boolean} useKsk If true, generate a KSK name, otherwise a DSK name.
 * @return {Name} The generated key name.
 * @throws Error If getNewKeyNamePromise doesn't return a SyncPromise which
 * is already fulfilled.
 */
IdentityStorage.prototype.getNewKeyName = function(identityName, useKsk)
{
  return SyncPromise.getValue
    (this.getNewKeyNamePromise(identityName, useKsk, true));
};

/**
 * Check if the specified key already exists.
 * @param {Name} keyName The name of the key.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which returns true if the key exists.
 */
IdentityStorage.prototype.doesKeyExistPromise = function(keyName, useSync)
{
  return SyncPromise.reject(new Error
    ("IdentityStorage.doesKeyExistPromise is not implemented"));
};

/**
 * Check if the specified key already exists.
 * @param {Name} keyName The name of the key.
 * @return {boolean} true if the key exists, otherwise false.
 * @throws Error If doesKeyExistPromise doesn't return a SyncPromise which
 * is already fulfilled.
 */
IdentityStorage.prototype.doesKeyExist = function(keyName)
{
  return SyncPromise.getValue(this.doesKeyExistPromise(keyName, true));
};

/**
 * Add a public key to the identity storage. Also call addIdentity to ensure
 * that the identityName for the key exists. However, if the key already
 * exists, do nothing.
 * @param {Name} keyName The name of the public key to be added.
 * @param {number} keyType Type of the public key to be added from KeyType, such
 * as KeyType.RSA..
 * @param {Blob} publicKeyDer A blob of the public key DER to be added.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which fulfills when complete.
 */
IdentityStorage.prototype.addKeyPromise = function
  (keyName, keyType, publicKeyDer, useSync)
{
  return SyncPromise.reject(new Error
    ("IdentityStorage.addKeyPromise is not implemented"));
};

/**
 * Add a public key to the identity storage. Also call addIdentity to ensure
 * that the identityName for the key exists.
 * @param {Name} keyName The name of the public key to be added.
 * @param {number} keyType Type of the public key to be added from KeyType, such
 * as KeyType.RSA..
 * @param {Blob} publicKeyDer A blob of the public key DER to be added.
 * @throws SecurityException if a key with the keyName already exists.
 * @throws Error If addKeyPromise doesn't return a SyncPromise which
 * is already fulfilled.
 */
IdentityStorage.prototype.addKey = function(keyName, keyType, publicKeyDer)
{
  return SyncPromise.getValue
    (this.addKeyPromise(keyName, keyType, publicKeyDer, true));
};

/**
 * Get the public key DER blob from the identity storage.
 * @param {Name} keyName The name of the requested public key.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which returns the DER Blob, or a
 * promise rejected with SecurityException if the key doesn't exist.
 */
IdentityStorage.prototype.getKeyPromise = function(keyName, useSync)
{
  return SyncPromise.reject(new Error
    ("IdentityStorage.getKeyPromise is not implemented"));
};

/**
 * Get the public key DER blob from the identity storage.
 * @param {Name} keyName The name of the requested public key.
 * @return {Blob} The DER Blob.
 * @throws SecurityException if the key doesn't exist.
 * @throws Error If getKeyPromise doesn't return a SyncPromise which
 * is already fulfilled.
 */
IdentityStorage.prototype.getKey = function(keyName)
{
  return SyncPromise.getValue(this.getKeyPromise(keyName, true));
};

/**
 * Activate a key.  If a key is marked as inactive, its private part will not be
 * used in packet signing.
 * @param {Name} keyName name of the key
 */
IdentityStorage.prototype.activateKey = function(keyName)
{
  throw new Error("IdentityStorage.activateKey is not implemented");
};

/**
 * Deactivate a key. If a key is marked as inactive, its private part will not
 * be used in packet signing.
 * @param {Name} keyName name of the key
 */
IdentityStorage.prototype.deactivateKey = function(keyName)
{
  throw new Error("IdentityStorage.deactivateKey is not implemented");
};

/**
 * Check if the specified certificate already exists.
 * @param {Name} certificateName The name of the certificate.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which returns true if the certificate
 * exists.
 */
IdentityStorage.prototype.doesCertificateExistPromise = function
  (certificateName, useSync)
{
  return SyncPromise.reject(new Error
    ("IdentityStorage.doesCertificateExistPromise is not implemented"));
};

/**
 * Check if the specified certificate already exists.
 * @param {Name} certificateName The name of the certificate.
 * @return {boolean} true if the certificate exists, otherwise false.
 * @throws Error If doesCertificateExistPromise doesn't return a SyncPromise
 * which is already fulfilled.
 */
IdentityStorage.prototype.doesCertificateExist = function(certificateName)
{
  return SyncPromise.getValue
    (this.doesCertificateExistPromise(certificateName, true));
};

/**
 * Add a certificate to the identity storage. Also call addKey to ensure that
 * the certificate key exists. If the certificate is already installed, don't
 * replace it.
 * @param {IdentityCertificate} certificate The certificate to be added.  This
 * makes a copy of the certificate.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which fulfills when finished.
 */
IdentityStorage.prototype.addCertificatePromise = function(certificate, useSync)
{
  return SyncPromise.reject(new Error
    ("IdentityStorage.addCertificatePromise is not implemented"));
};

/**
 * Add a certificate to the identity storage.
 * @param {IdentityCertificate} certificate The certificate to be added.  This
 * makes a copy of the certificate.
 * @throws SecurityException if the certificate is already installed.
 * @throws Error If addCertificatePromise doesn't return a SyncPromise which
 * is already fulfilled.
 */
IdentityStorage.prototype.addCertificate = function(certificate)
{
  return SyncPromise.getValue(this.addCertificatePromise(certificate, true));
};

/**
 * Get a certificate from the identity storage.
 * @param {Name} certificateName The name of the requested certificate.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which returns the requested
 * IdentityCertificate, or a promise rejected with SecurityException if the
 * certificate doesn't exist.
 */
IdentityStorage.prototype.getCertificatePromise = function
  (certificateName, useSync)
{
  return SyncPromise.reject(new Error
    ("IdentityStorage.getCertificatePromise is not implemented"));
};

/**
 * Get a certificate from the identity storage.
 * @param {Name} certificateName The name of the requested certificate.
 * @return {IdentityCertificate} The requested certificate.
 * @throws SecurityException if the certificate doesn't exist.
 * @throws Error If getCertificatePromise doesn't return a SyncPromise which
 * is already fulfilled.
 */
IdentityStorage.prototype.getCertificate = function(certificateName)
{
  return SyncPromise.getValue(this.getValuePromise(certificateName, true));
};

/**
 * Get the TPM locator associated with this storage.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise|SyncPromise} A promise which returns the TPM locator, or a
 * promise rejected with SecurityException if the TPM locator doesn't exist.
 */
IdentityStorage.prototype.getTpmLocatorPromise = function(useSync)
{
  return SyncPromise.reject(new Error
    ("IdentityStorage.getTpmLocatorPromise is not implemented"));
};

/**
 * Get the TPM locator associated with this storage.
 * @return {string} The TPM locator.
 * @throws SecurityException if the TPM locator doesn't exist.
 * @throws Error If getTpmLocatorPromise doesn't return a SyncPromise which is
 * already fulfilled.
 */
IdentityStorage.prototype.getTpmLocator = function()
{
  return SyncPromise.getValue(this.getTpmLocatorPromise(true));
};

/*****************************************
 *           Get/Set Default             *
 *****************************************/

/**
 * Get the default identity.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which returns the Name of default
 * identity, or a promise rejected with SecurityException if the default
 * identity is not set.
 */
IdentityStorage.prototype.getDefaultIdentityPromise = function(useSync)
{
  return SyncPromise.reject(new Error
    ("IdentityStorage.getDefaultIdentityPromise is not implemented"));
};

/**
 * Get the default identity.
 * @return {Name} The name of default identity.
 * @throws SecurityException if the default identity is not set.
 * @throws Error If getDefaultIdentityPromise doesn't return a SyncPromise
 * which is already fulfilled.
 */
IdentityStorage.prototype.getDefaultIdentity = function()
{
  return SyncPromise.getValue
    (this.getDefaultIdentityPromise(true));
};

/**
 * Get the default key name for the specified identity.
 * @param {Name} identityName The identity name.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which returns the default key Name,
 * or a promise rejected with SecurityException if the default key name for the
 * identity is not set.
 */
IdentityStorage.prototype.getDefaultKeyNameForIdentityPromise = function
  (identityName, useSync)
{
  return SyncPromise.reject(new Error
    ("IdentityStorage.getDefaultKeyNameForIdentityPromise is not implemented"));
};

/**
 * Get the default key name for the specified identity.
 * @param {Name} identityName The identity name.
 * @return {Name} The default key name.
 * @throws SecurityException if the default key name for the identity is not set.
 * @throws Error If getDefaultKeyNameForIdentityPromise doesn't return a
 * SyncPromise which is already fulfilled.
 */
IdentityStorage.prototype.getDefaultKeyNameForIdentity = function(identityName)
{
  return SyncPromise.getValue
    (this.getDefaultKeyNameForIdentityPromise(identityName, true));
};

/**
 * Get the default certificate name for the specified identity.
 * @param {Name} identityName The identity name.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which returns the default certificate
 * Name, or a promise rejected with SecurityException if the default key name
 * for the identity is not set or the default certificate name for the key name
 * is not set.
 */
IdentityStorage.prototype.getDefaultCertificateNameForIdentityPromise = function
  (identityName, useSync)
{
  var thisStorage = this;
  return this.getDefaultKeyNameForIdentityPromise(identityName)
  .then(function(keyName) {
    return thisStorage.getDefaultCertificateNameForKeyPromise(keyName);
  });
};

/**
 * Get the default certificate name for the specified identity.
 * @param {Name} identityName The identity name.
 * @return {Name} The default certificate name.
 * @throws SecurityException if the default key name for the identity is not
 * set or the default certificate name for the key name is not set.
 * @throws Error If getDefaultCertificateNameForIdentityPromise doesn't return
 * a SyncPromise which is already fulfilled.
 */
IdentityStorage.prototype.getDefaultCertificateNameForIdentity = function
  (identityName)
{
  return SyncPromise.getValue
    (this.getDefaultCertificateNameForIdentityPromise(identityName, true));
};

/**
 * Get the default certificate name for the specified key.
 * @param {Name} keyName The key name.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which returns the default certificate
 * Name, or a promise rejected with SecurityException if the default certificate
 * name for the key name is not set.
 */
IdentityStorage.prototype.getDefaultCertificateNameForKeyPromise = function
  (keyName, useSync)
{
  return SyncPromise.reject(new Error
    ("IdentityStorage.getDefaultCertificateNameForKeyPromise is not implemented"));
};

/**
 * Get the default certificate name for the specified key.
 * @param {Name} keyName The key name.
 * @return {Name} The default certificate name.
 * @throws SecurityException if the default certificate name for the key name
 * is not set.
 * @throws Error If getDefaultCertificateNameForKeyPromise doesn't return a
 * SyncPromise which is already fulfilled.
 */
IdentityStorage.prototype.getDefaultCertificateNameForKey = function(keyName)
{
  return SyncPromise.getValue
    (this.getDefaultCertificateNameForKeyPromise(keyName, true));
};

/**
 * Append all the identity names to the nameList.
 * @param {Array<Name>} nameList Append result names to nameList.
 * @param {boolean} isDefault If true, add only the default identity name. If
 * false, add only the non-default identity names.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise which fulfills when the names are added to
 * nameList.
 */
IdentityStorage.prototype.getAllIdentitiesPromise = function
  (nameList, isDefault, useSync)
{
  return SyncPromise.reject(new Error
    ("IdentityStorage.getAllIdentitiesPromise is not implemented"));
};

/**
 * Append all the key names of a particular identity to the nameList.
 * @param {Name} identityName The identity name to search for.
 * @param {Array<Name>} nameList Append result names to nameList.
 * @param {boolean} isDefault If true, add only the default key name. If false,
 * add only the non-default key names.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which fulfills when the names are
 * added to nameList.
 */
IdentityStorage.prototype.getAllKeyNamesOfIdentityPromise = function
  (identityName, nameList, isDefault, useSync)
{
  return SyncPromise.reject(new Error
    ("IdentityStorage.getAllKeyNamesOfIdentityPromise is not implemented"));
};

/**
 * Append all the certificate names of a particular key name to the nameList.
 * @param {Name} keyName The key name to search for.
 * @param {Array<Name>} nameList Append result names to nameList.
 * @param {boolean} isDefault If true, add only the default certificate name.
 * If false, add only the non-default certificate names.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise which fulfills when the names are added to
 * nameList.
 */
IdentityStorage.prototype.getAllCertificateNamesOfKeyPromise = function
  (keyName, nameList, isDefault, useSync)
{
  return SyncPromise.reject(new Error
    ("IdentityStorage.getAllCertificateNamesOfKeyPromise is not implemented"));
};

/**
 * Append all the key names of a particular identity to the nameList.
 * @param {Name} identityName The identity name to search for.
 * @param {Array<Name>} nameList Append result names to nameList.
 * @param {boolean} isDefault If true, add only the default key name. If false,
 * add only the non-default key names.
 * @throws Error If getAllKeyNamesOfIdentityPromise doesn't return a
 * SyncPromise which is already fulfilled.
 */
IdentityStorage.prototype.getAllKeyNamesOfIdentity = function
  (identityName, nameList, isDefault)
{
  return SyncPromise.getValue
    (this.getAllKeyNamesOfIdentityPromise(identityName, nameList, isDefault, true));
};

/**
 * Set the default identity.  If the identityName does not exist, then clear the
 * default identity so that getDefaultIdentity() throws an exception.
 * @param {Name} identityName The default identity name.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which fulfills when the default
 * identity is set.
 */
IdentityStorage.prototype.setDefaultIdentityPromise = function
  (identityName, useSync)
{
  return SyncPromise.reject(new Error
    ("IdentityStorage.setDefaultIdentityPromise is not implemented"));
};

/**
 * Set the default identity.  If the identityName does not exist, then clear the
 * default identity so that getDefaultIdentity() throws an exception.
 * @param {Name} identityName The default identity name.
 * @throws Error If setDefaultIdentityPromise doesn't return a SyncPromise which
 * is already fulfilled.
 */
IdentityStorage.prototype.setDefaultIdentity = function(identityName)
{
  return SyncPromise.getValue
    (this.setDefaultIdentityPromise(identityName, true));
};

/**
 * Set a key as the default key of an identity. The identity name is inferred
 * from keyName.
 * @param {Name} keyName The name of the key.
 * @param {Name} identityNameCheck (optional) The identity name to check that the
 * keyName contains the same identity name. If an empty name, it is ignored.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which fulfills when the default key
 * name is set.
 */
IdentityStorage.prototype.setDefaultKeyNameForIdentityPromise = function
  (keyName, identityNameCheck, useSync)
{
  return SyncPromise.reject(new Error
    ("IdentityStorage.setDefaultKeyNameForIdentityPromise is not implemented"));
};

/**
 * Set a key as the default key of an identity. The identity name is inferred
 * from keyName.
 * @param {Name} keyName The name of the key.
 * @param {Name} identityNameCheck (optional) The identity name to check that the
 * keyName contains the same identity name. If an empty name, it is ignored.
 * @throws Error If setDefaultKeyNameForIdentityPromise doesn't return a
 * SyncPromise which is already fulfilled.
 */
IdentityStorage.prototype.setDefaultKeyNameForIdentity = function
  (keyName, identityNameCheck)
{
  return SyncPromise.getValue
    (this.setDefaultKeyNameForIdentityPromise(keyName, identityNameCheck, true));
};

/**
 * Set the default key name for the specified identity.
 * @param {Name} keyName The key name.
 * @param {Name} certificateName The certificate name.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which fulfills when the default
 * certificate name is set.
 */
IdentityStorage.prototype.setDefaultCertificateNameForKeyPromise = function
  (keyName, certificateName, useSync)
{
  return SyncPromise.reject(new Error
    ("IdentityStorage.setDefaultCertificateNameForKeyPromise is not implemented"));
};

/**
 * Set the default key name for the specified identity.
 * @param {Name} keyName The key name.
 * @param {Name} certificateName The certificate name.
 * @throws Error If setDefaultCertificateNameForKeyPromise doesn't return a
 * SyncPromise which is already fulfilled.
 */
IdentityStorage.prototype.setDefaultCertificateNameForKey = function
  (keyName, certificateName)
{
  return SyncPromise.getValue
    (this.setDefaultCertificateNameForKeyPromise(keyName, certificateName, true));
};

/**
 * Get the certificate of the default identity.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which returns the requested
 * IdentityCertificate or null if not found.
 */
IdentityStorage.prototype.getDefaultCertificatePromise = function(useSync)
{
  var thisStorage = this;
  return this.getDefaultIdentityPromise(useSync)
  .then(function(identityName) {
    return thisStorage.getDefaultCertificateNameForIdentityPromise
      (identityName, useSync);
  }, function(ex) {
    // The default is not defined.
    return SyncPromise.resolve(null);
  })
  .then(function(certName) {
    if (certName == null)
      return SyncPromise.resolve(null);

    return thisStorage.getCertificatePromise(certName, useSync);
  });
};

/**
 * Get the certificate of the default identity.
 * @return {IdentityCertificate} The requested certificate.  If not found,
 * return null.
 * @throws Error If getDefaultCertificatePromise doesn't return a SyncPromise
 * which is already fulfilled.
 */
IdentityStorage.prototype.getDefaultCertificate = function()
{
  return SyncPromise.getValue
    (this.getDefaultCertificatePromise(true));
};

/*****************************************
 *            Delete Methods             *
 *****************************************/

/**
 * Delete a certificate.
 * @param {Name} certificateName The certificate name.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which fulfills when the certificate
 * info is deleted.
 */
IdentityStorage.prototype.deleteCertificateInfoPromise = function
  (certificateName, useSync)
{
  return SyncPromise.reject(new Error
    ("IdentityStorage.deleteCertificateInfoPromise is not implemented"));
};

/**
 * Delete a certificate.
 * @param {Name} certificateName The certificate name.
 * @throws Error If deleteCertificateInfoPromise doesn't return a SyncPromise
 * which is already fulfilled.
 */
IdentityStorage.prototype.deleteCertificateInfo = function(certificateName)
{
  return SyncPromise.getValue
    (this.deleteCertificateInfoPromise(certificateName, true));
};

/**
 * Delete a public key and related certificates.
 * @param {Name} keyName The key name.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which fulfills when the public key
 * info is deleted.
 */
IdentityStorage.prototype.deletePublicKeyInfoPromise = function(keyName, useSync)
{
  return SyncPromise.reject
    (new Error("IdentityStorage.deletePublicKeyInfoPromise is not implemented"));
};

/**
 * Delete a public key and related certificates.
 * @param {Name} keyName The key name.
 * @throws Error If deletePublicKeyInfoPromise doesn't return a SyncPromise
 * which is already fulfilled.
 */
IdentityStorage.prototype.deletePublicKeyInfo = function(keyName)
{
  return SyncPromise.getValue
    (this.deletePublicKeyInfoPromise(keyName, true));
};

/**
 * Delete an identity and related public keys and certificates.
 * @param {Name} identityName The identity name.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which fulfills when the identity info
 * is deleted.
 */
IdentityStorage.prototype.deleteIdentityInfoPromise = function
  (identityName, useSync)
{
  return SyncPromise.reject(new Error
    ("IdentityStorage.deleteIdentityInfoPromise is not implemented"));
};

/**
 * Delete an identity and related public keys and certificates.
 * @param {Name} identityName The identity name.
 * @throws Error If deleteIdentityInfoPromise doesn't return a SyncPromise
 * which is already fulfilled.
 */
IdentityStorage.prototype.deleteIdentityInfo = function(identityName)
{
  return SyncPromise.getValue
    (this.deleteIdentityInfoPromise(identityName, true));
};

// Track the lastTimestamp so that each timestamp is unique.
IdentityStorage.lastTimestamp = Math.floor(new Date().getTime() / 1000.0);
/**
 * Copyright (C) 2015-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

// Don't require modules since this is meant for the browser, not Node.js.

/**
 * IndexedDbIdentityStorage extends IdentityStorage and implements its methods
 * to store identity, public key and certificate objects using the browser's
 * IndexedDB service.
 * @constructor
 */
var IndexedDbIdentityStorage = function IndexedDbIdentityStorage()
{
  IdentityStorage.call(this);

  this.database = new Dexie("ndnsec-public-info");
  // The database schema imitates MemoryIdentityStorage.
  this.database.version(1).stores({
    // A table for global values. It currently only has the defaultIdentityUri.
    // "key" is the key like "defaultIdentityUri" // string
    // "value" is the value. For "defaultIdentityUri" the value is the
    //         default identity name URI, or absent if not defined. // string
    globals: "key",

    // "identityNameUri" is the identity name URI          // string
    // "defaultKeyUri" is the default key name URI or null // string
    identity: "identityNameUri",

    // "keyNameUri" is the key name URI                             // string
    // "keyType" is the type of the public key            // number from KeyType
    // "keyDer" is the public key DER                               // Uint8Array
    // "defaultCertificateUri" is the default cert name URI or null // string
    publicKey: "keyNameUri",

    // "certificateNameUri" is the certificate name URI // string
    // "encoding" is the certificate wire encoding      // Uint8Array
    certificate: "certificateNameUri"
  });
  this.database.open();
};

IndexedDbIdentityStorage.prototype = new IdentityStorage();
IndexedDbIdentityStorage.prototype.name = "IndexedDbIdentityStorage";

/**
 * Check if the specified identity already exists.
 * @param {Name} identityName The identity name.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise which returns true if the identity exists.
 */
IndexedDbIdentityStorage.prototype.doesIdentityExistPromise = function
  (identityName, useSync)
{
  if (useSync)
    return Promise.reject(new SecurityException(new Error
      ("IndexedDbIdentityStorage.doesIdentityExistPromise is only supported for async")));

  return this.database.identity.where("identityNameUri").equals
    (identityName.toUri())
  .count()
  .then(function(count) {
    return Promise.resolve(count > 0);
  });
};

/**
 * Add a new identity. Do nothing if the identity already exists.
 * @param {Name} identityName The identity name to be added.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise which fulfills when the identity is added.
 */
IndexedDbIdentityStorage.prototype.addIdentityPromise = function
  (identityName, useSync)
{
  if (useSync)
    return Promise.reject(new SecurityException(new Error
      ("IndexedDbIdentityStorage.addIdentityPromise is only supported for async")));

  var thisStorage = this;
  return this.doesIdentityExistPromise(identityName)
  .then(function(exists) {
    if (exists)
      // Do nothing.
      return Promise.resolve();

    return thisStorage.database.identity.put
      ({ identityNameUri: identityName.toUri(), defaultKeyUri: null });
  });
};

/**
 * Check if the specified key already exists.
 * @param {Name} keyName The name of the key.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise which returns true if the key exists.
 */
IndexedDbIdentityStorage.prototype.doesKeyExistPromise = function
  (keyName, useSync)
{
  if (useSync)
    return Promise.reject(new SecurityException(new Error
      ("IndexedDbIdentityStorage.doesKeyExistPromise is only supported for async")));

  return this.database.publicKey.where("keyNameUri").equals(keyName.toUri())
  .count()
  .then(function(count) {
    return Promise.resolve(count > 0);
  });
};

/**
 * Add a public key to the identity storage. Also call addIdentity to ensure
 * that the identityName for the key exists. However, if the key already
   * exists, do nothing.
 * @param {Name} keyName The name of the public key to be added.
 * @param {number} keyType Type of the public key to be added from KeyType, such
 * as KeyType.RSA..
 * @param {Blob} publicKeyDer A blob of the public key DER to be added.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise which fulfills when complete.
 */
IndexedDbIdentityStorage.prototype.addKeyPromise = function
  (keyName, keyType, publicKeyDer, useSync)
{
  if (useSync)
    return Promise.reject(new SecurityException(new Error
      ("IndexedDbIdentityStorage.addKeyPromise is only supported for async")));

  if (keyName.size() === 0)
    return Promise.resolve();

  var thisStorage = this;
  return this.doesKeyExistPromise(keyName)
  .then(function(exists) {
    if (exists)
      return Promise.resolve();

    var identityName = keyName.getPrefix(-1);
    return thisStorage.addIdentityPromise(identityName)
    .then(function() {
      return thisStorage.database.publicKey.put
        ({ keyNameUri: keyName.toUri(), keyType: keyType,
           keyDer: new Blob(publicKeyDer, true).buf(),
           defaultCertificate: null });
    });
  });
};

/**
 * Get the public key DER blob from the identity storage.
 * @param {Name} keyName The name of the requested public key.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise which returns the DER Blob, or a promise rejected
 * with SecurityException if the key doesn't exist.
 */
IndexedDbIdentityStorage.prototype.getKeyPromise = function(keyName, useSync)
{
  if (useSync)
    return Promise.reject(new SecurityException(new Error
      ("IndexedDbIdentityStorage.getKeyPromise is only supported for async")));

  if (keyName.size() === 0)
    return Promise.reject(new SecurityException(new Error
      ("IndexedDbIdentityStorage::getKeyPromise: Empty keyName")));

  return this.database.publicKey.get(keyName.toUri())
  .then(function(publicKeyEntry) {
    if (publicKeyEntry)
      return Promise.resolve(new Blob(publicKeyEntry.keyDer));
    else
      return Promise.reject(new SecurityException(new Error
        ("IndexedDbIdentityStorage::getKeyPromise: The key does not exist")));
  });
};

/**
 * Check if the specified certificate already exists.
 * @param {Name} certificateName The name of the certificate.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise which returns true if the certificate exists.
 */
IndexedDbIdentityStorage.prototype.doesCertificateExistPromise = function
  (certificateName, useSync)
{
  if (useSync)
    return Promise.reject(new SecurityException(new Error
      ("IndexedDbIdentityStorage.doesCertificateExistPromise is only supported for async")));

  return this.database.certificate.where("certificateNameUri").equals
    (certificateName.toUri())
  .count()
  .then(function(count) {
    return Promise.resolve(count > 0);
  });
};

/**
 * Add a certificate to the identity storage. Also call addKey to ensure that
 * the certificate key exists. If the certificate is already installed, don't
 * replace it.
 * @param {IdentityCertificate} certificate The certificate to be added.  This
 * makes a copy of the certificate.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise which fulfills when finished.
 */
IndexedDbIdentityStorage.prototype.addCertificatePromise = function
  (certificate, useSync)
{
  if (useSync)
    return Promise.reject(new SecurityException(new Error
      ("IndexedDbIdentityStorage.addCertificatePromise is only supported for async")));

  var certificateName = certificate.getName();
  var keyName = certificate.getPublicKeyName();

  var thisStorage = this;
  return this.addKeyPromise
    (keyName, certificate.getPublicKeyInfo().getKeyType(),
     certificate.getPublicKeyInfo().getKeyDer(), useSync)
  .then(function() {
    return thisStorage.doesCertificateExistPromise(certificateName);
  })
  .then(function(exists) {
    if (exists)
      return Promise.resolve();

    // Insert the certificate.
    // wireEncode returns the cached encoding if available.
    return thisStorage.database.certificate.put
      ({ certificateNameUri: certificateName.toUri(),
         encoding: certificate.wireEncode().buf() });
  });
};

/**
 * Get a certificate from the identity storage.
 * @param {Name} certificateName The name of the requested certificate.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise which returns the requested
 * IdentityCertificate, or a promise rejected with SecurityException if the
 * certificate doesn't exist.
 */
IndexedDbIdentityStorage.prototype.getCertificatePromise = function
  (certificateName, useSync)
{
  if (useSync)
    return Promise.reject(new SecurityException(new Error
      ("IndexedDbIdentityStorage.getCertificatePromise is only supported for async")));

  return this.database.certificate.get(certificateName.toUri())
  .then(function(certificateEntry) {
    if (certificateEntry) {
      var certificate = new IdentityCertificate();
      try {
        certificate.wireDecode(certificateEntry.encoding);
      } catch (ex) {
        return Promise.reject(new SecurityException(new Error
          ("IndexedDbIdentityStorage::getCertificatePromise: The certificate cannot be decoded")));
      }
      return Promise.resolve(certificate);
    }
    else
      return Promise.reject(new SecurityException(new Error
        ("IndexedDbIdentityStorage::getCertificatePromise: The certificate does not exist")));
  });
};

/*****************************************
 *           Get/Set Default             *
 *****************************************/

/**
 * Get the default identity.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise which returns the Name of default identity,
 * or a promise rejected with SecurityException if the default identity is not
 * set.
 */
IndexedDbIdentityStorage.prototype.getDefaultIdentityPromise = function(useSync)
{
  return this.database.globals.get("defaultIdentityUri")
  .then(function(defaultIdentityEntry) {
    if (defaultIdentityEntry)
      return Promise.resolve(new Name(defaultIdentityEntry.value));
    else
      throw new SecurityException(new Error
        ("IndexedDbIdentityStorage.getDefaultIdentity: The default identity is not defined"));
  });
};

/**
 * Get the default key name for the specified identity.
 * @param {Name} identityName The identity name.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise which returns the default key Name, or a
 * promise rejected with SecurityException if the default key name for the
 * identity is not set.
 */
IndexedDbIdentityStorage.prototype.getDefaultKeyNameForIdentityPromise = function
  (identityName, useSync)
{
  if (useSync)
    return Promise.reject(new SecurityException(new Error
      ("IndexedDbIdentityStorage.getDefaultKeyNameForIdentityPromise is only supported for async")));

  return this.database.identity.get(identityName.toUri())
  .then(function(identityEntry) {
    if (identityEntry) {
      if (identityEntry.defaultKeyUri != null)
        return Promise.resolve(new Name(identityEntry.defaultKeyUri));
      else
        throw new SecurityException(new Error("No default key set."));
    }
    else
      throw new SecurityException(new Error("Identity not found."));
  });
};

/**
 * Get the default certificate name for the specified key.
 * @param {Name} keyName The key name.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise which returns the default certificate Name,
 * or a promise rejected with SecurityException if the default certificate name
 * for the key name is not set.
 */
IndexedDbIdentityStorage.prototype.getDefaultCertificateNameForKeyPromise = function
  (keyName, useSync)
{
  if (useSync)
    return Promise.reject(new SecurityException(new Error
      ("IndexedDbIdentityStorage.getDefaultCertificateNameForKeyPromise is only supported for async")));

  return this.database.publicKey.get(keyName.toUri())
  .then(function(publicKeyEntry) {
    if (publicKeyEntry) {
      if (publicKeyEntry.defaultCertificateUri != null)
        return Promise.resolve(new Name(publicKeyEntry.defaultCertificateUri));
      else
        throw new SecurityException(new Error("No default certificate set."));
    }
    else
      throw new SecurityException(new Error("Key not found."));
  });
};

/**
 * Append all the identity names to the nameList.
 * @param {Array<Name>} nameList Append result names to nameList.
 * @param {boolean} isDefault If true, add only the default identity name. If
 * false, add only the non-default identity names.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise which fulfills when the names are added to
 * nameList.
 */
IndexedDbIdentityStorage.prototype.getAllIdentitiesPromise = function
  (nameList, isDefault, useSync)
{
  if (useSync)
    return Promise.reject(new SecurityException(new Error
      ("IndexedDbIdentityStorage.getAllIdentitiesPromise is only supported for async")));

  var defaultIdentityName = null;
  var thisStorage = this;
  return this.getDefaultIdentityPromise()
  .then(function(localDefaultIdentityName) {
    defaultIdentityName = localDefaultIdentityName;
    return SyncPromise.resolve();
  }, function(err) {
    // The default identity name was not found.
    return SyncPromise.resolve();
  })
  .then(function() {
    return thisStorage.database.identity.each(function(identityEntry) {
      var identityName = new Name(identityEntry.identityNameUri);
      var identityNameIsDefault =
        (defaultIdentityName !== null && identityName.equals(defaultIdentityName));
      if (isDefault && identityNameIsDefault)
        nameList.push(identityName);
      else if (!isDefault && !identityNameIsDefault)
        nameList.push(identityName);
    });
  });
};

/**
 * Append all the key names of a particular identity to the nameList.
 * @param {Name} identityName The identity name to search for.
 * @param {Array<Name>} nameList Append result names to nameList.
 * @param {boolean} isDefault If true, add only the default key name. If false,
 * add only the non-default key names.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise which fulfills when the names are added to
 * nameList.
 */
IndexedDbIdentityStorage.prototype.getAllKeyNamesOfIdentityPromise = function
  (identityName, nameList, isDefault, useSync)
{
  if (useSync)
    return Promise.reject(new SecurityException(new Error
      ("IndexedDbIdentityStorage.getAllKeyNamesOfIdentityPromise is only supported for async")));

  var defaultKeyName = null;
  var thisStorage = this;
  return this.getDefaultKeyNameForIdentityPromise(identityName)
  .then(function(localDefaultKeyName) {
    defaultKeyName = localDefaultKeyName;
    return SyncPromise.resolve();
  }, function(err) {
    // The default key name was not found.
    return SyncPromise.resolve();
  })
  .then(function() {
    // Iterate through each publicKey a to find ones that match identityName.
    // This is a little inefficient, but we don't expect the in-browser
    // database to be very big, we don't expect to use this function often (for
    // deleting an identity), and this is simpler than complicating the database
    // schema to store the identityName with each publicKey.
    return thisStorage.database.publicKey.each(function(publicKeyEntry) {
      var keyName = new Name(publicKeyEntry.keyNameUri);
      var keyIdentityName = keyName.getPrefix(-1);

      if (keyIdentityName.equals(identityName)) {
        var keyNameIsDefault =
          (defaultKeyName !== null && keyName.equals(defaultKeyName));
        if (isDefault && keyNameIsDefault)
          nameList.push(keyName);
        else if (!isDefault && !keyNameIsDefault)
          nameList.push(keyName);
      }
    });
  });
};

/**
 * Append all the certificate names of a particular key name to the nameList.
 * @param {Name} keyName The key name to search for.
 * @param {Array<Name>} nameList Append result names to nameList.
 * @param {boolean} isDefault If true, add only the default certificate name.
 * If false, add only the non-default certificate names.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise which fulfills when the names are added to
 * nameList.
 */
IndexedDbIdentityStorage.prototype.getAllCertificateNamesOfKeyPromise = function
  (keyName, nameList, isDefault, useSync)
{
  if (useSync)
    return Promise.reject(new SecurityException(new Error
      ("IndexedDbIdentityStorage.getAllCertificateNamesOfKeyPromise is only supported for async")));

  var defaultCertificateName = null;
  var thisStorage = this;
  return this.getDefaultCertificateNameForKeyPromise(keyName)
  .then(function(localDefaultCertificateName) {
    defaultCertificateName = localDefaultCertificateName;
    return SyncPromise.resolve();
  }, function(err) {
    // The default certificate name was not found.
    return SyncPromise.resolve();
  })
  .then(function() {
    // Iterate through each certificate record a to find ones that match keyName.
    // This is a little inefficient, but we don't expect the in-browser
    // database to be very big, we don't expect to use this function often (for
    // deleting an identity), and this is simpler than complicating the database
    // schema to store the keyName with each certificate record.
    return thisStorage.database.certificate.each(function(certificateEntry) {
      var certificateName = new Name(certificateEntry.certificateNameUri);
      var certificateKeyName = IdentityCertificate.certificateNameToPublicKeyName
        (certificateName);

      if (certificateKeyName.equals(keyName)) {
        var certificateNameIsDefault =
          (defaultCertificateName !== null &&
           certificateName.equals(defaultCertificateName));
        if (isDefault && certificateNameIsDefault)
          nameList.push(certificateName);
        else if (!isDefault && !certificateNameIsDefault)
          nameList.push(certificateName);
      }
    });
  });
};

/**
 * Set the default identity.  If the identityName does not exist, then clear the
 * default identity so that getDefaultIdentity() throws an exception.
 * @param {Name} identityName The default identity name.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise which fulfills when the default identity is set.
 */
IndexedDbIdentityStorage.prototype.setDefaultIdentityPromise = function
  (identityName, useSync)
{
  if (useSync)
    return Promise.reject(new SecurityException(new Error
      ("IndexedDbIdentityStorage.setDefaultIdentityPromise is only supported for async")));

  var thisStorage = this;
  return this.doesIdentityExistPromise(identityName)
  .then(function(exists) {
    if (exists)
      return thisStorage.database.globals.put
        ({ key: "defaultIdentityUri", value: identityName.toUri() });
    else
      // The identity doesn't exist, so clear the default.
      return thisStorage.database.globals.delete("defaultIdentityUri");
  });
};

/**
 * Set a key as the default key of an identity. The identity name is inferred
 * from keyName.
 * @param {Name} keyName The name of the key.
 * @param {Name} identityNameCheck (optional) The identity name to check that the
 * keyName contains the same identity name. If an empty name, it is ignored.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise which fulfills when the default key name is
 * set.
 */
IndexedDbIdentityStorage.prototype.setDefaultKeyNameForIdentityPromise = function
  (keyName, identityNameCheck, useSync)
{
  useSync = (typeof identityNameCheck === "boolean") ? identityNameCheck : useSync;
  identityNameCheck = (identityNameCheck instanceof Name) ? identityNameCheck : null;

  if (useSync)
    return Promise.reject(new SecurityException(new Error
      ("IndexedDbIdentityStorage.setDefaultKeyNameForIdentityPromise is only supported for async")));

  var identityName = keyName.getPrefix(-1);

  if (identityNameCheck != null && identityNameCheck.size() > 0 &&
      !identityNameCheck.equals(identityName))
    return Promise.reject(new SecurityException(new Error
      ("The specified identity name does not match the key name")));

  // update does nothing if the identityName doesn't exist.
  return this.database.identity.update
    (identityName.toUri(), { defaultKeyUri: keyName.toUri() });
};

/**
 * Set the default key name for the specified identity.
 * @param {Name} keyName The key name.
 * @param {Name} certificateName The certificate name.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise which fulfills when the default certificate
 * name is set.
 */
IndexedDbIdentityStorage.prototype.setDefaultCertificateNameForKeyPromise = function
  (keyName, certificateName, useSync)
{
  if (useSync)
    return Promise.reject(new SecurityException(new Error
      ("IndexedDbIdentityStorage.setDefaultCertificateNameForKeyPromise is only supported for async")));

  // update does nothing if the keyName doesn't exist.
  return this.database.publicKey.update
    (keyName.toUri(), { defaultCertificateUri: certificateName.toUri() });
};

/*****************************************
 *            Delete Methods             *
 *****************************************/

/**
 * Delete a certificate.
 * @param {Name} certificateName The certificate name.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise which fulfills when the certificate info is
 * deleted.
 */
IndexedDbIdentityStorage.prototype.deleteCertificateInfoPromise = function
  (certificateName, useSync)
{
  if (useSync)
    return Promise.reject(new SecurityException(new Error
      ("IndexedDbIdentityStorage.deleteCertificateInfoPromise is only supported for async")));

  if (certificateName.size() === 0)
    return Promise.resolve();

  return this.database.certificate.delete(certificateName.toUri());
};

/**
 * Delete a public key and related certificates.
 * @param {Name} keyName The key name.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise which fulfills when the public key info is
 * deleted.
 */
IndexedDbIdentityStorage.prototype.deletePublicKeyInfoPromise = function
  (keyName, useSync)
{
  if (useSync)
    return Promise.reject(new SecurityException(new Error
      ("IndexedDbIdentityStorage.deletePublicKeyInfoPromise is only supported for async")));

  if (keyName.size() === 0)
    return Promise.resolve();

  var thisStorage = this;
  return this.database.publicKey.delete(keyName.toUri())
  .then(function() {
    // Iterate through each certificate to find ones that match keyName. This is
    // a little inefficient, but we don't expect the in-browswer database to be
    // very big, we don't expect to delete often, and this is simpler than
    // complicating the database schema to store the keyName with each certificate.
    return thisStorage.database.certificate.each(function(certificateEntry) {
      if (IdentityCertificate.certificateNameToPublicKeyName
          (new Name(certificateEntry.certificateNameUri)).equals(keyName))
        thisStorage.database.certificate.delete
          (certificateEntry.certificateNameUri);
    });
  });
};

/**
 * Delete an identity and related public keys and certificates.
 * @param {Name} identityName The identity name.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise which fulfills when the identity info is
 * deleted.
 */
IndexedDbIdentityStorage.prototype.deleteIdentityInfoPromise = function
  (identityName, useSync)
{
  if (useSync)
    return Promise.reject(new SecurityException(new Error
      ("IndexedDbIdentityStorage.deleteIdentityInfoPromise is only supported for async")));

  var thisStorage = this;
  return this.database.identity.delete(identityName.toUri())
  // Iterate through each publicKey and certificate to find ones that match
  // identityName. This is a little inefficient, but we don't expect the
  // in-browswer database to be very big, we don't expect to delete often, and
  // this is simpler than complicating the database schema to store the
  // identityName with each publicKey and certificate.
  .then(function() {
    return thisStorage.database.publicKey.each(function(publicKeyEntry) {
      var keyIdentityName = new Name(publicKeyEntry.keyNameUri).getPrefix(-1);
      if (keyIdentityName.equals(identityName))
        thisStorage.database.publicKey.delete(publicKeyEntry.keyNameUri);
    });
  })
  .then(function() {
    return thisStorage.database.certificate.each(function(certificateEntry) {
      var certificateKeyName = IdentityCertificate.certificateNameToPublicKeyName
        (new Name(certificateEntry.certificateNameUri));
      var certificateIdentityName = certificateKeyName.getPrefix(-1);
      if (certificateIdentityName.equals(identityName))
        thisStorage.database.certificate.delete
          (certificateEntry.certificateNameUri);
    });
  });
};
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
 *
 * 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.
 */

/** @ignore */
var Name = require('../../name.js').Name; /** @ignore */
var Blob = require('../../util/blob.js').Blob; /** @ignore */
var SecurityException = require('../security-exception.js').SecurityException; /** @ignore */
var IdentityCertificate = require('../certificate/identity-certificate.js').IdentityCertificate; /** @ignore */
var SyncPromise = require('../../util/sync-promise.js').SyncPromise; /** @ignore */
var IdentityStorage = require('./identity-storage.js').IdentityStorage;

/**
 * MemoryIdentityStorage extends IdentityStorage and implements its methods to
 * store identity, public key and certificate objects in memory. The application
 * must get the objects through its own means and add the objects to the
 * MemoryIdentityStorage object. To use permanent file-based storage, see
 * BasicIdentityStorage.
 * @constructor
 */
var MemoryIdentityStorage = function MemoryIdentityStorage()
{
  // Call the base constructor.
  IdentityStorage.call(this);

  // The map key is the identityName.toUri(). The value is the object
  //   {defaultKey // Name
  //   }.
  this.identityStore = {};
  // The default identity in identityStore, or "" if not defined.
  this.defaultIdentity = "";
  // The key is the keyName.toUri(). The value is the object
  //  {keyType, // number from KeyType
  //   keyDer   // Blob
  //   defaultCertificate // Name
  //  }.
  this.keyStore = {};
  // The key is the key is the certificateName.toUri(). The value is the
  //   encoded certificate.
  this.certificateStore = {};
};

MemoryIdentityStorage.prototype = new IdentityStorage();
MemoryIdentityStorage.prototype.name = "MemoryIdentityStorage";

exports.MemoryIdentityStorage = MemoryIdentityStorage;
/**
 * Check if the specified identity already exists.
 * @param {Name} identityName The identity name.
 * @return {SyncPromise} A promise which returns true if the identity exists.
 */
MemoryIdentityStorage.prototype.doesIdentityExistPromise = function(identityName)
{
  return SyncPromise.resolve
    (this.identityStore[identityName.toUri()] !== undefined);
};

/**
 * Add a new identity. Do nothing if the identity already exists.
 * @param {Name} identityName The identity name to be added.
 * @return {SyncPromise} A promise which fulfills when the identity is added.
 */
MemoryIdentityStorage.prototype.addIdentityPromise = function(identityName)
{
  var identityUri = identityName.toUri();
  if (this.identityStore[identityUri] === undefined)
    this.identityStore[identityUri] = { defaultKey: null };

  return SyncPromise.resolve();
};

/**
 * Check if the specified key already exists.
 * @param {Name} keyName The name of the key.
 * @return {SyncPromise} A promise which returns true if the key exists.
 */
MemoryIdentityStorage.prototype.doesKeyExistPromise = function(keyName)
{
  return SyncPromise.resolve(this.keyStore[keyName.toUri()] !== undefined);
};

/**
 * Add a public key to the identity storage. Also call addIdentity to ensure
 * that the identityName for the key exists. However, if the key already
 * exists, do nothing.
 * @param {Name} keyName The name of the public key to be added.
 * @param {number} keyType Type of the public key to be added from KeyType, such
 * as KeyType.RSA..
 * @param {Blob} publicKeyDer A blob of the public key DER to be added.
 * @return {SyncPromise} A promise which fulfills when complete.
 */
MemoryIdentityStorage.prototype.addKeyPromise = function
  (keyName, keyType, publicKeyDer)
{
  if (keyName.size() === 0)
    return SyncPromise.resolve();

  if (this.doesKeyExist(keyName))
    return SyncPromise.resolve();

  var identityName = keyName.getSubName(0, keyName.size() - 1);

  this.addIdentity(identityName);

  this.keyStore[keyName.toUri()] =
    { keyType: keyType, keyDer: new Blob(publicKeyDer), defaultCertificate: null };

  return SyncPromise.resolve();
};

/**
 * Get the public key DER blob from the identity storage.
 * @param {Name} keyName The name of the requested public key.
 * @return {SyncPromise} A promise which returns the DER Blob, or a promise
 * rejected with SecurityException if the key doesn't exist.
 */
MemoryIdentityStorage.prototype.getKeyPromise = function(keyName)
{
  if (keyName.size() === 0)
    return SyncPromise.reject(new SecurityException(new Error
      ("MemoryIdentityStorage::getKeyPromise: Empty keyName")));

  var keyNameUri = keyName.toUri();
  var entry = this.keyStore[keyNameUri];
  if (entry === undefined)
    return SyncPromise.reject(new SecurityException(new Error
      ("MemoryIdentityStorage::getKeyPromise: The key does not exist")));

  return SyncPromise.resolve(entry.keyDer);
};

/**
 * Check if the specified certificate already exists.
 * @param {Name} certificateName The name of the certificate.
 * @return {SyncPromise} A promise which returns true if the certificate exists.
 */
MemoryIdentityStorage.prototype.doesCertificateExistPromise = function
  (certificateName)
{
  return SyncPromise.resolve
    (this.certificateStore[certificateName.toUri()] !== undefined);
};

/**
 * Add a certificate to the identity storage. Also call addKey to ensure that
 * the certificate key exists. If the certificate is already installed, don't
 * replace it.
 * @param {IdentityCertificate} certificate The certificate to be added.  This
 * makes a copy of the certificate.
 * @return {SyncPromise} A promise which fulfills when finished.
 */
MemoryIdentityStorage.prototype.addCertificatePromise = function(certificate)
{
  var certificateName = certificate.getName();
  var keyName = certificate.getPublicKeyName();

  this.addKey(keyName, certificate.getPublicKeyInfo().getKeyType(),
         certificate.getPublicKeyInfo().getKeyDer());

  if (this.doesCertificateExist(certificateName))
    return SyncPromise.resolve();

  // Insert the certificate.
  // wireEncode returns the cached encoding if available.
  this.certificateStore[certificateName.toUri()] = certificate.wireEncode();

  return SyncPromise.resolve();
};

/**
 * Get a certificate from the identity storage.
 * @param {Name} certificateName The name of the requested certificate.
 * @return {SyncPromise} A promise which returns the requested
 * IdentityCertificate, or a promise rejected with SecurityException if the
 * certificate doesn't exist.
 */
MemoryIdentityStorage.prototype.getCertificatePromise = function
  (certificateName)
{
  var certificateNameUri = certificateName.toUri();
  if (this.certificateStore[certificateNameUri] === undefined)
    return SyncPromise.reject(new SecurityException(new Error
      ("MemoryIdentityStorage::getCertificatePromise: The certificate does not exist")));

  var certificate = new IdentityCertificate();
  try {
    certificate.wireDecode(this.certificateStore[certificateNameUri]);
  } catch (ex) {
    return SyncPromise.reject(new SecurityException(new Error
      ("MemoryIdentityStorage::getCertificatePromise: The certificate cannot be decoded")));
  }
  return SyncPromise.resolve(certificate);
};

/**
 * Get the TPM locator associated with this storage.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise|SyncPromise} A promise which returns the TPM locator, or a
 * promise rejected with SecurityException if the TPM locator doesn't exist.
 */
IdentityStorage.prototype.getTpmLocatorPromise = function(useSync)
{
  return SyncPromise.resolve("tpm-memory:");
};

/*****************************************
 *           Get/Set Default             *
 *****************************************/

/**
 * Get the default identity.
 * @return {SyncPromise} A promise which returns the Name of default identity,
 * or a promise rejected with SecurityException if the default identity is not
 * set.
 */
MemoryIdentityStorage.prototype.getDefaultIdentityPromise = function()
{
  if (this.defaultIdentity.length === 0)
    return SyncPromise.reject(new SecurityException(new Error
      ("MemoryIdentityStorage.getDefaultIdentity: The default identity is not defined")));

  return SyncPromise.resolve(new Name(this.defaultIdentity));
};

/**
 * Get the default key name for the specified identity.
 * @param {Name} identityName The identity name.
 * @return {SyncPromise} A promise which returns the default key Name, or a
 * promise rejected with SecurityException if the default key name for the
 * identity is not set.
 */
MemoryIdentityStorage.prototype.getDefaultKeyNameForIdentityPromise = function
  (identityName)
{
  var identityUri = identityName.toUri();
  if (this.identityStore[identityUri] !== undefined) {
    if (this.identityStore[identityUri].defaultKey != null)
      return SyncPromise.resolve(this.identityStore[identityUri].defaultKey);
    else
      return SyncPromise.reject(new SecurityException(new Error
        ("No default key set.")));
  }
  else
    return SyncPromise.reject(new SecurityException(new Error("Identity not found.")));
};

/**
 * Get the default certificate name for the specified key.
 * @param {Name} keyName The key name.
 * @return {SyncPromise} A promise which returns the default certificate Name,
 * or a promise rejected with SecurityException if the default certificate name
 * for the key name is not set.
 */
MemoryIdentityStorage.prototype.getDefaultCertificateNameForKeyPromise = function
  (keyName)
{
  var keyUri = keyName.toUri();
  if (this.keyStore[keyUri] !== undefined) {
    if (this.keyStore[keyUri].defaultCertificate != null)
      return SyncPromise.resolve(this.keyStore[keyUri].defaultCertificate);
    else
      return SyncPromise.reject(new SecurityException(new Error
        ("No default certificate set.")));
  }
  else
    return SyncPromise.reject(new SecurityException(new Error("Key not found.")));
};

/**
 * Set the default identity.  If the identityName does not exist, then clear the
 * default identity so that getDefaultIdentity() throws an exception.
 * @param {Name} identityName The default identity name.
 * @return {SyncPromise} A promise which fulfills when the default identity is set.
 */
MemoryIdentityStorage.prototype.setDefaultIdentityPromise = function
  (identityName)
{
  var identityUri = identityName.toUri();
  if (this.identityStore[identityUri] !== undefined)
    this.defaultIdentity = identityUri;
  else
    // The identity doesn't exist, so clear the default.
    this.defaultIdentity = "";

  return SyncPromise.resolve();
};

/**
 * Set a key as the default key of an identity. The identity name is inferred
 * from keyName.
 * @param {Name} keyName The name of the key.
 * @param {Name} identityNameCheck (optional) The identity name to check that the
 * keyName contains the same identity name. If an empty name, it is ignored.
 * @return {SyncPromise} A promise which fulfills when the default key name is
 * set.
 */
MemoryIdentityStorage.prototype.setDefaultKeyNameForIdentityPromise = function
  (keyName, identityNameCheck)
{
  identityNameCheck = (identityNameCheck instanceof Name) ? identityNameCheck : null;

  var identityName = keyName.getPrefix(-1);

  if (identityNameCheck != null && identityNameCheck.size() > 0 &&
      !identityNameCheck.equals(identityName))
    return SyncPromise.reject(new SecurityException(new Error
      ("The specified identity name does not match the key name")));

  var identityUri = identityName.toUri();
  if (this.identityStore[identityUri] !== undefined)
    this.identityStore[identityUri].defaultKey = new Name(keyName);

  return SyncPromise.resolve();
};

/**
 * Set the default key name for the specified identity.
 * @param {Name} keyName The key name.
 * @param {Name} certificateName The certificate name.
 * @return {SyncPromise} A promise which fulfills when the default certificate
 * name is set.
 */
MemoryIdentityStorage.prototype.setDefaultCertificateNameForKeyPromise = function
  (keyName, certificateName)
{
  var keyUri = keyName.toUri();
  if (this.keyStore[keyUri] !== undefined)
    this.keyStore[keyUri].defaultCertificate = new Name(certificateName);

  return SyncPromise.resolve();
};

/*****************************************
 *            Delete Methods             *
 *****************************************/

/**
 * Delete a certificate.
 * @param {Name} certificateName The certificate name.
 * @return {SyncPromise} A promise which fulfills when the certificate
 * info is deleted.
 */
MemoryIdentityStorage.prototype.deleteCertificateInfoPromise = function
  (certificateName)
{
  return SyncPromise.reject(new Error
    ("MemoryIdentityStorage.deleteCertificateInfoPromise is not implemented"));
};

/**
 * Delete a public key and related certificates.
 * @param {Name} keyName The key name.
 * @return {SyncPromise} A promise which fulfills when the public key info is
 * deleted.
 */
MemoryIdentityStorage.prototype.deletePublicKeyInfoPromise = function(keyName)
{
  return SyncPromise.reject(new Error
    ("MemoryIdentityStorage.deletePublicKeyInfoPromise is not implemented"));
};

/**
 * Delete an identity and related public keys and certificates.
 * @param {Name} identity The identity name.
 * @return {SyncPromise} A promise which fulfills when the identity info is
 * deleted.
 */
MemoryIdentityStorage.prototype.deleteIdentityInfoPromise = function(identity)
{
  return SyncPromise.reject(new Error
    ("MemoryIdentityStorage.deleteIdentityInfoPromise is not implemented"));
};
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
 *
 * 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.
 */

/** @ignore */
var SyncPromise = require('../../util/sync-promise.js').SyncPromise; /** @ignore */
var DerNode = require('../../encoding/der/der-node.js').DerNode;

/**
 * PrivateKeyStorage is an abstract class which declares methods for working
 * with a private key storage. You should use a subclass.
 * @constructor
 */
var PrivateKeyStorage = function PrivateKeyStorage()
{
};

exports.PrivateKeyStorage = PrivateKeyStorage;

/**
 * Generate a pair of asymmetric keys.
 * @param {Name} keyName The name of the key pair.
 * @param {KeyParams} params The parameters of the key.
 * @param {boolean} (optional) useSync If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that fulfills when the pair is
 * generated.
 */
PrivateKeyStorage.prototype.generateKeyPairPromise = function
  (keyName, params, useSync)
{
  return SyncPromise.reject(new Error
    ("PrivateKeyStorage.generateKeyPairPromise is not implemented"));
};

/**
 * Generate a pair of asymmetric keys.
 * @param {Name} keyName The name of the key pair.
 * @param {KeyParams} params The parameters of the key.
 * @throws Error If generateKeyPairPromise doesn't return a SyncPromise which
 * is already fulfilled.
 */
PrivateKeyStorage.prototype.generateKeyPair = function(keyName, params)
{
  SyncPromise.getValue(this.generateKeyPairPromise(keyName, params, true));
};

/**
 * Delete a pair of asymmetric keys. If the key doesn't exist, do nothing.
 * @param {Name} keyName The name of the key pair.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that fulfills when the key pair is
 * deleted.
 */
PrivateKeyStorage.prototype.deleteKeyPairPromise = function(keyName, useSync)
{
  return SyncPromise.reject(new Error
    ("PrivateKeyStorage.deleteKeyPairPromise is not implemented"));
};

/**
 * Delete a pair of asymmetric keys. If the key doesn't exist, do nothing.
 * @param {Name} keyName The name of the key pair.
 * @throws Error If deleteKeyPairPromise doesn't return a SyncPromise which
 * is already fulfilled.
 */
PrivateKeyStorage.prototype.deleteKeyPair = function(keyName)
{
  SyncPromise.getValue(this.deleteKeyPairPromise(keyName, true));
};

/**
 * Get the public key
 * @param {Name} keyName The name of public key.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that returns the PublicKey.
 */
PrivateKeyStorage.prototype.getPublicKeyPromise = function(keyName, useSync)
{
  return SyncPromise.reject(new Error
    ("PrivateKeyStorage.getPublicKeyPromise is not implemented"));
};

/**
 * Get the public key
 * @param {Name} keyName The name of public key.
 * @return {PublicKey} The public key.
 * @throws Error If getPublicKeyPromise doesn't return a SyncPromise which
 * is already fulfilled.
 */
PrivateKeyStorage.prototype.getPublicKey = function(keyName)
{
  return SyncPromise.getValue(this.getPublicKeyPromise(keyName, true));
};

/**
 * Fetch the private key for keyName and sign the data to produce a signature Blob.
 * @param {Buffer} data Pointer to the input byte array.
 * @param {Name} keyName The name of the signing key.
 * @param {number} digestAlgorithm (optional) The digest algorithm from
 * DigestAlgorithm, such as DigestAlgorithm.SHA256. If omitted, use
 * DigestAlgorithm.SHA256.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that returns the signature Blob.
 */
PrivateKeyStorage.prototype.signPromise = function
  (data, keyName, digestAlgorithm, useSync)
{
  return SyncPromise.reject(new Error("PrivateKeyStorage.sign is not implemented"));
};

/**
 * Fetch the private key for keyName and sign the data to produce a signature Blob.
 * @param {Buffer} data Pointer to the input byte array.
 * @param {Name} keyName The name of the signing key.
 * @param {number} digestAlgorithm (optional) The digest algorithm from
 * DigestAlgorithm, such as DigestAlgorithm.SHA256. If omitted, use
 * DigestAlgorithm.SHA256.
 * @return {Blob} The signature Blob.
 * @throws Error If signPromise doesn't return a SyncPromise which is already
 * fulfilled.
 */
PrivateKeyStorage.prototype.sign = function(data, keyName, digestAlgorithm)
{
  return SyncPromise.getValue
    (this.signPromise(data, keyName, digestAlgorithm, true));
};

/**
 * Decrypt data.
 * @param {Name} keyName The name of the decrypting key.
 * @param {Buffer} data The byte to be decrypted.
 * @param {boolean} isSymmetric (optional) If true symmetric encryption is used,
 * otherwise asymmetric encryption is used. If omitted, use asymmetric
 * encryption.
 * @return {Blob} The decrypted data.
 */
PrivateKeyStorage.prototype.decrypt = function(keyName, data, isSymmetric)
{
  throw new Error("PrivateKeyStorage.decrypt is not implemented");
};

/**
 * Encrypt data.
 * @param {Name} keyName The name of the encrypting key.
 * @param {Buffer} data The byte to be encrypted.
 * @param {boolean} isSymmetric (optional) If true symmetric encryption is used,
 * otherwise asymmetric encryption is used. If omitted, use asymmetric
 * encryption.
 * @return {Blob} The encrypted data.
 */
PrivateKeyStorage.prototype.encrypt = function(keyName, data, isSymmetric)
{
  throw new Error("PrivateKeyStorage.encrypt is not implemented");
};

/**
 * @brief Generate a symmetric key.
 * @param {Name} keyName The name of the key.
 * @param {KeyParams} params The parameters of the key.
 */
PrivateKeyStorage.prototype.generateKey = function(keyName, params)
{
  throw new Error("PrivateKeyStorage.generateKey is not implemented");
};

/**
 * Check if a particular key exists.
 * @param {Name} keyName The name of the key.
 * @param {number} keyClass The class of the key, e.g. KeyClass.PUBLIC,
 * KeyClass.PRIVATE, or KeyClass.SYMMETRIC.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which returns true if the key exists.
 */
PrivateKeyStorage.prototype.doesKeyExistPromise = function
  (keyName, keyClass, useSync)
{
  return SyncPromise.reject(new Error
    ("PrivateKeyStorage.doesKeyExist is not implemented"));
};

/**
 * Check if a particular key exists.
 * @param {Name} keyName The name of the key.
 * @param {number} keyClass The class of the key, e.g. KeyClass.PUBLIC,
 * KeyClass.PRIVATE, or KeyClass.SYMMETRIC.
 * @return {boolean} True if the key exists.
 * @throws Error If doesKeyExistPromise doesn't return a SyncPromise which
 * is already fulfilled.
 */
PrivateKeyStorage.prototype.doesKeyExist = function(keyName, keyClass)
{
  return SyncPromise.getValue(this.doesKeyExistPromise(keyName, keyClass, true));
};

/**
 * Encode the private key to a PKCS #8 private key. We do this explicitly here
 * to avoid linking to extra OpenSSL libraries.
 * @param {Buffer} privateKeyDer The input private key DER.
 * @param {OID} oid The OID of the privateKey.
 * @param {DerNode} parameters The DerNode of the parameters for the OID.
 * @return {Blob} The PKCS #8 private key DER.
 */
PrivateKeyStorage.encodePkcs8PrivateKey = function
  (privateKeyDer, oid, parameters)
{
  var algorithmIdentifier = new DerNode.DerSequence();
  algorithmIdentifier.addChild(new DerNode.DerOid(oid));
  algorithmIdentifier.addChild(parameters);

  var result = new DerNode.DerSequence();
  result.addChild(new DerNode.DerInteger(0));
  result.addChild(algorithmIdentifier);
  result.addChild(new DerNode.DerOctetString(privateKeyDer));

  return result.encode();
};

/**
 * Encode the RSAKey private key as a PKCS #1 private key.
 * @param {RSAKey} rsaKey The RSAKey private key.
 * @return {Blob} The PKCS #1 private key DER.
 */
PrivateKeyStorage.encodePkcs1PrivateKeyFromRSAKey = function(rsaKey)
{
  // Imitate KJUR getEncryptedPKCS5PEMFromRSAKey.
  var result = new DerNode.DerSequence();

  result.addChild(new DerNode.DerInteger(0));
  result.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(rsaKey.n)));
  result.addChild(new DerNode.DerInteger(rsaKey.e));
  result.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(rsaKey.d)));
  result.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(rsaKey.p)));
  result.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(rsaKey.q)));
  result.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(rsaKey.dmp1)));
  result.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(rsaKey.dmq1)));
  result.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(rsaKey.coeff)));

  return result.encode();
};

/**
 * Encode the public key values in the RSAKey private key as a
 * SubjectPublicKeyInfo.
 * @param {RSAKey} rsaKey The RSAKey private key with the public key values.
 * @return {Blob} The SubjectPublicKeyInfo DER.
 */
PrivateKeyStorage.encodePublicKeyFromRSAKey = function(rsaKey)
{
  var rsaPublicKey = new DerNode.DerSequence();

  rsaPublicKey.addChild(new DerNode.DerInteger(PrivateKeyStorage.bigIntegerToBuffer(rsaKey.n)));
  rsaPublicKey.addChild(new DerNode.DerInteger(rsaKey.e));

  var algorithmIdentifier = new DerNode.DerSequence();
  algorithmIdentifier.addChild
    (new DerNode.DerOid(new OID(PrivateKeyStorage.RSA_ENCRYPTION_OID)));
  algorithmIdentifier.addChild(new DerNode.DerNull());

  var result = new DerNode.DerSequence();

  result.addChild(algorithmIdentifier);
  result.addChild(new DerNode.DerBitString(rsaPublicKey.encode().buf(), 0));

  return result.encode();
};

/**
 * Convert a BigInteger to a Buffer.
 * @param {BigInteger} bigInteger The BigInteger.
 * @return {Buffer} The Buffer.
 */
PrivateKeyStorage.bigIntegerToBuffer = function(bigInteger)
{
  // Imitate KJUR.asn1.ASN1Util.bigIntToMinTwosComplementsHex.
  var hex = bigInteger.toString(16);
  if (hex.substr(0, 1) == "-")
    throw new Error
      ("PrivateKeyStorage.bigIntegerToBuffer: Negative integers are not currently supported");

  if (hex.length % 2 == 1)
    // Odd number of characters.
    hex = "0" + hex;
  else {
    if (! hex.match(/^[0-7]/))
      // The first byte is >= 0x80, so prepend a zero to keep it positive.
      hex = "00" + hex;
  }

  return new Buffer(hex, 'hex');
};

PrivateKeyStorage.RSA_ENCRYPTION_OID = "1.2.840.113549.1.1.1";
PrivateKeyStorage.EC_ENCRYPTION_OID = "1.2.840.10045.2.1";
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
 *
 * 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.
 */

// Use capitalized Crypto to not clash with the browser's crypto.subtle.
/** @ignore */
var Crypto = require('../../crypto.js'); /** @ignore */
var Blob = require('../../util/blob.js').Blob; /** @ignore */
var SecurityException = require('../security-exception.js').SecurityException; /** @ignore */
var PublicKey = require('../certificate/public-key.js').PublicKey; /** @ignore */
var KeyClass = require('../security-types.js').KeyClass; /** @ignore */
var KeyType = require('../security-types').KeyType; /** @ignore */
var DigestAlgorithm = require('../security-types.js').DigestAlgorithm; /** @ignore */
var DataUtils = require('../../encoding/data-utils.js').DataUtils; /** @ignore */
var PrivateKeyStorage = require('./private-key-storage.js').PrivateKeyStorage; /** @ignore */
var DerNode = require('../../encoding/der/der-node.js').DerNode; /** @ignore */
var OID = require('../../encoding/oid.js').OID; /** @ignore */
var SyncPromise = require('../../util/sync-promise.js').SyncPromise; /** @ignore */
var UseSubtleCrypto = require('../../use-subtle-crypto-node.js').UseSubtleCrypto; /** @ignore */
var rsaKeygen = null;
try {
  // This should be installed with: sudo npm install rsa-keygen
  rsaKeygen = require('rsa-keygen');
}
catch (e) {}

/**
 * MemoryPrivateKeyStorage class extends PrivateKeyStorage to implement private
 * key storage in memory.
 * @constructor
 */
var MemoryPrivateKeyStorage = function MemoryPrivateKeyStorage()
{
  // Call the base constructor.
  PrivateKeyStorage.call(this);

  // The key is the keyName.toUri(). The value is security.certificate.PublicKey.
  this.publicKeyStore = {};
  // The key is the keyName.toUri(). The value is the object
  //  {keyType,     // number from KeyType
  //   privateKey   // The PEM-encoded private key.
  //  }.
  this.privateKeyStore = {};
};

MemoryPrivateKeyStorage.prototype = new PrivateKeyStorage();
MemoryPrivateKeyStorage.prototype.name = "MemoryPrivateKeyStorage";

exports.MemoryPrivateKeyStorage = MemoryPrivateKeyStorage;

/**
 * Set the public key for the keyName.
 * @param {Name} keyName The key name.
 * @param {number} keyType The KeyType, such as KeyType.RSA.
 * @param {Buffer} publicKeyDer The public key DER byte array.
 */
MemoryPrivateKeyStorage.prototype.setPublicKeyForKeyName = function
  (keyName, keyType, publicKeyDer)
{
  this.publicKeyStore[keyName.toUri()] = new PublicKey
    (new Blob(publicKeyDer, true));
};

/**
 * Set the private key for the keyName.
 * @param {Name} keyName The key name.
 * @param {number} keyType The KeyType, such as KeyType.RSA.
 * @param {Buffer} privateKeyDer The private key DER byte array.
 */
MemoryPrivateKeyStorage.prototype.setPrivateKeyForKeyName = function
  (keyName, keyType, privateKeyDer)
{
  // Encode the DER as PEM.
  var keyBase64 = privateKeyDer.toString('base64');
  var keyPem;
  if (keyType === KeyType.RSA) {
    keyPem = "-----BEGIN RSA PRIVATE KEY-----\n";
    for (var i = 0; i < keyBase64.length; i += 64)
      keyPem += (keyBase64.substr(i, 64) + "\n");
    keyPem += "-----END RSA PRIVATE KEY-----";
  }
  else if (keyType === KeyType.ECDSA) {
    keyPem = "-----BEGIN EC PRIVATE KEY-----\n";
    for (var i = 0; i < keyBase64.length; i += 64)
      keyPem += (keyBase64.substr(i, 64) + "\n");
    keyPem += "-----END EC PRIVATE KEY-----";
  }
  else
    throw new SecurityException(new Error
      ("MemoryPrivateKeyStorage: KeyType is not supported"));

  this.privateKeyStore[keyName.toUri()] =
    { keyType: keyType, privateKey: keyPem };
};

/**
 * Set the public and private key for the keyName.
 * @param {Name} keyName The key name.
 * @param {number} keyType The KeyType, such as KeyType.RSA.
 * @param {Buffer} publicKeyDer The public key DER byte array.
 * @param {Buffer} privateKeyDer The private key DER byte array.
 */
MemoryPrivateKeyStorage.prototype.setKeyPairForKeyName = function
  (keyName, keyType, publicKeyDer, privateKeyDer)
{
  this.setPublicKeyForKeyName(keyName, keyType, publicKeyDer);
  this.setPrivateKeyForKeyName(keyName, keyType, privateKeyDer);
};

/**
 * Generate a pair of asymmetric keys.
 * @param {Name} keyName The name of the key pair.
 * @param {KeyParams} params The parameters of the key.
 * @param {boolean} useSync (optional) If true then use blocking crypto and
 * return a SyncPromise which is already fulfilled. If omitted or false, if
 * possible use crypto.subtle and return an async Promise, otherwise use
 * blocking crypto and return a SyncPromise.
 * @return {Promise|SyncPromise} A promise that fulfills when the pair is
 * generated.
 */
MemoryPrivateKeyStorage.prototype.generateKeyPairPromise = function
  (keyName, params, useSync)
{
  if (this.doesKeyExist(keyName, KeyClass.PUBLIC))
    return SyncPromise.reject(new SecurityException(new Error
      ("Public key already exists")));
  if (this.doesKeyExist(keyName, KeyClass.PRIVATE))
    return SyncPromise.reject(new SecurityException(new Error
      ("Private key already exists")));

  var thisStore = this;

  if (UseSubtleCrypto() && !useSync) {
    if (params.getKeyType() === KeyType.RSA) {
      var privateKey = null;
      var publicKeyDer = null;

      return crypto.subtle.generateKey
        ({ name: "RSASSA-PKCS1-v1_5", modulusLength: params.getKeySize(),
           publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
           hash: {name: "SHA-256"} },
         true, ["sign", "verify"])
      .then(function(key) {
        privateKey = key.privateKey;

        // Export the public key to DER.
        return crypto.subtle.exportKey("spki", key.publicKey);
      })
      .then(function(exportedPublicKey) {
        publicKeyDer = new Blob(new Uint8Array(exportedPublicKey), false).buf();

        // Export the private key to DER.
        return crypto.subtle.exportKey("pkcs8", privateKey);
      })
      .then(function(pkcs8Der) {
        // Crypto.subtle exports the private key as PKCS #8. Decode it to find
        // the inner private key DER.
        var parsedNode = DerNode.parse
          (new Blob(new Uint8Array(pkcs8Der), false).buf());
        // Get the value of the 3rd child which is the octet string.
        var privateKeyDer = parsedNode.getChildren()[2].toVal();

        // Save the key pair.
        thisStore.setKeyPairForKeyName
          (keyName, params.getKeyType(), publicKeyDer, privateKeyDer.buf());

        // sign will use subtleKey directly.
        thisStore.privateKeyStore[keyName.toUri()].subtleKey = privateKey;

        return Promise.resolve();
      });
    }
    else
      return SyncPromise.reject(new SecurityException(new Error
        ("Only RSA key generation currently supported")));
  }
  else {
    return SyncPromise.resolve()
    .then(function() {
      if (typeof RSAKey !== 'undefined') {
        // Assume we are in the browser.
        if (params.getKeyType() === KeyType.RSA) {
          var rsaKey = new RSAKey();
          rsaKey.generate(params.getKeySize(), '010001');
          thisStore.setKeyPairForKeyName
            (keyName, params.getKeyType(),
             PrivateKeyStorage.encodePublicKeyFromRSAKey(rsaKey).buf(),
             PrivateKeyStorage.encodePkcs1PrivateKeyFromRSAKey(rsaKey).buf());
        }
        else
          return SyncPromise.reject(new SecurityException(new Error
            ("Only RSA key generation currently supported")));
      }
      else {
        // Assume we are in Node.js.
        var publicKeyDer;
        var privateKeyPem;

        if (params.getKeyType() === KeyType.RSA) {
          if (!rsaKeygen)
            return SyncPromise.reject(new SecurityException(new Error
              ("Need to install rsa-keygen: sudo npm install rsa-keygen")));

          var keyPair = rsaKeygen.generate(params.getKeySize());

          // Get the public key DER from the PEM string.
          var publicKeyBase64 = keyPair.public_key.toString().replace
            ("-----BEGIN PUBLIC KEY-----", "").replace
            ("-----END PUBLIC KEY-----", "");
          publicKeyDer = new Buffer(publicKeyBase64, 'base64');

          privateKeyPem = keyPair.private_key.toString();
        }
        else
          return SyncPromise.reject(new SecurityException(new Error
            ("Only RSA key generation currently supported")));

        thisStore.setPublicKeyForKeyName(keyName, params.getKeyType(), publicKeyDer);
        thisStore.privateKeyStore[keyName.toUri()] =
          { keyType: params.getKeyType(), privateKey: privateKeyPem };
      }

      return SyncPromise.resolve();
    });
  }
};

/**
 * Delete a pair of asymmetric keys. If the key doesn't exist, do nothing.
 * @param {Name} keyName The name of the key pair.
 * @return {SyncPromise} A promise that fulfills when the key pair is deleted.
 */
MemoryPrivateKeyStorage.prototype.deleteKeyPairPromise = function(keyName)
{
  var keyUri = keyName.toUri();

  delete this.publicKeyStore[keyUri];
  delete this.privateKeyStore[keyUri];

  return SyncPromise.resolve();
};

/**
 * Get the public key
 * @param {Name} keyName The name of public key.
 * @return {SyncPromise} A promise that returns the PublicKey.
 */
MemoryPrivateKeyStorage.prototype.getPublicKeyPromise = function(keyName)
{
  var keyUri = keyName.toUri();
  var publicKey = this.publicKeyStore[keyUri];
  if (publicKey === undefined)
    return SyncPromise.reject(new SecurityException(new Error
      ("MemoryPrivateKeyStorage: Cannot find public key " + keyName.toUri())));

  return SyncPromise.resolve(publicKey);
};

/**
 * Fetch the private key for keyName and sign the data to produce a signature Blob.
 * @param {Buffer} data Pointer to the input byte array.
 * @param {Name} keyName The name of the signing key.
 * @param {number} digestAlgorithm (optional) The digest algorithm from
 * DigestAlgorithm, such as DigestAlgorithm.SHA256. If omitted, use
 * DigestAlgorithm.SHA256.
 * @param {boolean} useSync (optional) If true then use blocking crypto and
 * return a SyncPromise which is already fulfilled. If omitted or false, if
 * possible use crypto.subtle and return an async Promise, otherwise use
 * blocking crypto and return a SyncPromise.
 * @return {Promise|SyncPromise} A promise that returns the signature Blob.
 */
MemoryPrivateKeyStorage.prototype.signPromise = function
  (data, keyName, digestAlgorithm, useSync)
{
  useSync = (typeof digestAlgorithm === "boolean") ? digestAlgorithm : useSync;
  digestAlgorithm = (typeof digestAlgorithm === "boolean" || !digestAlgorithm) ? DigestAlgorithm.SHA256 : digestAlgorithm;

  if (digestAlgorithm != DigestAlgorithm.SHA256)
    return SyncPromise.reject(new SecurityException(new Error
      ("MemoryPrivateKeyStorage.sign: Unsupported digest algorithm")));

  // Find the private key.
  var keyUri = keyName.toUri();
  var privateKey = this.privateKeyStore[keyUri];
  if (privateKey === undefined)
    return SyncPromise.reject(new SecurityException(new Error
      ("MemoryPrivateKeyStorage: Cannot find private key " + keyUri)));

  if (UseSubtleCrypto() && !useSync){
    var algo = {name:"RSASSA-PKCS1-v1_5",hash:{name:"SHA-256"}};

    if (!privateKey.subtleKey){
      //this is the first time in the session that we're using crypto subtle with this key
      //so we have to convert to pkcs8 and import it.
      //assigning it to privateKey.subtleKey means we only have to do this once per session,
      //giving us a small, but not insignificant, performance boost.
      var privateDER = DataUtils.privateKeyPemToDer(privateKey.privateKey);
      var pkcs8 = PrivateKeyStorage.encodePkcs8PrivateKey
        (privateDER, new OID(PrivateKeyStorage.RSA_ENCRYPTION_OID),
         new DerNode.DerNull()).buf();

      var promise = crypto.subtle.importKey("pkcs8", pkcs8.buffer, algo, true, ["sign"]).then(function(subtleKey){
        //cache the crypto.subtle key object
        privateKey.subtleKey = subtleKey;
        return crypto.subtle.sign(algo, subtleKey, data);
      });
    } else {
      // The crypto.subtle key has been cached on a previous sign or from keygen.
      var promise = crypto.subtle.sign(algo, privateKey.subtleKey, data);
    }

    return promise.then(function(signature){
      var result = new Blob(new Uint8Array(signature), true);
      return Promise.resolve(result);
    });
  } else {
    var signer;
    if (privateKey.keyType === KeyType.RSA)
      signer = Crypto.createSign("RSA-SHA256");
    else if (privateKey.keyType === KeyType.ECDSA)
      // Just create a "sha256". The Crypto library will infer ECDSA from the key.
      signer = Crypto.createSign("sha256");
    else
      // We don't expect this to happen since setPrivateKeyForKeyName already checked.
      return SyncPromise.reject(new SecurityException(new Error
        ("MemoryPrivateKeyStorage.sign: Unrecognized private key type")));

    signer.update(data);
    var signature = new Buffer
      (DataUtils.toNumbersIfString(signer.sign(privateKey.privateKey)));
    var result = new Blob(signature, false);

    return SyncPromise.resolve(result);
  }
};

/**
 * Check if a particular key exists.
 * @param {Name} keyName The name of the key.
 * @param {number} keyClass The class of the key, e.g. KeyClass.PUBLIC,
 * KeyClass.PRIVATE, or KeyClass.SYMMETRIC.
 * @return {SyncPromise} A promise which returns true if the key exists.
 */
MemoryPrivateKeyStorage.prototype.doesKeyExistPromise = function
  (keyName, keyClass)
{
  var keyUri = keyName.toUri();
  var result = false;
  if (keyClass == KeyClass.PUBLIC)
    result = this.publicKeyStore[keyUri] !== undefined;
  else if (keyClass == KeyClass.PRIVATE)
    result = this.privateKeyStore[keyUri] !== undefined;

  return SyncPromise.resolve(result);
};
/**
 * Copyright (C) 2015-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

// Use capitalized Crypto to not clash with the browser's crypto.subtle.
var Crypto = require('../../crypto.js');
// Don't require other modules since this is meant for the browser, not Node.js.

/**
 * IndexedDbPrivateKeyStorage extends PrivateKeyStorage to implement private key
 * storage using the browser's IndexedDB service.
 * @constructor
 */
var IndexedDbPrivateKeyStorage = function IndexedDbPrivateKeyStorage()
{
  PrivateKeyStorage.call(this);

  this.database = new Dexie("ndnsec-tpm");
  this.database.version(1).stores({
    // "nameHash" is transformName(keyName) // string
    // "encoding" is the public key DER     // Uint8Array
    publicKey: "nameHash",

    // "nameHash" is transformName(keyName)     // string
    // "encoding" is the PKCS 8 private key DER // Uint8Array
    privateKey: "nameHash"
  });
  this.database.open();
};

IndexedDbPrivateKeyStorage.prototype = new PrivateKeyStorage();
IndexedDbPrivateKeyStorage.prototype.name = "IndexedDbPrivateKeyStorage";

/**
 * Generate a pair of asymmetric keys.
 * @param {Name} keyName The name of the key pair.
 * @param {KeyParams} params The parameters of the key.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise that fulfills when the pair is generated.
 */
IndexedDbPrivateKeyStorage.prototype.generateKeyPairPromise = function
  (keyName, params, useSync)
{
  if (useSync)
    return Promise.reject(new SecurityException(new Error
      ("IndexedDbPrivateKeyStorage.generateKeyPairPromise is only supported for async")));

  var thisStorage = this;

  return thisStorage.doesKeyExistPromise(keyName, KeyClass.PUBLIC)
  .then(function(exists) {
    if (exists)
      throw new Error("Public key already exists");

    return thisStorage.doesKeyExistPromise(keyName, KeyClass.PRIVATE);
  })
  .then(function(exists) {
    if (exists)
      throw new Error("Private key already exists");

    if (params.getKeyType() === KeyType.RSA) {
      var privateKey = null;
      var publicKeyDer = null;

      return crypto.subtle.generateKey
        ({ name: "RSASSA-PKCS1-v1_5", modulusLength: params.getKeySize(),
           publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
           hash: {name: "SHA-256"} },
         true, ["sign", "verify"])
      .then(function(key) {
        privateKey = key.privateKey;

        // Export the public key to DER.
        return crypto.subtle.exportKey("spki", key.publicKey);
      })
      .then(function(exportedPublicKey) {
        publicKeyDer = new Uint8Array(exportedPublicKey);

        // Export the private key to DER.
        return crypto.subtle.exportKey("pkcs8", privateKey);
      })
      .then(function(pkcs8Der) {
        // Save the key pair
        return thisStorage.database.transaction
          ("rw", thisStorage.database.privateKey, thisStorage.database.publicKey, function () {
            thisStorage.database.publicKey.put
              ({nameHash: IndexedDbPrivateKeyStorage.transformName(keyName),
                encoding: publicKeyDer});
            thisStorage.database.privateKey.put
              ({nameHash: IndexedDbPrivateKeyStorage.transformName(keyName),
                encoding: new Uint8Array(pkcs8Der)});
          });
      });
    }
    else
      throw new Error("Only RSA key generation currently supported");
  });
};


/**
 * Delete a pair of asymmetric keys. If the key doesn't exist, do nothing.
 * @param {Name} keyName The name of the key pair.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise that fulfills when the key pair is deleted.
 */
IndexedDbPrivateKeyStorage.prototype.deleteKeyPairPromise = function
  (keyName, useSync)
{
  if (useSync)
    return Promise.reject(new SecurityException(new Error
      ("IndexedDbPrivateKeyStorage.deleteKeyPairPromise is only supported for async")));

  var thisStorage = this;
  // delete does nothing if the key doesn't exist.
  return this.database.publicKey.delete
    (IndexedDbPrivateKeyStorage.transformName(keyName))
  .then(function() {
    return thisStorage.database.privateKey.delete
      (IndexedDbPrivateKeyStorage.transformName(keyName));
  });
};

/**
 * Get the public key
 * @param {Name} keyName The name of public key.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise that returns the PublicKey.
 */
IndexedDbPrivateKeyStorage.prototype.getPublicKeyPromise = function
  (keyName, useSync)
{
  if (useSync)
    return Promise.reject(new SecurityException(new Error
      ("IndexedDbPrivateKeyStorage.getPublicKeyPromise is only supported for async")));

  return this.database.publicKey.get
    (IndexedDbPrivateKeyStorage.transformName(keyName))
  .then(function(publicKeyEntry) {
    return Promise.resolve(new PublicKey(new Blob(publicKeyEntry.encoding)));
  });
};

/**
 * Fetch the private key for keyName and sign the data to produce a signature Blob.
 * @param {Buffer} data Pointer to the input byte array.
 * @param {Name} keyName The name of the signing key.
 * @param {number} digestAlgorithm (optional) The digest algorithm from
 * DigestAlgorithm, such as DigestAlgorithm.SHA256. If omitted, use
 * DigestAlgorithm.SHA256.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise that returns the signature Blob.
 */
IndexedDbPrivateKeyStorage.prototype.signPromise = function
  (data, keyName, digestAlgorithm, useSync)
{
  useSync = (typeof digestAlgorithm === "boolean") ? digestAlgorithm : useSync;
  digestAlgorithm = (typeof digestAlgorithm === "boolean" || !digestAlgorithm) ? DigestAlgorithm.SHA256 : digestAlgorithm;

  if (useSync)
    return Promise.reject(new SecurityException(new Error
      ("IndexedDbPrivateKeyStorage.signPromise is only supported for async")));

  if (digestAlgorithm != DigestAlgorithm.SHA256)
    return Promise.reject(new SecurityException(new Error
      ("IndexedDbPrivateKeyStorage.sign: Unsupported digest algorithm")));

  // TODO: Support non-RSA keys.
  var algo = { name: "RSASSA-PKCS1-v1_5", hash: {name: "SHA-256" }};

  // Find the private key.
  return this.database.privateKey.get
    (IndexedDbPrivateKeyStorage.transformName(keyName))
  .then(function(privateKeyEntry) {
    return crypto.subtle.importKey
      ("pkcs8", new Blob(privateKeyEntry.encoding).buf(), algo, true, ["sign"]);
  })
  .then(function(privateKey) {
    return crypto.subtle.sign(algo, privateKey, data);
  })
  .then(function(signature) {
    return Promise.resolve(new Blob(new Uint8Array(signature), true));
  });
};

/**
 * Check if a particular key exists.
 * @param {Name} keyName The name of the key.
 * @param {number} keyClass The class of the key, e.g. KeyClass.PUBLIC,
 * KeyClass.PRIVATE, or KeyClass.SYMMETRIC.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise which returns true if the key exists.
 */
IndexedDbPrivateKeyStorage.prototype.doesKeyExistPromise = function
  (keyName, keyClass, useSync)
{
  if (useSync)
    return Promise.reject(new SecurityException(new Error
      ("IndexedDbPrivateKeyStorage.doesKeyExistPromise is only supported for async")));

  var table = null;
  if (keyClass == KeyClass.PUBLIC)
    table = this.database.publicKey;
  else if (keyClass == KeyClass.PRIVATE)
    table = this.database.privateKey;
  else
    // Silently say that anything else doesn't exist.
    return Promise.resolve(false);

  return table.where("nameHash").equals
    (IndexedDbPrivateKeyStorage.transformName(keyName))
  .count()
  .then(function(count) {
    return Promise.resolve(count > 0);
  });
};

/**
 * Transform the key name into the base64 encoding of the hash (the same as in
 * FilePrivateKeyStorage without the file name extension).
 */
IndexedDbPrivateKeyStorage.transformName = function(keyName)
{
  var hash = Crypto.createHash('sha256');
  hash.update(new Buffer(keyName.toUri()));
  var fileName = hash.digest('base64');
  return fileName.replace(/\//g, '%');
};
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
 *
 * 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.
 */

// Use capitalized Crypto to not clash with the browser's crypto.subtle.
/** @ignore */
var Crypto = require('../../crypto.js'); /** @ignore */
var Name = require('../../name.js').Name; /** @ignore */
var Data = require('../../data.js').Data; /** @ignore */
var Blob = require('../../util/blob.js').Blob; /** @ignore */
var ConfigFile = require('../../util/config-file.js').ConfigFile; /** @ignore */
var DigestSha256Signature = require('../../digest-sha256-signature.js').DigestSha256Signature; /** @ignore */
var Sha256WithRsaSignature = require('../../sha256-with-rsa-signature.js').Sha256WithRsaSignature; /** @ignore */
var Sha256WithEcdsaSignature = require('../../sha256-with-ecdsa-signature.js').Sha256WithEcdsaSignature; /** @ignore */
var KeyLocatorType = require('../../key-locator.js').KeyLocatorType; /** @ignore */
var WireFormat = require('../../encoding/wire-format.js').WireFormat; /** @ignore */
var SecurityException = require('../security-exception.js').SecurityException; /** @ignore */
var DigestAlgorithm = require('../security-types.js').DigestAlgorithm; /** @ignore */
var KeyType = require('../security-types.js').KeyType; /** @ignore */
var RsaKeyParams = require('../key-params.js').RsaKeyParams; /** @ignore */
var IdentityCertificate = require('../certificate/identity-certificate.js').IdentityCertificate; /** @ignore */
var PublicKey = require('../certificate/public-key.js').PublicKey; /** @ignore */
var CertificateSubjectDescription = require('../certificate/certificate-subject-description.js').CertificateSubjectDescription; /** @ignore */
var SyncPromise = require('../../util/sync-promise.js').SyncPromise; /** @ignore */
var BasicIdentityStorage = require('./basic-identity-storage.js').BasicIdentityStorage; /** @ignore */
var FilePrivateKeyStorage = require('./file-private-key-storage.js').FilePrivateKeyStorage;

/**
 * An IdentityManager is the interface of operations related to identity, keys,
 * and certificates.
 *
 * Create a new IdentityManager to use the IdentityStorage and
 * PrivateKeyStorage.
 * @param {IdentityStorage} identityStorage An object of a subclass of
 * IdentityStorage. In Node.js, if this is omitted then use BasicIdentityStorage.
 * @param {PrivateKeyStorage} privateKeyStorage An object of a subclass of
 * PrivateKeyStorage. In Node.js, if this is omitted then use the default
 * PrivateKeyStorage for your system, which is FilePrivateKeyStorage for any
 * system other than OS X. (OS X key chain storage is not yet implemented, so
 * you must supply a different PrivateKeyStorage.)
 * @throws SecurityException if this is not in Node.js and identityStorage or
 * privateKeyStorage is omitted.
 * @constructor
 */
var IdentityManager = function IdentityManager
  (identityStorage, privateKeyStorage)
{
  if (privateKeyStorage) {
    // Don't call checkTpm() when using a custom PrivateKeyStorage.
    if (!identityStorage)
        // We don't expect this to happen.
        throw new Error
          ("IdentityManager: A custom privateKeyStorage is supplied with a null identityStorage")

    this.identityStorage = identityStorage;
    this.privateKeyStorage = privateKeyStorage;
  }
  else {
    if (!ConfigFile)
      // Assume we are in the browser.
      throw new SecurityException(new Error
        ("IdentityManager: If not in Node.js then you must supply identityStorage and privateKeyStorage."));
    var config = new ConfigFile();

    var canonicalTpmLocator = [null];
    var thisStorage = this;
    // Make the function that BasicIdentityStorage will call the first time it
    // is used. It has to be an async promise becuase getTpmLocatorPromise is async.
    function initialCheckPromise() 
    {
      return thisStorage.checkTpmPromise_(canonicalTpmLocator[0]);
    }

    this.identityStorage = identityStorage ? identityStorage
      : IdentityManager.getDefaultIdentityStorage_(config, initialCheckPromise);
    this.privateKeyStorage = IdentityManager.getDefaultPrivateKeyStorage_
      (config, canonicalTpmLocator);
  }
};

exports.IdentityManager = IdentityManager;

/**
 * Create an identity by creating a pair of Key-Signing-Key (KSK) for this
 * identity and a self-signed certificate of the KSK. If a key pair or
 * certificate for the identity already exists, use it.
 * @param {Name} identityName The name of the identity.
 * @params {KeyParams} params The key parameters if a key needs to be generated
 * for the identity.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which returns the name of the default
 * certificate of the identity.
 */
IdentityManager.prototype.createIdentityAndCertificatePromise = function
  (identityName, params, useSync)
{
  var thisManager = this;
  var generateKey = true;
  var keyName = null;

  return this.identityStorage.addIdentityPromise(identityName, useSync)
  .then(function() {
    return thisManager.identityStorage.getDefaultKeyNameForIdentityPromise
      (identityName, useSync)
    .then(function(localKeyName) {
      keyName = localKeyName;

      // Set generateKey.
      return thisManager.identityStorage.getKeyPromise(keyName, useSync)
      .then(function(publicKeyDer) {
        var key = new PublicKey(publicKeyDer);
        if (key.getKeyType() == params.getKeyType())
          // The key exists and has the same type, so don't need to generate one.
          generateKey = false;
        return SyncPromise.resolve();
      });
    }, function(err) {
      if (!(err instanceof SecurityException))
        throw err;

      // The key doesn't exist, so leave generateKey true.
      return SyncPromise.resolve();
    });
  })
  .then(function() {
    if (generateKey)
      return thisManager.generateKeyPairPromise(identityName, true, params, useSync)
      .then(function(localKeyName) {
        keyName = localKeyName;
        return thisManager.identityStorage.setDefaultKeyNameForIdentityPromise
          (keyName, useSync);
      });
    else
      // Don't generate a key pair. Use the existing keyName.
      return SyncPromise.resolve();
  })
  .then(function() {
    return thisManager.identityStorage.getDefaultCertificateNameForKeyPromise
      (keyName, useSync)
    .then(function(certName) {
      // The cert exists, so don't need to make it.
      return SyncPromise.resolve(certName);
    }, function(err) {
      if (!(err instanceof SecurityException))
        throw err;

      // The cert doesn't exist, so make one.
      var certName;
      return thisManager.selfSignPromise(keyName, useSync)
      .then(function(selfCert) {
        certName = selfCert.getName();
        return thisManager.addCertificateAsIdentityDefaultPromise(selfCert, useSync);
      })
      .then(function() {
        return SyncPromise.resolve(certName);
      });
    });
  });
};

/**
 * Create an identity by creating a pair of Key-Signing-Key (KSK) for this
 * identity and a self-signed certificate of the KSK. If a key pair or
 * certificate for the identity already exists, use it.
 * @param {Name} identityName The name of the identity.
 * @params {KeyParams} params The key parameters if a key needs to be generated
 * for the identity.
 * @param {function} onComplete (optional) This calls onComplete(certificateName)
 * with the name of the default certificate of the identity. If omitted, the
 * return value is described below. (Some crypto libraries only use a callback,
 * so onComplete is required to use these.)
 * @param {function} onError (optional) If defined, then onComplete must be
 * defined and if there is an exception, then this calls onError(exception)
 * with the exception. If onComplete is defined but onError is undefined, then
 * this will log any thrown exception. (Some crypto libraries only use a
 * callback, so onError is required to be notified of an exception.)
 * @return {Name} If onComplete is omitted, return the name of the default
 * certificate of the identity. Otherwise, if onComplete is supplied then return
 * undefined and use onComplete as described above.
 */
IdentityManager.prototype.createIdentityAndCertificate = function
  (identityName, params, onComplete, onError)
{
  return SyncPromise.complete(onComplete, onError,
    this.createIdentityAndCertificatePromise(identityName, params, !onComplete));
};

/**
 * Create an identity by creating a pair of Key-Signing-Key (KSK) for this
 * identity and a self-signed certificate of the KSK. If a key pair or
 * certificate for the identity already exists, use it.
 * @deprecated Use createIdentityAndCertificate which returns the
 * certificate name instead of the key name. You can use
 * IdentityCertificate.certificateNameToPublicKeyName to convert the
 * certificate name to the key name.
 * @param {Name} identityName The name of the identity.
 * @params {KeyParams} params The key parameters if a key needs to be generated
 * for the identity.
 * @return {Name} The key name of the auto-generated KSK of the identity.
 */
IdentityManager.prototype.createIdentity = function(identityName, params)
{
  return IdentityCertificate.certificateNameToPublicKeyName
    (this.createIdentityAndCertificate(identityName, params));
};

/**
 * Delete the identity from the public and private key storage. If the
 * identity to be deleted is the current default system default, this will not
 * delete the identity and will return immediately.
 * @param {Name} identityName The name of the identity.
 * @param {function} onComplete (optional) This calls onComplete() when the
 * operation is complete. If omitted, do not use it. (Some database libraries
 * only use a callback, so onComplete is required to use these.)
 * @param {function} onError (optional) If defined, then onComplete must be
 * defined and if there is an exception, then this calls onError(exception)
 * with the exception. If onComplete is defined but onError is undefined, then
 * this will log any thrown exception. (Some database libraries only use a
 * callback, so onError is required to be notified of an exception.)
 */
IdentityManager.prototype.deleteIdentity = function
  (identityName, onComplete, onError)
{
  var useSync = !onComplete;
  var thisManager = this;

  var doDelete = true;

  var mainPromise = this.identityStorage.getDefaultIdentityPromise(useSync)
  .then(function(defaultIdentityName) {
    if (defaultIdentityName.equals(identityName))
      // Don't delete the default identity!
      doDelete = false;

    return SyncPromise.resolve();
  }, function(err) {
    // There is no default identity to check.
    return SyncPromise.resolve();
  })
  .then(function() {
    if (!doDelete)
      return SyncPromise.resolve();

    var keysToDelete = [];
    return thisManager.identityStorage.getAllKeyNamesOfIdentityPromise
      (identityName, keysToDelete, true)
    .then(function() {
      return thisManager.identityStorage.getAllKeyNamesOfIdentityPromise
        (identityName, keysToDelete, false);
    })
    .then(function() {
      return thisManager.identityStorage.deleteIdentityInfoPromise(identityName);
    })
    .then(function() {
      // Recursively loop through keysToDelete, calling deleteKeyPairPromise.
      function deleteKeyLoop(i) {
        if (i >= keysToDelete.length)
          return SyncPromise.resolve();

        return thisManager.privateKeyStorage.deleteKeyPairPromise(keysToDelete[i])
        .then(function() {
          return deleteKeyLoop(i + 1);
        });
      }

      return deleteKeyLoop(0);
    });
  });

  return SyncPromise.complete(onComplete, onError, mainPromise);
};

/**
 * Set the default identity.  If the identityName does not exist, then clear the
 * default identity so that getDefaultIdentity() throws an exception.
 * @param {Name} identityName The default identity name.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which fulfills when the default
 * identity is set.
 */
IdentityManager.prototype.setDefaultIdentityPromise = function
  (identityName, useSync)
{
  return this.identityStorage.setDefaultIdentityPromise(identityName, useSync);
};

/**
 * Set the default identity.  If the identityName does not exist, then clear the
 * default identity so that getDefaultIdentity() throws an exception.
 * @param {Name} identityName The default identity name.
 * @param {function} onComplete (optional) This calls onComplete() when complete.
 * (Some database libraries only use a callback, so onComplete is required to
 * use these.)
 * @param {function} onError (optional) If defined, then onComplete must be
 * defined and if there is an exception, then this calls onError(exception)
 * with the exception. If onComplete is defined but onError is undefined, then
 * this will log any thrown exception. (Some database libraries only use a
 * callback, so onError is required to be notified of an exception.)
 */
IdentityManager.prototype.setDefaultIdentity = function
  (identityName, onComplete, onError)
{
  return SyncPromise.complete(onComplete, onError,
    this.identityStorage.setDefaultIdentityPromise(identityName, !onComplete));
};

/**
 * Get the default identity.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which returns the Name of default
 * identity, or a promise rejected with SecurityException if the default
 * identity is not set.
 */
IdentityManager.prototype.getDefaultIdentityPromise = function(useSync)
{
  return this.identityStorage.getDefaultIdentityPromise(useSync);
};

/**
 * Get the default identity.
 * @param {function} onComplete (optional) This calls onComplete(identityName)
 * with name of the default identity. If omitted, the return value is described
 * below. (Some database libraries only use a callback, so onComplete is required
 * to use these.)
 * @param {function} onError (optional) If defined, then onComplete must be
 * defined and if there is an exception, then this calls onError(exception)
 * with the exception. If onComplete is defined but onError is undefined, then
 * this will log any thrown exception. (Some database libraries only use a
 * callback, so onError is required to be notified of an exception.)
 * @return {Name} If onComplete is omitted, return the name of the default
 * identity. Otherwise, if onComplete is supplied then return undefined and use
 * onComplete as described above.
 * @throws SecurityException if the default identity is not set. However, if
 * onComplete and onError are defined, then if there is an exception return
 * undefined and call onError(exception).
 */
IdentityManager.prototype.getDefaultIdentity = function(onComplete, onError)
{
  return SyncPromise.complete(onComplete, onError,
    this.identityStorage.getDefaultIdentityPromise(!onComplete));
};

/**
 * Get the certificate of the default identity.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which returns the requested
 * IdentityCertificate or null if not found.
 */
IdentityManager.prototype.getDefaultCertificatePromise = function(useSync)
{
  return this.identityStorage.getDefaultCertificatePromise(useSync);
};

/**
 * Generate a pair of RSA keys for the specified identity.
 * @param {Name} identityName The name of the identity.
 * @param {boolean} isKsk True for generating a Key-Signing-Key (KSK), false for
 * a Data-Signing-Key (DSK).
 * @param {number} keySize The size of the key.
 * @return {Name} The generated key name.
 */
IdentityManager.prototype.generateRSAKeyPair = function
  (identityName, isKsk, keySize)
{
  // For now, require sync. This method may be removed from the API.
  return SyncPromise.getValue
    (this.generateKeyPairPromise
     (identityName, isKsk, new RsaKeyParams(keySize), true));
};

/**
 * Set a key as the default key of an identity. The identity name is inferred
 * from keyName.
 * @param {Name} keyName The name of the key.
 * @param {Name} identityNameCheck (optional) The identity name to check that the
 * keyName contains the same identity name. If an empty name, it is ignored.
 * @param {function} onComplete (optional) This calls onComplete() when complete.
 * (Some database libraries only use a callback, so onComplete is required to
 * use these.)
 * @param {function} onError (optional) If defined, then onComplete must be
 * defined and if there is an exception, then this calls onError(exception)
 * with the exception. If onComplete is defined but onError is undefined, then
 * this will log any thrown exception. (Some database libraries only use a
 * callback, so onError is required to be notified of an exception.)
 */
IdentityManager.prototype.setDefaultKeyForIdentity = function
  (keyName, identityNameCheck, onComplete, onError)
{
  onError = (typeof identityNameCheck === "function") ? onComplete : onError;
  onComplete = (typeof identityNameCheck === "function") ?
    identityNameCheck : onComplete;
  identityNameCheck = (typeof identityNameCheck === "function" || !identityNameCheck) ?
    new Name() : identityNameCheck;

  return SyncPromise.complete(onComplete, onError,
    this.identityStorage.setDefaultKeyNameForIdentityPromise
      (keyName, identityNameCheck, !onComplete));
};

/**
 * Get the default key for an identity.
 * @param {Name} identityName The name of the identity.
 * @param {function} onComplete (optional) This calls onComplete(keyName)
 * with name of the default key. If omitted, the return value is described
 * below. (Some database libraries only use a callback, so onComplete is required
 * to use these.)
 * @param {function} onError (optional) If defined, then onComplete must be
 * defined and if there is an exception, then this calls onError(exception)
 * with the exception. If onComplete is defined but onError is undefined, then
 * this will log any thrown exception. (Some database libraries only use a
 * callback, so onError is required to be notified of an exception.)
 * @return {Name} If onComplete is omitted, return the default key name.
 * Otherwise, if onComplete is supplied then return undefined and use onComplete
 * as described above.
 * @throws SecurityException if the default key name for the identity is not set.
 * However, if onComplete and onError are defined, then if there is an exception
 * return undefined and call onError(exception).
 */
IdentityManager.prototype.getDefaultKeyNameForIdentity = function
  (identityName, onComplete, onError)
{
  return SyncPromise.complete(onComplete, onError,
    this.identityStorage.getDefaultKeyNameForIdentityPromise
      (identityName, !onComplete));
};

/**
 * Generate a pair of RSA keys for the specified identity and set it as default
 * key for the identity.
 * @param {Name} identityName The name of the identity.
 * @param {boolean} isKsk True for generating a Key-Signing-Key (KSK), false for
 * a Data-Signing-Key (DSK).
 * @param {number} keySize The size of the key.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If false, this may return a SyncPromise or an async
 * Promise.
 * @return {Promise|SyncPromise} A promise which returns the generated key name.
 */
IdentityManager.prototype.generateRSAKeyPairAsDefaultPromise = function
  (identityName, isKsk, keySize, useSync)
{
  var newKeyName;
  var thisManager = this;
  return this.generateKeyPairPromise(identityName, isKsk, new RsaKeyParams(keySize))
  .then(function(localKeyName) {
    newKeyName = localKeyName;

    return thisManager.identityStorage.setDefaultKeyNameForIdentityPromise
      (newKeyName);
  })
  .then(function() {
    return SyncPromise.resolve(newKeyName);
  });
};

/**
 * Generate a pair of RSA keys for the specified identity and set it as default
 * key for the identity.
 * @param {Name} identityName The name of the identity.
 * @param {boolean} isKsk True for generating a Key-Signing-Key (KSK), false for
 * a Data-Signing-Key (DSK).
 * @param {number} keySize The size of the key.
 * @return {Name} The generated key name.
 */
IdentityManager.prototype.generateRSAKeyPairAsDefault = function
  (identityName, isKsk, keySize)
{
  return SyncPromise.getValue
    (this.generateRSAKeyPairAsDefaultPromise(identityName, isKsk, keySize, true));
};

/**
 * Get the public key with the specified name.
 * @param {Name} keyName The name of the key.
 * @param {function} onComplete (optional) This calls onComplete(publicKey)
 * with PublicKey. If omitted, the return value is described below. (Some database
 * libraries only use a callback, so onComplete is required to use these.)
 * @param {function} onError (optional) If defined, then onComplete must be
 * defined and if there is an exception, then this calls onError(exception)
 * with the exception. If onComplete is defined but onError is undefined, then
 * this will log any thrown exception. (Some database libraries only use a
 * callback, so onError is required to be notified of an exception.)
 * @return {PublicKey} If onComplete is omitted, return the public key.
 * Otherwise, if onComplete is supplied then return undefined and use onComplete
 * as described above.
 */
IdentityManager.prototype.getPublicKey = function(keyName, onComplete, onError)
{
  return SyncPromise.complete(onComplete, onError,
    this.identityStorage.getKeyPromise(keyName, !onComplete)
    .then(function(keyDer) {
      return SyncPromise.resolve(new PublicKey(keyDer));
    }));
};

// TODO: Add two versions of createIdentityCertificate.

/**
 * Prepare an unsigned identity certificate.
 * @param {Name} keyName The key name, e.g., `/{identity_name}/ksk-123456`.
 * @param {PublicKey} publicKey (optional) The public key to sign. If ommited,
 * use the keyName to get the public key from the identity storage.
 * @param {Name} signingIdentity The signing identity.
 * @param {number} notBefore See IdentityCertificate.
 * @param {number} notAfter See IdentityCertificate.
 * @param {Array<CertificateSubjectDescription>} subjectDescription A list of
 * CertificateSubjectDescription. See IdentityCertificate. If null or empty,
 * this adds a an ATTRIBUTE_NAME based on the keyName.
 * @param {Name} certPrefix (optional) The prefix before the `KEY` component. If
 * null or omitted, this infers the certificate name according to the relation
 * between the signingIdentity and the subject identity. If the signingIdentity
 * is a prefix of the subject identity, `KEY` will be inserted after the
 * signingIdentity, otherwise `KEY` is inserted after subject identity (i.e.,
 * before `ksk-...`).
 * @param {function} onComplete (optional) This calls onComplete(certificate)
 * with the unsigned IdentityCertificate, or null if the inputs are invalid. If
 * omitted, the return value is described below. (Some database libraries only
 * use a callback, so onComplete is required to use these.)
 * @param {function} onError (optional) If defined, then onComplete must be
 * defined and if there is an exception, then this calls onError(exception)
 * with the exception. If onComplete is defined but onError is undefined, then
 * this will log any thrown exception. (Some database libraries only use a
 * callback, so onError is required to be notified of an exception.)
 * @return {IdentityCertificate} If onComplete is omitted, return the the
 * unsigned IdentityCertificate, or null if the inputs are invalid. Otherwise,
 * if onComplete is supplied then return undefined and use onComplete as
 * described above.
 */
IdentityManager.prototype.prepareUnsignedIdentityCertificate = function
  (keyName, publicKey, signingIdentity, notBefore, notAfter, subjectDescription,
   certPrefix, onComplete, onError)
{
  if (!(publicKey instanceof PublicKey)) {
    // The publicKey was omitted. Shift arguments.
    onError = onComplete;
    onComplete = certPrefix;
    certPrefix = subjectDescription;
    subjectDescription = notAfter;
    notAfter = notBefore;
    notBefore = signingIdentity;
    signingIdentity = publicKey;
    publicKey = null;
  }

  // certPrefix may be omitted or null, so check for it and the following args.
  var arg7 = certPrefix;
  var arg8 = onComplete;
  var arg9 = onError;
  if (arg7 instanceof Name)
    certPrefix = arg7;
  else
    certPrefix = null;

  if (typeof arg7 === 'function') {
    onComplete = arg7;
    onError = arg8;
  }
  else if (typeof arg8 === 'function') {
    onComplete = arg8;
    onError = arg9;
  }
  else {
    onComplete = null;
    onError = null;
  }

  var promise;
  if (publicKey == null)
    promise =  this.prepareUnsignedIdentityCertificatePromise
      (keyName, signingIdentity, notBefore, notAfter, subjectDescription,
       certPrefix, !onComplete);
  else
    promise =  this.prepareUnsignedIdentityCertificatePromise
      (keyName, publicKey, signingIdentity, notBefore, notAfter,
       subjectDescription, certPrefix, !onComplete);
  return SyncPromise.complete(onComplete, onError, promise);
};

/**
 * Prepare an unsigned identity certificate.
 * @param {Name} keyName The key name, e.g., `/{identity_name}/ksk-123456`.
 * @param {PublicKey} publicKey (optional) The public key to sign. If ommited,
 * use the keyName to get the public key from the identity storage.
 * @param {Name} signingIdentity The signing identity.
 * @param {number} notBefore See IdentityCertificate.
 * @param {number} notAfter See IdentityCertificate.
 * @param {Array<CertificateSubjectDescription>} subjectDescription A list of
 * CertificateSubjectDescription. See IdentityCertificate. If null or empty,
 * this adds a an ATTRIBUTE_NAME based on the keyName.
 * @param {Name} certPrefix (optional) The prefix before the `KEY` component. If
 * null or omitted, this infers the certificate name according to the relation
 * between the signingIdentity and the subject identity. If the signingIdentity
 * is a prefix of the subject identity, `KEY` will be inserted after the
 * signingIdentity, otherwise `KEY` is inserted after subject identity (i.e.,
 * before `ksk-...`).
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that returns the unsigned
 * IdentityCertificate, or that returns null if the inputs are invalid.
 */
IdentityManager.prototype.prepareUnsignedIdentityCertificatePromise = function
  (keyName, publicKey, signingIdentity, notBefore, notAfter, subjectDescription,
   certPrefix, useSync)
{
  if (!(publicKey instanceof PublicKey)) {
    // The publicKey was omitted. Shift arguments.
    useSync = certPrefix;
    certPrefix = subjectDescription;
    subjectDescription = notAfter;
    notAfter = notBefore;
    notBefore = signingIdentity;
    signingIdentity = publicKey;
    publicKey = null;
  }

  // certPrefix may be omitted or null, so check for it and the following arg.
  var arg7 = certPrefix;
  var arg8 = useSync;
  if (arg7 instanceof Name)
    certPrefix = arg7;
  else
    certPrefix = null;

  if (typeof arg7 === 'boolean')
    useSync = arg7;
  else if (typeof arg8 === 'boolean')
    useSync = arg8;
  else
    useSync = false;

  var promise;
  if (publicKey == null) {
    promise = this.identityStorage.getKeyPromise(keyName, useSync)
    .then(function(keyDer) {
      publicKey = new PublicKey(keyDer);
      return SyncPromise.resolve();
    });
  }
  else
    promise = SyncPromise.resolve();

  return promise
  .then(function() {
    return SyncPromise.resolve
      (IdentityManager.prepareUnsignedIdentityCertificateHelper_
       (keyName, publicKey, signingIdentity, notBefore, notAfter,
        subjectDescription, certPrefix));
  });
};

/**
 * A helper for prepareUnsignedIdentityCertificatePromise where the publicKey
 * is known.
 */
IdentityManager.prepareUnsignedIdentityCertificateHelper_ = function
  (keyName, publicKey, signingIdentity, notBefore, notAfter, subjectDescription,
   certPrefix)
{
  if (keyName.size() < 1)
    return null;

  var tempKeyIdPrefix = keyName.get(-1).toEscapedString();
  if (tempKeyIdPrefix.length < 4)
    return null;
  keyIdPrefix = tempKeyIdPrefix.substr(0, 4);
  if (keyIdPrefix != "ksk-" && keyIdPrefix != "dsk-")
    return null;

  var certificate = new IdentityCertificate();
  var certName = new Name();

  if (certPrefix == null) {
    // No certificate prefix hint, so infer the prefix.
    if (signingIdentity.match(keyName))
      certName.append(signingIdentity)
        .append("KEY")
        .append(keyName.getSubName(signingIdentity.size()))
        .append("ID-CERT")
        .appendVersion(new Date().getTime());
    else
      certName.append(keyName.getPrefix(-1))
        .append("KEY")
        .append(keyName.get(-1))
        .append("ID-CERT")
        .appendVersion(new Date().getTime());
  }
  else {
    // A cert prefix hint is supplied, so determine the cert name.
    if (certPrefix.match(keyName) && !certPrefix.equals(keyName))
      certName.append(certPrefix)
        .append("KEY")
        .append(keyName.getSubName(certPrefix.size()))
        .append("ID-CERT")
        .appendVersion(new Date().getTime());
    else
      return null;
  }

  certificate.setName(certName);
  certificate.setNotBefore(notBefore);
  certificate.setNotAfter(notAfter);
  certificate.setPublicKeyInfo(publicKey);

  if (subjectDescription == null || subjectDescription.length === 0)
    certificate.addSubjectDescription(new CertificateSubjectDescription
      ("2.5.4.41", keyName.getPrefix(-1).toUri()));
  else {
    for (var i = 0; i < subjectDescription.length; ++i)
      certificate.addSubjectDescription(subjectDescription[i]);
  }

  try {
    certificate.encode();
  } catch (ex) {
    throw SecurityException(new Error("DerEncodingException: " + ex));
  }

  return certificate;
};

/**
 * Add a certificate into the public key identity storage.
 * @param {IdentityCertificate} certificate The certificate to to added. This
 * makes a copy of the certificate.
 * @param {function} onComplete (optional) This calls onComplete() when complete.
 * (Some database libraries only use a callback, so onComplete is required to
 * use these.)
 * @param {function} onError (optional) If defined, then onComplete must be
 * defined and if there is an exception, then this calls onError(exception)
 * with the exception. If onComplete is defined but onError is undefined, then
 * this will log any thrown exception. (Some database libraries only use a
 * callback, so onError is required to be notified of an exception.)
 */
IdentityManager.prototype.addCertificate = function
  (certificate, onComplete, onError)
{
  return SyncPromise.complete(onComplete, onError,
    this.identityStorage.addCertificatePromise(certificate, !onComplete));
};

/**
 * Set the certificate as the default for its corresponding key.
 * @param {IdentityCertificate} certificate The certificate.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If false, this may return a SyncPromise or an async
 * Promise.
 * @return {Promise|SyncPromise} A promise which fulfills when the default
 * certificate is set.
 */
IdentityManager.prototype.setDefaultCertificateForKeyPromise = function
  (certificate, useSync)
{
  var thisManager = this;

  var keyName = certificate.getPublicKeyName();
  return this.identityStorage.doesKeyExistPromise(keyName, useSync)
  .then(function(exists) {
    if (!exists)
      throw new SecurityException(new Error
        ("No corresponding Key record for certificate!"));

    return thisManager.identityStorage.setDefaultCertificateNameForKeyPromise
      (keyName, certificate.getName(), useSync);
  });
};

/**
 * Set the certificate as the default for its corresponding key.
 * @param {IdentityCertificate} certificate The certificate.
 * @param {function} onComplete (optional) This calls onComplete() when complete.
 * (Some database libraries only use a callback, so onComplete is required to
 * use these.)
 * @param {function} onError (optional) If defined, then onComplete must be
 * defined and if there is an exception, then this calls onError(exception)
 * with the exception. If onComplete is defined but onError is undefined, then
 * this will log any thrown exception. (Some database libraries only use a
 * callback, so onError is required to be notified of an exception.)
 */
IdentityManager.prototype.setDefaultCertificateForKey = function
  (certificate, onComplete, onError)
{
  return SyncPromise.complete(onComplete, onError,
    this.setDefaultCertificateForKeyPromise(certificate, !onComplete));
};

/**
 * Add a certificate into the public key identity storage and set the
 * certificate as the default for its corresponding identity.
 * @param {IdentityCertificate} certificate The certificate to be added. This
 * makes a copy of the certificate.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If false, this may return a SyncPromise or an async
 * Promise.
 * @return {Promise|SyncPromise} A promise which fulfills when the certificate
 * is added.
 */
IdentityManager.prototype.addCertificateAsIdentityDefaultPromise = function
  (certificate, useSync)
{
  var thisManager = this;
  return this.identityStorage.addCertificatePromise(certificate, useSync)
  .then(function() {
    var keyName = certificate.getPublicKeyName();
    return thisManager.identityStorage.setDefaultKeyNameForIdentityPromise
      (keyName, useSync);
  })
  .then(function() {
    return thisManager.setDefaultCertificateForKeyPromise(certificate, useSync);
  });
};

/**
 * Add a certificate into the public key identity storage and set the
 * certificate as the default of its corresponding key.
 * @param {IdentityCertificate} certificate The certificate to be added. This
 * makes a copy of the certificate.
 * @param {function} onComplete (optional) This calls onComplete() when complete.
 * (Some database libraries only use a callback, so onComplete is required to use
 * these.)
 * @param {function} onError (optional) If defined, then onComplete must be
 * defined and if there is an exception, then this calls onError(exception)
 * with the exception. If onComplete is defined but onError is undefined, then
 * this will log any thrown exception. (Some database libraries only use a
 * callback, so onError is required to be notified of an exception.)
 */
IdentityManager.prototype.addCertificateAsDefault = function
  (certificate, onComplete, onError)
{
  var useSync = !onComplete;
  var thisManager = this;

  return SyncPromise.complete(onComplete, onError,
    this.identityStorage.addCertificatePromise(certificate, useSync)
    .then(function() {
      return thisManager.setDefaultCertificateForKeyPromise(certificate, useSync);
    }));
};

/**
 * Get a certificate which is still valid with the specified name.
 * @param {Name} certificateName The name of the requested certificate.
 * @param {function} onComplete (optional) This calls onComplete(certificate)
 * with the requested IdentityCertificate. If omitted, the return value is 
 * described below. (Some database libraries only use a callback, so onComplete
 * is required to use these.)
 * @param {function} onError (optional) If defined, then onComplete must be
 * defined and if there is an exception, then this calls onError(exception)
 * with the exception. If onComplete is defined but onError is undefined, then
 * this will log any thrown exception. (Some database libraries only use a
 * callback, so onError is required to be notified of an exception.)
 * @return {IdentityCertificate} If onComplete is omitted, return the requested
 * certificate. Otherwise, if onComplete is supplied then return undefined and
 * use onComplete as described above.
 */
IdentityManager.prototype.getCertificate = function
  (certificateName, onComplete, onError)
{
  return SyncPromise.complete(onComplete, onError,
    this.identityStorage.getCertificatePromise
      (certificateName, false, !onComplete));
};

/**
 * Get the default certificate name for the specified identity.
 * @param {Name} identityName The identity name.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which returns the default certificate
 * Name, or a promise rejected with SecurityException if the default key name
 * for the identity is not set or the default certificate name for the key name
 * is not set.
 */
IdentityManager.prototype.getDefaultCertificateNameForIdentityPromise = function
  (identityName, useSync)
{
  return this.identityStorage.getDefaultCertificateNameForIdentityPromise
    (identityName, useSync);
}

/**
 * Get the default certificate name for the specified identity, which will be
 * used when signing is performed based on identity.
 * @param {Name} identityName The name of the specified identity.
 * @param {function} onComplete (optional) This calls onComplete(certificateName)
 * with name of the default certificate. If omitted, the return value is described
 * below. (Some database libraries only use a callback, so onComplete is required
 * to use these.)
 * @param {function} onError (optional) If defined, then onComplete must be
 * defined and if there is an exception, then this calls onError(exception)
 * with the exception. If onComplete is defined but onError is undefined, then
 * this will log any thrown exception. (Some database libraries only use a
 * callback, so onError is required to be notified of an exception.)
 * @return {Name} If onComplete is omitted, return the default certificate name.
 * Otherwise, if onComplete is supplied then return undefined and use
 * onComplete as described above.
 * @throws SecurityException if the default key name for the identity is not
 * set or the default certificate name for the key name is not set. However, if
 * onComplete and onError are defined, then if there is an exception return
 * undefined and call onError(exception).
 */
IdentityManager.prototype.getDefaultCertificateNameForIdentity = function
  (identityName, onComplete, onError)
{
  return SyncPromise.complete(onComplete, onError,
    this.identityStorage.getDefaultCertificateNameForIdentityPromise
      (identityName, !onComplete));
};

/**
 * Get the default certificate name of the default identity, which will be used
 * when signing is based on identity and the identity is not specified.
 * @param {function} onComplete (optional) This calls onComplete(certificateName)
 * with name of the default certificate. If omitted, the return value is described
 * below. (Some database libraries only use a callback, so onComplete is required
 * to use these.)
 * @param {function} onError (optional) If defined, then onComplete must be
 * defined and if there is an exception, then this calls onError(exception)
 * with the exception. If onComplete is defined but onError is undefined, then
 * this will log any thrown exception. (Some database libraries only use a
 * callback, so onError is required to be notified of an exception.)
 * @return {Name} If onComplete is omitted, return the default certificate name.
 * Otherwise, if onComplete is supplied then return undefined and use
 * onComplete as described above.
 * @throws SecurityException if the default identity is not set or the default
 * key name for the identity is not set or the default certificate name for
 * the key name is not set. However, if onComplete and onError are defined, then
 * if there is an exception return undefined and call onError(exception).
 */
IdentityManager.prototype.getDefaultCertificateName = function
  (onComplete, onError)
{
  var useSync = !onComplete;
  var thisManager = this;

  return SyncPromise.complete(onComplete, onError,
    this.identityStorage.getDefaultIdentityPromise(useSync)
    .then(function(identityName) {
      return thisManager.identityStorage.getDefaultCertificateNameForIdentityPromise
        (identityName, useSync);
    }));
};

/**
 * Append all the identity names to the nameList.
 * @param {Array<Name>} nameList Append result names to nameList.
 * @param {boolean} isDefault If true, add only the default identity name. If
 * false, add only the non-default identity names.
 * @param {function} onComplete (optional) This calls onComplete() when finished
 * adding to nameList. If omitted, this returns when complete. (Some database
 * libraries only use a callback, so onComplete is required to use these.)
 * @param {function} onError (optional) If defined, then onComplete must be
 * defined and if there is an exception, then this calls onError(exception)
 * with the exception. If onComplete is defined but onError is undefined, then
 * this will log any thrown exception. (Some database libraries only use a
 * callback, so onError is required to be notified of an exception.)
 * @return {void} If onComplete is omitted, return when complete. Otherwise, if
 * onComplete is supplied then return undefined and use onComplete as described
 * above.
 */
IdentityManager.prototype.getAllIdentities = function
  (nameList, isDefault, onComplete, onError)
{
  return SyncPromise.complete(onComplete, onError,
    this.identityStorage.getAllIdentitiesPromise
      (nameList, isDefault, !onComplete));
};

/**
 * Append all the key names of a particular identity to the nameList.
 * @param {Name} identityName The identity name to search for.
 * @param {Array<Name>} nameList Append result names to nameList.
 * @param {boolean} isDefault If true, add only the default key name. If false,
 * add only the non-default key names.
 * @param {function} onComplete (optional) This calls onComplete() when finished
 * adding to nameList. If omitted, this returns when complete. (Some database
 * libraries only use a callback, so onComplete is required to use these.)
 * @param {function} onError (optional) If defined, then onComplete must be
 * defined and if there is an exception, then this calls onError(exception)
 * with the exception. If onComplete is defined but onError is undefined, then
 * this will log any thrown exception. (Some database libraries only use a
 * callback, so onError is required to be notified of an exception.)
 * @return {void} If onComplete is omitted, return when complete. Otherwise, if
 * onComplete is supplied then return undefined and use onComplete as described
 * above.
 */
IdentityManager.prototype.getAllKeyNamesOfIdentity = function
  (identityName, nameList, isDefault, onComplete, onError)
{
  return SyncPromise.complete(onComplete, onError,
    this.identityStorage.getAllKeyNamesOfIdentityPromise
      (identityName, nameList, isDefault, !onComplete));
};

/**
 * Append all the certificate names of a particular key name to the nameList.
 * @param {Name} keyName The key name to search for.
 * @param {Array<Name>} nameList Append result names to nameList.
 * @param {boolean} isDefault If true, add only the default certificate name. If
 * false, add only the non-default certificate names.
 * @param {function} onComplete (optional) This calls onComplete() when finished
 * adding to nameList. If omitted, this returns when complete. (Some database
 * libraries only use a callback, so onComplete is required to use these.)
 * @param {function} onError (optional) If defined, then onComplete must be
 * defined and if there is an exception, then this calls onError(exception)
 * with the exception. If onComplete is defined but onError is undefined, then
 * this will log any thrown exception. (Some database libraries only use a
 * callback, so onError is required to be notified of an exception.)
 * @return {void} If onComplete is omitted, return when complete. Otherwise, if
 * onComplete is supplied then return undefined and use onComplete as described
 * above.
 */
IdentityManager.prototype.getAllCertificateNamesOfKey = function
  (keyName, nameList, isDefault, onComplete, onError)
{
  return SyncPromise.complete(onComplete, onError,
    this.identityStorage.getAllCertificateNamesOfKeyPromise
      (keyName, nameList, isDefault, !onComplete));
};

/**
 * Sign the Data packet or byte array data based on the certificate name.
 * @param {Data|Buffer} target If this is a Data object, wire encode for signing,
 * update its signature and key locator field and wireEncoding. If it is a
 * Buffer, sign it to produce a Signature object.
 * @param {Name} certificateName The Name identifying the certificate which
 * identifies the signing key.
 * @param {WireFormat} (optional) The WireFormat for calling encodeData, or
 * WireFormat.getDefaultWireFormat() if omitted.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that returns the generated Signature
 * object (if target is a Buffer) or the target (if target is Data).
 */
IdentityManager.prototype.signByCertificatePromise = function
  (target, certificateName, wireFormat, useSync)
{
  useSync = (typeof wireFormat === "boolean") ? wireFormat : useSync;
  wireFormat = (typeof wireFormat === "boolean" || !wireFormat) ? WireFormat.getDefaultWireFormat() : wireFormat;

  var keyName = IdentityManager.certificateNameToPublicKeyName(certificateName);

  var thisManager = this;
  if (target instanceof Data) {
    var data = target;
    var digestAlgorithm = [0];

    return this.makeSignatureByCertificatePromise
      (certificateName, digestAlgorithm, useSync)
    .then(function(signature) {
      data.setSignature(signature);
      // Encode once to get the signed portion.
      var encoding = data.wireEncode(wireFormat);

      return thisManager.privateKeyStorage.signPromise
        (encoding.signedBuf(), keyName, digestAlgorithm[0], useSync);
    })
    .then(function(signatureValue) {
      data.getSignature().setSignature(signatureValue);
      // Encode again to include the signature.
      data.wireEncode(wireFormat);

      return SyncPromise.resolve(data);
    });
  }
  else {
    var digestAlgorithm = [0];
    return this.makeSignatureByCertificatePromise
      (certificateName, digestAlgorithm, useSync)
    .then(function(signature) {
      return thisManager.privateKeyStorage.signPromise
        (target, keyName, digestAlgorithm[0], useSync);
    })
    .then(function (signatureValue) {
      signature.setSignature(signatureValue);
      return SyncPromise.resolve(signature);
    });
  }
};

/**
 * Sign the Data packet or byte array data based on the certificate name.
 * @param {Data|Buffer} target If this is a Data object, wire encode for signing,
 * update its signature and key locator field and wireEncoding. If it is a
 * Buffer, sign it to produce a Signature object.
 * @param {Name} certificateName The Name identifying the certificate which
 * identifies the signing key.
 * @param {WireFormat} (optional) The WireFormat for calling encodeData, or
 * WireFormat.getDefaultWireFormat() if omitted.
 * @param {function} onComplete (optional) If target is a Data object, this calls
 * onComplete(data) with the supplied Data object which has been modified to set
 * its signature. If target is a Buffer, this calls onComplete(signature) where
 * signature is the produced Signature object. If omitted, the return value is
 * described below. (Some crypto libraries only use a callback, so onComplete is
 * required to use these.)
 * @param {function} onError (optional) If defined, then onComplete must be
 * defined and if there is an exception, then this calls onError(exception)
 * with the exception. If onComplete is defined but onError is undefined, then
 * this will log any thrown exception. (Some crypto libraries only use a
 * callback, so onError is required to be notified of an exception.)
 * @return {Signature} If onComplete is omitted, return the generated Signature
 * object (if target is a Buffer) or the target (if target is Data). Otherwise,
 * if onComplete is supplied then return undefined and use onComplete as described
 * above.
 */
IdentityManager.prototype.signByCertificate = function
  (target, certificateName, wireFormat, onComplete, onError)
{
  onError = (typeof wireFormat === "function") ? onComplete : onError;
  onComplete = (typeof wireFormat === "function") ? wireFormat : onComplete;
  wireFormat = (typeof wireFormat === "function" || !wireFormat) ? WireFormat.getDefaultWireFormat() : wireFormat;

  return SyncPromise.complete(onComplete, onError,
    this.signByCertificatePromise
      (target, certificateName, wireFormat, !onComplete));
};

/**
 * Append a SignatureInfo to the Interest name, sign the name components and
 * append a final name component with the signature bits.
 * @param {Interest} interest The Interest object to be signed. This appends
 * name components of SignatureInfo and the signature bits.
 * @param {Name} certificateName The certificate name of the key to use for
 * signing.
 * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
 * the input. If omitted, use WireFormat getDefaultWireFormat().
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that returns the supplied Interest.
 */
IdentityManager.prototype.signInterestByCertificatePromise = function
  (interest, certificateName, wireFormat, useSync)
{
  useSync = (typeof wireFormat === "boolean") ? wireFormat : useSync;
  wireFormat = (typeof wireFormat === "boolean" || !wireFormat) ? WireFormat.getDefaultWireFormat() : wireFormat;

  var thisManager = this;
  var signature;
  var digestAlgorithm = [0];
  return this.makeSignatureByCertificatePromise
      (certificateName, digestAlgorithm, useSync)
  .then(function(localSignature) {
    signature = localSignature;
    // Append the encoded SignatureInfo.
    interest.getName().append(wireFormat.encodeSignatureInfo(signature));

    // Append an empty signature so that the "signedPortion" is correct.
    interest.getName().append(new Name.Component());
    // Encode once to get the signed portion.
    var encoding = interest.wireEncode(wireFormat);
    var keyName = IdentityManager.certificateNameToPublicKeyName
      (certificateName);

    return thisManager.privateKeyStorage.signPromise
      (encoding.signedBuf(), keyName, digestAlgorithm[0], useSync);
  })
  .then(function(signatureValue) {
    signature.setSignature(signatureValue);

    // Remove the empty signature and append the real one.
    interest.setName(interest.getName().getPrefix(-1).append
      (wireFormat.encodeSignatureValue(signature)));
    return SyncPromise.resolve(interest);
  });
};

/**
 * Append a SignatureInfo to the Interest name, sign the name components and
 * append a final name component with the signature bits.
 * @param {Interest} interest The Interest object to be signed. This appends
 * name components of SignatureInfo and the signature bits.
 * @param {Name} certificateName The certificate name of the key to use for
 * signing.
 * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
 * the input. If omitted, use WireFormat getDefaultWireFormat().
 * @param {function} onComplete (optional) This calls onComplete(interest) with
 * the supplied Interest object which has been modified to set its signature. If
 * omitted, then return when the interest has been signed. (Some crypto
 * libraries only use a callback, so onComplete is required to use these.)
 * @param {function} onError (optional) If defined, then onComplete must be
 * defined and if there is an exception, then this calls onError(exception)
 * with the exception. If onComplete is defined but onError is undefined, then
 * this will log any thrown exception. (Some crypto libraries only use a
 * callback, so onError is required to be notified of an exception.)
 * @return {Signature} If onComplete is omitted, return the interest. Otherwise,
 * if onComplete is supplied then return undefined and use onComplete as
 * described above.
 */
IdentityManager.prototype.signInterestByCertificate = function
  (interest, certificateName, wireFormat, onComplete, onError)
{
  onError = (typeof wireFormat === "function") ? onComplete : onError;
  onComplete = (typeof wireFormat === "function") ? wireFormat : onComplete;
  wireFormat = (typeof wireFormat === "function" || !wireFormat) ? WireFormat.getDefaultWireFormat() : wireFormat;

  return SyncPromise.complete(onComplete, onError,
    this.signInterestByCertificatePromise
      (interest, certificateName, wireFormat, !onComplete));
};

/**
 * Wire encode the Data object, digest it and set its SignatureInfo to a
 * DigestSha256.
 * @param {Data} data The Data object to be signed. This updates its signature
 * and wireEncoding.
 * @param {WireFormat} (optional) The WireFormat for calling encodeData, or
 * WireFormat.getDefaultWireFormat() if omitted.
 */
IdentityManager.prototype.signWithSha256 = function(data, wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());

  data.setSignature(new DigestSha256Signature());
  // Encode once to get the signed portion.
  var encoding = data.wireEncode(wireFormat);

  // Digest and set the signature.
  var hash = Crypto.createHash('sha256');
  hash.update(encoding.signedBuf());
  data.getSignature().setSignature(new Blob(hash.digest(), false));

  // Encode again to include the signature.
  data.wireEncode(wireFormat);
};

/**
 * Append a SignatureInfo for DigestSha256 to the Interest name, digest the
   * name components and append a final name component with the signature bits
   * (which is the digest).
 * @param {Interest} interest The Interest object to be signed. This appends
 * name components of SignatureInfo and the signature bits.
 * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
 * the input. If omitted, use WireFormat getDefaultWireFormat().
 */
IdentityManager.prototype.signInterestWithSha256 = function(interest, wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());

  var signature = new DigestSha256Signature();

  // Append the encoded SignatureInfo.
  interest.getName().append(wireFormat.encodeSignatureInfo(signature));

  // Append an empty signature so that the "signedPortion" is correct.
  interest.getName().append(new Name.Component());
  // Encode once to get the signed portion.
  var encoding = interest.wireEncode(wireFormat);

  // Digest and set the signature.
  var hash = Crypto.createHash('sha256');
  hash.update(encoding.signedBuf());
  signature.setSignature(new Blob(hash.digest(), false));

  // Remove the empty signature and append the real one.
  interest.setName(interest.getName().getPrefix(-1).append
    (wireFormat.encodeSignatureValue(signature)));
};

/**
 * Generate a self-signed certificate for a public key.
 * @param {Name} keyName The name of the public key.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If false, this may return a SyncPromise or an async
 * Promise.
 * @return {Promise|SyncPromise} A promise which returns the generated
 * IdentityCertificate.
 */
IdentityManager.prototype.selfSignPromise = function(keyName, useSync)
{
  var certificate = new IdentityCertificate();

  var thisManager = this;
  return this.identityStorage.getKeyPromise(keyName, useSync)
  .then(function(keyBlob) {
    var publicKey = new PublicKey(keyBlob);

    var notBefore = new Date().getTime();
    var notAfter = notBefore + 2 * 365 * 24 * 3600 * 1000; // about 2 years

    certificate.setNotBefore(notBefore);
    certificate.setNotAfter(notAfter);

    var certificateName = keyName.getPrefix(-1).append("KEY").append
      (keyName.get(-1)).append("ID-CERT").appendVersion(certificate.getNotBefore());
    certificate.setName(certificateName);

    certificate.setPublicKeyInfo(publicKey);
    certificate.addSubjectDescription(new CertificateSubjectDescription
      ("2.5.4.41", keyName.toUri()));
    certificate.encode();

    return thisManager.signByCertificatePromise
      (certificate, certificate.getName(), useSync);
  })
};

/**
 * Generate a self-signed certificate for a public key.
 * @param {Name} keyName The name of the public key.
 * @param {function} onComplete (optional) This calls onComplete(certificate)
 * with the the generated IdentityCertificate. If omitted, the return value is
 * described below. (Some crypto libraries only use a callback, so onComplete is
 * required to use these.)
 * @return {IdentityCertificate} If onComplete is omitted, return the
 * generated certificate. Otherwise, if onComplete is supplied then return
 * undefined and use onComplete as described above.
 * @param {function} onError (optional) If defined, then onComplete must be
 * defined and if there is an exception, then this calls onError(exception)
 * with the exception. If onComplete is defined but onError is undefined, then
 * this will log any thrown exception. (Some crypto libraries only use a
 * callback, so onError is required to be notified of an exception.)
 */
IdentityManager.prototype.selfSign = function(keyName, onComplete, onError)
{
  return SyncPromise.complete(onComplete, onError,
    this.selfSignPromise(keyName, !onComplete));
};

/**
 * Get the public key name from the full certificate name.
 *
 * @param {Name} certificateName The full certificate name.
 * @return {Name} The related public key name.
 * TODO: Move this to IdentityCertificate
 */
IdentityManager.certificateNameToPublicKeyName = function(certificateName)
{
  var i = certificateName.size() - 1;
  var idString = "ID-CERT";
  while (i >= 0) {
    if (certificateName.get(i).toEscapedString() == idString)
      break;
    --i;
  }

  var tmpName = certificateName.getSubName(0, i);
  var keyString = "KEY";
  i = 0;
  while (i < tmpName.size()) {
    if (tmpName.get(i).toEscapedString() == keyString)
      break;
    ++i;
  }

  return tmpName.getSubName(0, i).append(tmpName.getSubName
    (i + 1, tmpName.size() - i - 1));
};

/**
 * Return a new Signature object based on the signature algorithm of the public
 * key with keyName (derived from certificateName).
 * @param {Name} certificateName The certificate name.
 * @param {Array} digestAlgorithm Set digestAlgorithm[0] to the signature
 * algorithm's digest algorithm, e.g. DigestAlgorithm.SHA256.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If false, this may return a SyncPromise or an async
 * Promise.
 * @return {Promise|SyncPromise} A promise which returns a new object of the
 * correct subclass of Signature.
 */
IdentityManager.prototype.makeSignatureByCertificatePromise = function
  (certificateName, digestAlgorithm, useSync)
{
  var keyName = IdentityManager.certificateNameToPublicKeyName(certificateName);
  return this.privateKeyStorage.getPublicKeyPromise(keyName, useSync)
  .then(function(publicKey) {
    var keyType = publicKey.getKeyType();

    var signature = null;
    if (keyType == KeyType.RSA) {
      signature = new Sha256WithRsaSignature();
      digestAlgorithm[0] = DigestAlgorithm.SHA256;

      signature.getKeyLocator().setType(KeyLocatorType.KEYNAME);
      signature.getKeyLocator().setKeyName(certificateName.getPrefix(-1));
    }
    else if (keyType == KeyType.ECDSA) {
      signature = new Sha256WithEcdsaSignature();
      digestAlgorithm[0] = DigestAlgorithm.SHA256;

      signature.getKeyLocator().setType(KeyLocatorType.KEYNAME);
      signature.getKeyLocator().setKeyName(certificateName.getPrefix(-1));
    }
    else
      throw new SecurityException(new Error("Key type is not recognized"));

    return SyncPromise.resolve(signature);
  });
};

/**
 * A private method to generate a pair of keys for the specified identity.
 * @param {Name} identityName The name of the identity.
 * @param {boolean} isKsk true for generating a Key-Signing-Key (KSK), false for
 * a Data-Signing-Key (DSK).
 * @param {KeyParams} params The parameters of the key.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If false, this may return a SyncPromise or an async
 * Promise.
 * @return {Promise|SyncPromise} A promise which returns the generated key name.
 */
IdentityManager.prototype.generateKeyPairPromise = function
  (identityName, isKsk, params, useSync)
{
  var keyName;
  var thisManager = this;
  return this.identityStorage.getNewKeyNamePromise(identityName, isKsk, useSync)
  .then(function(localKeyName) {
    keyName = localKeyName;
    return thisManager.privateKeyStorage.generateKeyPairPromise
      (keyName, params, useSync);
  })
  .then(function() {
    return thisManager.privateKeyStorage.getPublicKeyPromise
      (keyName, useSync);
  })
  .then(function(publicKey) {
    return thisManager.identityStorage.addKeyPromise
      (keyName, params.getKeyType(), publicKey.getKeyDer());
  })
  .then(function() {
    return SyncPromise.resolve(keyName);
  });
};

/**
 * Get the IdentityStorage from the pib value in the configuration file if
 * supplied. Otherwise, get the default for this platform.
 * @param {ConfigFile} config The configuration file to check.
 * @param {function} initialCheckPromise This is passed to the
 * BasicIdentityStorage constructor. See it for details.
 * @return {IdentityStorage} A new IdentityStorage.
 */
IdentityManager.getDefaultIdentityStorage_ = function(config, initialCheckPromise)
{
  // Assume we are in Node.js.
  var pibLocator = config.get("pib", "");

  if (pibLocator !== "") {
    // Don't support non-default locations for now.
    if (pibLocator !== "pib-sqlite3")
      throw new SecurityException(new Error
        ("Invalid config file pib value: " + pibLocator));
  }

  return new BasicIdentityStorage(initialCheckPromise);
};

/**
 * Get the PrivateKeyStorage from the tpm value in the configuration file if
 * supplied. Otherwise, get the default for this platform.
 * @param {ConfigFile} config The configuration file to check.
 * @param {Array<string>} canonicalTpmLocator Set canonicalTpmLocator[0] to the
 * canonical value including the colon, * e.g. "tpm-file:".
 * @return A new PrivateKeyStorage.
 */
IdentityManager.getDefaultPrivateKeyStorage_ = function
  (config, canonicalTpmLocator)
{
  var tpmLocator = config.get("tpm", "");

  if (tpmLocator === "") {
    // Assume we are in Node.js, so check the system.
    if (process.platform === "darwin") {
      canonicalTpmLocator[0] = "tpm-osxkeychain:";
      throw new SecurityException(new Error
        ("IdentityManager: OS X key chain storage is not yet implemented. You must supply a privateKeyStorage."));
    }
    else {
      canonicalTpmLocator[0] = "tpm-file:";
      return new FilePrivateKeyStorage();
    }
  }
  else if (tpmLocator === "tpm-osxkeychain") {
    canonicalTpmLocator[0] = "tpm-osxkeychain:";
    throw new SecurityException(new Error
      ("IdentityManager: tpm-osxkeychain is not yet implemented."));
  }
  else if (tpmLocator === "tpm-file") {
    canonicalTpmLocator[0] = "tpm-file:";
    return new FilePrivateKeyStorage();
  }
  else
    throw new SecurityException(new Error
      ("Invalid config file tpm value: " + tpmLocator));
};

/**
 * Check that identityStorage.getTpmLocatorPromise() (if defined) matches the
 * canonicalTpmLocator. This has to be an async Promise because it calls async
 * getTpmLocatorPromise.
 * @param canonicalTpmLocator The canonical locator from
 * getDefaultPrivateKeyStorage().
 * @return {Promise} A promise which resolves if canonicalTpmLocator is OK, or a
 * promise rejected with SecurityException if the private key storage does not
 * match.
 */
IdentityManager.prototype.checkTpmPromise_ = function(canonicalTpmLocator)
{
  return this.identityStorage.getTpmLocatorPromise()
  .then(function(tpmLocator) {
    // Just check. If a PIB reset is required, expect ndn-cxx/NFD to do it.
    if (tpmLocator !== "" && tpmLocator !== canonicalTpmLocator)
      return Promise.reject(new SecurityException(new Error
        ("The TPM locator supplied does not match the TPM locator in the PIB: " +
         tpmLocator + " != " + canonicalTpmLocator)));
    else
      return Promise.resolve();
  }, function(err) {
    // The TPM locator is not set in the PIB yet.
    return Promise.resolve();
  });
};
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
 *
 * 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.
 */

/**
 * A ValidationRequest is used to return information from
 * PolicyManager.checkVerificationPolicy.
 *
 * Create a new ValidationRequest with the given values.
 * @param {Interest} interest An interest for fetching more data.
 * @param {function} onVerified If the signature is verified, this calls
 * onVerified(data).
 * @param {function} onValidationFailed If the signature check fails, this calls
 * onValidationFailed(data, reason).
 * @param {number} retry The number of retrials when there is an interest timeout.
 * @param {number} stepCount  The number of verification steps that have been
 * done, used to track the verification progress.
 * @constructor
 */
var ValidationRequest = function ValidationRequest
  (interest, onVerified, onValidationFailed, retry, stepCount)
{
  this.interest = interest;
  this.onVerified = onVerified;
  this.onValidationFailed = onValidationFailed;
  this.retry = retry;
  this.stepCount = stepCount;
};

exports.ValidationRequest = ValidationRequest;
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
 *
 * 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.
 */

// Use capitalized Crypto to not clash with the browser's crypto.subtle.
/** @ignore */
var Crypto = require('../../crypto.js'); /** @ignore */
var Blob = require('../../util/blob.js').Blob; /** @ignore */
var DataUtils = require('../../encoding/data-utils.js').DataUtils; /** @ignore */
var SecurityException = require('../security-exception.js').SecurityException; /** @ignore */
var DigestSha256Signature = require('../../digest-sha256-signature.js').DigestSha256Signature; /** @ignore */
var Sha256WithRsaSignature = require('../../sha256-with-rsa-signature.js').Sha256WithRsaSignature; /** @ignore */
var Sha256WithEcdsaSignature = require('../../sha256-with-ecdsa-signature.js').Sha256WithEcdsaSignature; /** @ignore */
var UseSubtleCrypto = require("../../use-subtle-crypto-node.js").UseSubtleCrypto;

/**
 * A PolicyManager is an abstract base class to represent the policy for
 * verifying data packets. You must create an object of a subclass.
 * @constructor
 */
var PolicyManager = function PolicyManager()
{
};

exports.PolicyManager = PolicyManager;

/**
 * Check if the received data packet or signed interest can escape from
 * verification and be trusted as valid.
 * Your derived class should override.
 *
 * @param {Data|Interest} dataOrInterest The received data packet or interest.
 * @return {boolean} True if the data or interest does not need to be verified
 * to be trusted as valid, otherwise false.
 */
PolicyManager.prototype.skipVerifyAndTrust = function(dataOrInterest)
{
  throw new Error("PolicyManager.skipVerifyAndTrust is not implemented");
};

/**
 * Check if this PolicyManager has a verification rule for the received data
 * packet or signed interest.
 * Your derived class should override.
 *
 * @param {Data|Interest} dataOrInterest The received data packet or interest.
 * @return {boolean} True if the data or interest must be verified, otherwise
 * false.
 */
PolicyManager.prototype.requireVerify = function(dataOrInterest)
{
  throw new Error("PolicyManager.requireVerify is not implemented");
};

/**
 * Check whether the received data or interest packet complies with the
 * verification policy, and get the indication of the next verification step.
 * Your derived class should override.
 *
 * @param {Data|Interest} dataOrInterest The Data object or interest with the
 * signature to check.
 * @param {number} stepCount The number of verification steps that have been
 * done, used to track the verification progress.
 * @param {function} onVerified If the signature is verified, this calls
 * onVerified(dataOrInterest).
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onValidationFailed If the signature check fails, this calls
 * onValidationFailed(dataOrInterest, reason).
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {WireFormat} wireFormat
 * @return {ValidationRequest} The indication of next verification step, or
 * null if there is no further step.
 */
PolicyManager.prototype.checkVerificationPolicy = function
  (dataOrInterest, stepCount, onVerified, onValidationFailed, wireFormat)
{
  throw new Error("PolicyManager.checkVerificationPolicy is not implemented");
};

/**
 * Check if the signing certificate name and data name satisfy the signing
 * policy.
 * Your derived class should override.
 *
 * @param {Name} dataName The name of data to be signed.
 * @param {Name} certificateName The name of signing certificate.
 * @return {boolean} True if the signing certificate can be used to sign the
 * data, otherwise false.
 */
PolicyManager.prototype.checkSigningPolicy = function(dataName, certificateName)
{
  throw new Error("PolicyManager.checkSigningPolicy is not implemented");
};

/**
 * Infer the signing identity name according to the policy. If the signing
 * identity cannot be inferred, return an empty name.
 * Your derived class should override.
 *
 * @param {Name} dataName The name of data to be signed.
 * @return {Name} The signing identity or an empty name if cannot infer.
 */
PolicyManager.prototype.inferSigningIdentity = function(dataName)
{
  throw new Error("PolicyManager.inferSigningIdentity is not implemented");
};

// The first time verify is called, it sets this to determine if a signature
// buffer needs to be converted to a string for the crypto verifier.
PolicyManager.verifyUsesString_ = null;
PolicyManager.setVerifyUsesString_ = function()
{
  var hashResult = Crypto.createHash('sha256').digest();
  // If the hash result is a string, we assume that this is a version of
  //   crypto where verify also uses a string signature.
  PolicyManager.verifyUsesString_ = (typeof hashResult === 'string');
};

/**
 * Check the type of signature and use the publicKeyDer to verify the
 * signedBlob using the appropriate signature algorithm.
 * @param {Signature} signature An object of a subclass of Signature, e.g.
 * Sha256WithRsaSignature.
 * @param {SignedBlob} signedBlob the SignedBlob with the signed portion to
 * verify.
 * @param {Blob} publicKeyDer The DER-encoded public key used to verify the
 * signature.
 * @param {function} onComplete This calls onComplete(true) if the signature
 * verifies, otherwise onComplete(false).
 * @throws SecurityException if the signature type is not recognized or if
 * publicKeyDer can't be decoded.
 */
PolicyManager.verifySignature = function
  (signature, signedBlob, publicKeyDer, onComplete)
{
  if (signature instanceof Sha256WithRsaSignature) {
    if (publicKeyDer.isNull()) {
      onComplete(false);
      return;
    }
    PolicyManager.verifySha256WithRsaSignature
      (signature.getSignature(), signedBlob, publicKeyDer, onComplete);
  }
  else if (signature instanceof Sha256WithEcdsaSignature) {
    if (publicKeyDer.isNull()) {
      onComplete(false);
      return;
    }
    PolicyManager.verifySha256WithEcdsaSignature
      (signature.getSignature(), signedBlob, publicKeyDer, onComplete);
  }
  else if (signature instanceof DigestSha256Signature)
    PolicyManager.verifyDigestSha256Signature
      (signature.getSignature(), signedBlob, onComplete);
  else
    // We don't expect this to happen.
    throw new SecurityException(new Error
      ("PolicyManager.verify: Signature type is unknown"));
};

/**
 * Verify the RSA signature on the SignedBlob using the given public key.
 * @param {Blob} signature The signature bits.
 * @param {SignedBlob} signedBlob the SignedBlob with the signed portion to
 * verify.
 * @param {Blob} publicKeyDer The DER-encoded public key used to verify the
 * signature.
 * @param {function} onComplete This calls onComplete(true) if the signature
 * verifies, otherwise onComplete(false).
 */
PolicyManager.verifySha256WithRsaSignature = function
  (signature, signedBlob, publicKeyDer, onComplete)
{
  if (UseSubtleCrypto()){
    var algo = {name:"RSASSA-PKCS1-v1_5",hash:{name:"SHA-256"}};

    crypto.subtle.importKey("spki", publicKeyDer.buf().buffer, algo, true, ["verify"]).then(function(publicKey){
      return crypto.subtle.verify(algo, publicKey, signature.buf(), signedBlob.signedBuf())
    }).then(function(verified){
      onComplete(verified);
    });
  } else {
    if (PolicyManager.verifyUsesString_ === null)
      PolicyManager.setVerifyUsesString_();

    // The crypto verifier requires a PEM-encoded public key.
    var keyBase64 = publicKeyDer.buf().toString('base64');
    var keyPem = "-----BEGIN PUBLIC KEY-----\n";
    for (var i = 0; i < keyBase64.length; i += 64)
      keyPem += (keyBase64.substr(i, 64) + "\n");
    keyPem += "-----END PUBLIC KEY-----";

    var verifier = Crypto.createVerify('RSA-SHA256');
    verifier.update(signedBlob.signedBuf());
    var signatureBytes = PolicyManager.verifyUsesString_ ?
      DataUtils.toString(signature.buf()) : signature.buf();
    onComplete(verifier.verify(keyPem, signatureBytes));
  }
};

/**
 * Verify the ECDSA signature on the SignedBlob using the given public key.
 * @param {Blob} signature The signature bits.
 * @param {SignedBlob} signedBlob the SignedBlob with the signed portion to
 * verify.
 * @param {Blob} publicKeyDer The DER-encoded public key used to verify the
 * signature.
 * @param {function} onComplete This calls onComplete(true) if the signature
 * verifies, otherwise onComplete(false).
 */
PolicyManager.verifySha256WithEcdsaSignature = function
  (signature, signedBlob, publicKeyDer, onComplete)
{
  if (UseSubtleCrypto()) {
/*
    var algo = {name:"RSASSA-PKCS1-v1_5",hash:{name:"SHA-256"}};

    crypto.subtle.importKey("spki", publicKeyDer.buf().buffer, algo, true, ["verify"]).then(function(publicKey){
      return crypto.subtle.verify(algo, publicKey, signature.buf(), signedBlob.signedBuf())
    }).then(function(verified){
      onComplete(verified);
    });
*/  onComplete(false);
  } else {
    if (PolicyManager.verifyUsesString_ === null)
      PolicyManager.setVerifyUsesString_();

    // The crypto verifier requires a PEM-encoded public key.
    var keyBase64 = publicKeyDer.buf().toString("base64");
    var keyPem = "-----BEGIN PUBLIC KEY-----\n";
    for (var i = 0; i < keyBase64.length; i += 64)
      keyPem += (keyBase64.substr(i, 64) + "\n");
    keyPem += "-----END PUBLIC KEY-----";

    // Just create a "sha256". The Crypto library will infer ECDSA from the key.
    var verifier = Crypto.createVerify("sha256");
    verifier.update(signedBlob.signedBuf());
    var signatureBytes = PolicyManager.verifyUsesString_ ?
      DataUtils.toString(signature.buf()) : signature.buf();
    onComplete(verifier.verify(keyPem, signatureBytes));
  }
};

/**
 * Verify the DigestSha256 signature on the SignedBlob by verifying that the
 * digest of SignedBlob equals the signature.
 * @param {Blob} signature The signature bits.
 * @param {SignedBlob} signedBlob the SignedBlob with the signed portion to
 * verify.
 * @param {function} onComplete This calls onComplete(true) if the signature
 * verifies, otherwise onComplete(false).
 */
PolicyManager.verifyDigestSha256Signature = function
  (signature, signedBlob, onComplete)
{
  // Set signedPortionDigest to the digest of the signed portion of the signedBlob.
  var hash = Crypto.createHash('sha256');
  hash.update(signedBlob.signedBuf());
  var signedPortionDigest = new Blob(hash.digest(), false);

  onComplete(signedPortionDigest.equals(signature));
};
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * From PyNDN certificate_cache.py by Adeola Bannis.
 * Originally from Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>.
 *
 * 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.
 */

/** @ignore */
var IdentityCertificate = require('../certificate/identity-certificate.js').IdentityCertificate;

/**
 * A CertificateCache is used to save other users' certificate during
 * verification.
 * @constructor
 */
var CertificateCache = function CertificateCache()
{
  // The key is the certificate name URI. The value is the wire encoding Blob.
  this.cache = {};
};

exports.CertificateCache = CertificateCache;

/**
 * Insert the certificate into the cache. Assumes the timestamp is not yet
 * removed from the name.
 * @param {IdentityCertificate} certificate The certificate to insert.
 */
CertificateCache.prototype.insertCertificate = function(certificate)
{
  var certName = certificate.getName().getPrefix(-1);
  this.cache[certName.toUri()] = certificate.wireEncode();
};

/**
 * Remove a certificate from the cache. This does nothing if it is not present.
 * @param {Name} certificateName The name of the certificate to remove. This
 * assumes there is no timestamp in the name.
 */
CertificateCache.prototype.deleteCertificate = function(certificateName)
{
  delete this.cache[certificateName.toUri()];
};

/**
 * Fetch a certificate from the cache.
 * @param {Name} certificateName The name of the certificate to remove. This
 * assumes there is no timestamp in the name.
 * @return {IdentityCertificate} A new copy of the IdentityCertificate, or null
 * if not found.
 */
CertificateCache.prototype.getCertificate = function(certificateName)
{
  var certData = this.cache[certificateName.toUri()];
  if (certData === undefined)
    return null;

  var cert = new IdentityCertificate();
  cert.wireDecode(certData);
  return cert;
};

/**
 * Clear all certificates from the store.
 */
CertificateCache.prototype.reset = function()
{
  this.cache = {};
};
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * From PyNDN config_policy_manager.py by Adeola Bannis.
 * Originally from Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>.
 *
 * 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.
 */

/** @ignore */
var fs = require('fs'); /** @ignore */
var path = require('path'); /** @ignore */
var Name = require('../../name.js').Name; /** @ignore */
var Data = require('../../data.js').Data; /** @ignore */
var Interest = require('../../interest.js').Interest; /** @ignore */
var KeyLocator = require('../../key-locator.js').KeyLocator; /** @ignore */
var KeyLocatorType = require('../../key-locator.js').KeyLocatorType; /** @ignore */
var Blob = require('../../util/blob.js').Blob; /** @ignore */
var IdentityCertificate = require('../certificate/identity-certificate.js').IdentityCertificate; /** @ignore */
var BoostInfoParser = require('../../util/boost-info-parser.js').BoostInfoParser; /** @ignore */
var NdnRegexMatcher = require('../../util/ndn-regex-matcher.js').NdnRegexMatcher; /** @ignore */
var CertificateCache = require('./certificate-cache.js').CertificateCache; /** @ignore */
var ValidationRequest = require('./validation-request.js').ValidationRequest; /** @ignore */
var SecurityException = require('../security-exception.js').SecurityException; /** @ignore */
var WireFormat = require('../../encoding/wire-format.js').WireFormat; /** @ignore */
var PolicyManager = require('./policy-manager.js').PolicyManager; /** @ignore */
var NdnCommon = require('../../util/ndn-common.js').NdnCommon;

/**
 * ConfigPolicyManager manages trust according to a configuration file in the
 * Validator Configuration File Format
 * (http://redmine.named-data.net/projects/ndn-cxx/wiki/CommandValidatorConf)
 *
 * Once a rule is matched, the ConfigPolicyManager looks in the
 * CertificateCache for the IdentityCertificate matching the name in the KeyLocator
 * and uses its public key to verify the data packet or signed interest. If the
 * certificate can't be found, it is downloaded, verified and installed. A chain
 * of certificates will be followed to a maximum depth.
 * If the new certificate is accepted, it is used to complete the verification.
 *
 * The KeyLocators of data packets and signed interests MUST contain a name for
 * verification to succeed.
 *
 * Create a new ConfigPolicyManager which will act on the rules specified in the
 * configuration and download unknown certificates when necessary.
 *
 * @param {string} configFileName (optional) If not null or empty, the path to
 * the configuration file containing verification rules. (This only works in
 * Node.js since it reads files using the "fs" module.) Otherwise, you should
 * separately call load().
 * @param {CertificateCache} certificateCache (optional) A CertificateCache to
 * hold known certificates. If this is null or omitted, then create an internal
 * CertificateCache.
 * @param {number} searchDepth (optional) The maximum number of links to follow
 * when verifying a certificate chain. If omitted, use a default.
 * @param {number} graceInterval (optional) The window of time difference
 * (in milliseconds) allowed between the timestamp of the first interest signed with
 * a new public key and the validation time. If omitted, use a default value.
 * @param {number} keyTimestampTtl (optional) How long a public key's last-used
 * timestamp is kept in the store (milliseconds). If omitted, use a default value.
 * @param {number} maxTrackedKeys The maximum number of public key use
 * timestamps to track. If omitted, use a default.
 * @constructor
 */
var ConfigPolicyManager = function ConfigPolicyManager
  (configFileName, certificateCache, searchDepth, graceInterval,
   keyTimestampTtl, maxTrackedKeys)
{
  // Call the base constructor.
  PolicyManager.call(this);

  if (certificateCache == undefined)
    certificateCache = null;
  if (searchDepth == undefined)
    searchDepth = 5;
  if (graceInterval == undefined)
    graceInterval = 3000;
  if (keyTimestampTtl == undefined)
    keyTimestampTtl = 3600000;
  if (maxTrackedKeys == undefined)
    maxTrackedKeys = 1000;

  if (certificateCache == null)
    this.certificateCache = new CertificateCache();
  else
    this.certificateCache = certificateCache;
  this.maxDepth = searchDepth;
  this.keyGraceInterval = graceInterval;
  this.keyTimestampTtl = keyTimestampTtl;
  this.maxTrackedKeys = maxTrackedKeys;

  this.reset();

  if (configFileName != null && configFileName != "")
    this.load(configFileName);
};

ConfigPolicyManager.prototype = new PolicyManager();
ConfigPolicyManager.prototype.name = "ConfigPolicyManager";

exports.ConfigPolicyManager = ConfigPolicyManager;

/**
 * Reset the certificate cache and other fields to the constructor state.
 */
ConfigPolicyManager.prototype.reset = function()
{
  this.certificateCache.reset();

  // Stores the fixed-signer certificate name associated with validation rules
  // so we don't keep loading from files.
  this.fixedCertificateCache = {};

  // Stores the timestamps for each public key used in command interests to
  // avoid replay attacks.
  // Key is public key name, value is last timestamp.
  this.keyTimestamps = {};

  this.requiresVerification = true;

  this.config = new BoostInfoParser();
  this.refreshManager = new ConfigPolicyManager.TrustAnchorRefreshManager();
};

/**
 * Call reset() and load the configuration rules from the file name or the input
 * string. There are two forms:
 * load(configFileName) reads configFileName from the file system. (This only
 * works in Node.js since it reads files using the "fs" module.)
 * load(input, inputName) reads from the input, in which case inputName is used
 * only for log messages, etc.
 * @param {string} configFileName The path to the file containing configuration
 * rules.
 * @param {string} input The contents of the configuration rules, with lines
 * separated by "\n" or "\r\n".
 * @param {string} inputName Use with input for log messages, etc.
 */
ConfigPolicyManager.prototype.load = function(configFileNameOrInput, inputName)
{
  this.reset();
  this.config.read(configFileNameOrInput, inputName);
  this.loadTrustAnchorCertificates();
}

/**
 * Check if this PolicyManager has a verification rule for the received data.
 * If the configuration file contains the trust anchor 'any', nothing is
 * verified.
 *
 * @param {Data|Interest} dataOrInterest The received data packet or interest.
 * @return {boolean} true if the data must be verified, otherwise false.
 */
ConfigPolicyManager.prototype.requireVerify = function(dataOrInterest)
{
  return this.requiresVerification;
};

/**
 * Override to always indicate that the signing certificate name and data name
 * satisfy the signing policy.
 *
 * @param {Name} dataName The name of data to be signed.
 * @param {Name} certificateName The name of signing certificate.
 * @return {boolean} True to indicate that the signing certificate can be used
 * to sign the data.
 */
ConfigPolicyManager.prototype.checkSigningPolicy = function
  (dataName, certificateName)
{
  return true;
};

/**
 * Check if the received signed interest can escape from verification and be
 * trusted as valid. If the configuration file contains the trust anchor
 * 'any', nothing is verified.
 *
 * @param {Data|Interest} dataOrInterest The received data packet or interest.
 * @return {boolean} true if the data or interest does not need to be verified
 * to be trusted as valid, otherwise false.
 */
ConfigPolicyManager.prototype.skipVerifyAndTrust = function(dataOrInterest)
{
  return !this.requiresVerification;
};

/**
 * Check whether the received data packet or interest complies with the
 * verification policy, and get the indication of the next verification step.
 *
 * @param {Data|Interest} dataOrInterest The Data object or interest with the
 * signature to check.
 * @param {number} stepCount The number of verification steps that have been
 * done, used to track the verification progress.
 * @param {function} onVerified If the signature is verified, this calls
 * onVerified(dataOrInterest).
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onValidationFailed If the signature check fails, this calls
 * onValidationFailed(dataOrInterest, reason).
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {WireFormat} wireFormat
 * @return {ValidationRequest} The indication of next verification step, or
 * null if there is no further step.
 */
ConfigPolicyManager.prototype.checkVerificationPolicy = function
  (dataOrInterest, stepCount, onVerified, onValidationFailed, wireFormat)
{
  if (stepCount > this.maxDepth) {
    try {
      onValidationFailed
        (dataOrInterest, "The verification stepCount " + stepCount +
           " exceeded the maxDepth " + this.maxDepth);
    } catch (ex) {
      console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
    }
    return null;
  }

  var signature = ConfigPolicyManager.extractSignature(dataOrInterest, wireFormat);
  // No signature -> fail.
  if (signature == null) {
    try {
      onValidationFailed
        (dataOrInterest, "Cannot extract the signature from " +
         dataOrInterest.getName().toUri());
    } catch (ex) {
      console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
    }
    return null;
  }

  if (!KeyLocator.canGetFromSignature(signature)) {
    // We only support signature types with key locators.
    try {
      onValidationFailed
        (dataOrInterest, "The signature type does not support a KeyLocator");
    } catch (ex) {
      console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
    }
    return null;
  }

  var keyLocator = null;
  try {
    keyLocator = KeyLocator.getFromSignature(signature);
  }
  catch (ex) {
    // No key locator -> fail.
    try {
      onValidationFailed
        (dataOrInterest, "Error in KeyLocator.getFromSignature: " + ex);
    } catch (ex) {
      console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
    }
    return null;
  }

  var signatureName = keyLocator.getKeyName();
  // No key name in KeyLocator -> fail.
  if (signatureName.size() == 0) {
    try {
      onValidationFailed
        (dataOrInterest, "The signature KeyLocator doesn't have a key name");
    } catch (ex) {
      console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
    }
    return null;
  }

  var objectName = dataOrInterest.getName();
  var matchType = "data";

  // For command interests, we need to ignore the last 4 components when
  // matching the name.
  if (dataOrInterest instanceof Interest) {
    objectName = objectName.getPrefix(-4);
    matchType = "interest";
  }

  // First see if we can find a rule to match this packet.
  var matchedRule = this.findMatchingRule(objectName, matchType);

  // No matching rule -> fail.
  if (matchedRule == null) {
    try {
      onValidationFailed
        (dataOrInterest, "No matching rule found for " + objectName.toUri());
    } catch (ex) {
      console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
    }
    return null;
  }

  var failureReason = ["unknown"];
  var signatureMatches = this.checkSignatureMatch
    (signatureName, objectName, matchedRule, failureReason);
  if (!signatureMatches) {
    try {
      onValidationFailed(dataOrInterest, failureReason[0]);
    } catch (ex) {
      console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
    }
    return null;
  }

  // Before we look up keys, refresh any certificate directories.
  this.refreshManager.refreshAnchors();

  // Now finally check that the data or interest was signed correctly.
  // If we don't actually have the certificate yet, create a
  // ValidationRequest for it.
  var foundCert = this.refreshManager.getCertificate(signatureName);
  if (foundCert == null)
    foundCert = this.certificateCache.getCertificate(signatureName);
  var thisManager = this;
  if (foundCert == null) {
    var certificateInterest = new Interest(signatureName);
    var onCertificateDownloadComplete = function(data) {
      var certificate;
      try {
        certificate = new IdentityCertificate(data);
      } catch (ex) {
        try {
          onValidationFailed
            (dataOrInterest, "Cannot decode certificate " + data.getName().toUri());
        } catch (ex) {
          console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
        }
        return null;
      }
      thisManager.certificateCache.insertCertificate(certificate);
      thisManager.checkVerificationPolicy
        (dataOrInterest, stepCount + 1, onVerified, onValidationFailed);
    };

    var nextStep = new ValidationRequest
      (certificateInterest, onCertificateDownloadComplete, onValidationFailed,
       2, stepCount + 1);

    return nextStep;
  }

  // For interests, we must check that the timestamp is fresh enough.
  // We do this after (possibly) downloading the certificate to avoid
  // filling the cache with bad keys.
  if (dataOrInterest instanceof Interest) {
    var keyName = foundCert.getPublicKeyName();
    var timestamp = dataOrInterest.getName().get(-4).toNumber();

    if (!this.interestTimestampIsFresh(keyName, timestamp, failureReason)) {
      try {
        onValidationFailed(dataOrInterest, failureReason[0]);
      } catch (ex) {
        console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
      }
      return null;
    }
  }

  // Certificate is known, so verify the signature.
  this.verify(signature, dataOrInterest.wireEncode(), function (verified, reason) {
    if (verified) {
      try {
        onVerified(dataOrInterest);
      } catch (ex) {
        console.log("Error in onVerified: " + NdnCommon.getErrorWithStackTrace(ex));
      }
      if (dataOrInterest instanceof Interest)
        thisManager.updateTimestampForKey(keyName, timestamp);
    }
    else {
      try {
        onValidationFailed(dataOrInterest, reason);
      } catch (ex) {
        console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
      }
    }
  });
};

/**
 * The configuration file allows 'trust anchor' certificates to be preloaded.
 * The certificates may also be loaded from a directory, and if the 'refresh'
 * option is set to an interval, the certificates are reloaded at the specified
 * interval.
 */
ConfigPolicyManager.prototype.loadTrustAnchorCertificates = function()
{
  var anchors = this.config.getRoot().get("validator/trust-anchor");

  for (var i = 0; i < anchors.length; ++i) {
    var anchor = anchors[i];

    var typeName = anchor.get("type")[0].getValue();
    var isPath = false;
    var certID;
    if (typeName == 'file') {
      certID = anchor.get("file-name")[0].getValue();
      isPath = true;
    }
    else if (typeName == 'base64') {
      certID = anchor.get("base64-string")[0].getValue();
      isPath = false;
    }
    else if (typeName == "dir") {
      var dirName = anchor.get("dir")[0].getValue();

      var refreshPeriod = 0;
      var refreshTrees = anchor.get("refresh");
      if (refreshTrees.length >= 1) {
        var refreshPeriodStr = refreshTrees[0].getValue();

        var refreshMatch = refreshPeriodStr.match(/(\d+)([hms])/);
        if (refreshMatch == null)
          refreshPeriod = 0;
        else {
          refreshPeriod = parseInt(refreshMatch[1]);
          if (refreshMatch[2] != 's') {
            refreshPeriod *= 60;
            if (refreshMatch[2] != 'm')
              refreshPeriod *= 60;
          }
        }
      }

      // Convert refreshPeriod from seconds to milliseconds.
      this.refreshManager.addDirectory(dirName, refreshPeriod * 1000);
      continue;
    }
    else if (typeName == "any") {
      // This disables all security!
      this.requiresVerification = false;
      break;
    }

    this.lookupCertificate(certID, isPath);
  }
};

/**
 * Once a rule is found to match data or a signed interest, the name in the
 * KeyLocator must satisfy the condition in the 'checker' section of the rule,
 * else the data or interest is rejected.
 * @param {Name} signatureName The certificate name from the KeyLocator.
 * @param {Name} objectName The name of the data packet or interest. In the case
 * of signed interests, this excludes the timestamp, nonce and signature
 * components.
 * @param {BoostInfoTree} rule The rule from the configuration file that matches
 * the data or interest.
 * @param {Array<string>} failureReason If matching fails, set failureReason[0]
 * to the failure reason.
 * @return {boolean} True if matches.
 */
ConfigPolicyManager.prototype.checkSignatureMatch = function
  (signatureName, objectName, rule, failureReason)
{
  var checker = rule.get("checker")[0];
  var checkerType = checker.get("type")[0].getValue();
  if (checkerType == "fixed-signer") {
    var signerInfo = checker.get("signer")[0];
    var signerType = signerInfo.get("type")[0].getValue();

    var cert;
    if (signerType == "file") {
      cert = this.lookupCertificate
        (signerInfo.get("file-name")[0].getValue(), true);
      if (cert == null) {
        failureReason[0] = "Can't find fixed-signer certificate file: " +
          signerInfo.get("file-name")[0].getValue();
        return false;
      }
    }
    else if (signerType == "base64") {
      cert = this.lookupCertificate
        (signerInfo.get("base64-string")[0].getValue(), false);
      if (cert == null) {
        failureReason[0] = "Can't find fixed-signer certificate base64: " +
          signerInfo.get("base64-string")[0].getValue();
        return false;
      }
    }
    else {
      failureReason[0] = "Unrecognized fixed-signer signerType: " + signerType;
      return false;
    }

    if (cert.getName().equals(signatureName))
      return true;
    else {
      failureReason[0] = "fixed-signer cert name \"" + cert.getName().toUri() +
        "\" does not equal signatureName \"" + signatureName.toUri() + "\"";
      return false;
    }
  }
  else if (checkerType == "hierarchical") {
    // This just means the data/interest name has the signing identity as a prefix.
    // That means everything before "ksk-?" in the key name.
    var identityRegex = "^([^<KEY>]*)<KEY>(<>*)<ksk-.+><ID-CERT>";
    var identityMatch = NdnRegexMatcher.match(identityRegex, signatureName);
    if (identityMatch != null) {
      var identityPrefix = new Name(identityMatch[1]).append
        (new Name(identityMatch[2]));
      if (ConfigPolicyManager.matchesRelation
          (objectName, identityPrefix, "is-prefix-of"))
        return true;
      else {
        failureReason[0] = "The hierarchical objectName \"" + objectName.toUri() +
          "\" is not a prefix of \"" + identityPrefix.toUri() + "\"";
        return false;
      }
    }
    else {
      failureReason[0] = "The hierarchical identityRegex \"" + identityRegex +
        "\" does not match signatureName \"" + signatureName.toUri() + "\"";
      return false;
    }
  }
  else if (checkerType == "customized") {
    var keyLocatorInfo = checker.get("key-locator")[0];
    // Not checking type - only name is supported.

    // Is this a simple relation?
    var relationType = keyLocatorInfo.getFirstValue("relation");
    if (relationType != null) {
      var matchName = new Name(keyLocatorInfo.get("name")[0].getValue());
      if (ConfigPolicyManager.matchesRelation
          (signatureName, matchName, relationType))
        return true;
      else {
        failureReason[0] = "The custom signatureName \"" + signatureName.toUri() +
          "\" does not match matchName \"" + matchName.toUri() +
          "\" using relation " + relationType;
        return false;
      }
    }

    // Is this a simple regex?
    var keyRegex = keyLocatorInfo.getFirstValue("regex");
    if (keyRegex != null) {
      if (NdnRegexMatcher.match(keyRegex, signatureName) != null)
        return true;
      else {
        failureReason[0] = "The custom signatureName \"" + signatureName.toUri() +
          "\" does not regex match simpleKeyRegex \"" + keyRegex + "\"";
        return false;
      }
    }

    // Is this a hyper-relation?
    var hyperRelationList = keyLocatorInfo.get("hyper-relation");
    if (hyperRelationList.length >= 1) {
      var hyperRelation = hyperRelationList[0];

      var keyRegex = hyperRelation.getFirstValue("k-regex");
      var keyExpansion = hyperRelation.getFirstValue("k-expand");
      var nameRegex = hyperRelation.getFirstValue("p-regex");
      var nameExpansion = hyperRelation.getFirstValue("p-expand");
      var relationType = hyperRelation.getFirstValue("h-relation");
      if (keyRegex != null && keyExpansion != null && nameRegex != null &&
          nameExpansion != null && relationType != null) {
        var keyMatch = NdnRegexMatcher.match(keyRegex, signatureName);
        if (keyMatch == null || keyMatch[1] === undefined) {
          failureReason[0] = "The custom hyper-relation signatureName \"" +
            signatureName.toUri() + "\" does not match the keyRegex \"" +
            keyRegex + "\"";
          return false;
        }
        var keyMatchPrefix = ConfigPolicyManager.expand(keyMatch, keyExpansion);

        var nameMatch = NdnRegexMatcher.match(nameRegex, objectName);
        if (nameMatch == null || nameMatch[1] === undefined) {
          failureReason[0] = "The custom hyper-relation objectName \"" +
            objectName.toUri() + "\" does not match the nameRegex \"" +
            nameRegex + "\"";
          return false;
        }
        var nameMatchStr = ConfigPolicyManager.expand(nameMatch, nameExpansion);

        if (ConfigPolicyManager.matchesRelation
            (new Name(nameMatchStr), new Name(keyMatchPrefix), relationType))
          return true;
        else {
          failureReason[0] = "The custom hyper-relation nameMatch \"" +
            nameMatchStr + "\" does not match the keyMatchPrefix \"" +
            keyMatchPrefix + "\" using relation " + relationType;
          return false;
        }
      }
    }
  }

  failureReason[0] = "Unrecognized checkerType: " + checkerType;
  return false;
};

/**
 * Similar to Python expand, return expansion where every \1, \2, etc. is
 * replaced by match[1], match[2], etc.  Note: Even though this is a general
 * utility function, we define it locally because it is only tested to work in
 * the cases used by this class.
 * @param {Object} match The match object from String.match.
 * @param {string} expansion The string with \1, \2, etc. to replace from match.
 * @return {string} The expanded string.
 */
ConfigPolicyManager.expand = function(match, expansion)
{
  return expansion.replace
    (/\\(\d)/g,
     function(fullMatch, n) { return match[parseInt(n)];})
};

/**
 * This looks up certificates specified as base64-encoded data or file names.
 * These are cached by filename or encoding to avoid repeated reading of files
 * or decoding.
 * @param {string} certID
 * @param {boolean} isPath
 * @return {IdentityCertificate} The certificate object, or null if not found.
 */
ConfigPolicyManager.prototype.lookupCertificate = function(certID, isPath)
{
  var cert;

  var cachedCertUri = this.fixedCertificateCache[certID];
  if (cachedCertUri === undefined) {
    if (isPath)
      // load the certificate data (base64 encoded IdentityCertificate)
      cert = ConfigPolicyManager.TrustAnchorRefreshManager.loadIdentityCertificateFromFile
        (certID);
    else {
      var certData = new Buffer(certID, 'base64');
      cert = new IdentityCertificate();
      cert.wireDecode(certData);
    }

    var certUri = cert.getName().getPrefix(-1).toUri();
    this.fixedCertificateCache[certID] = certUri;
    this.certificateCache.insertCertificate(cert);
  }
  else
    cert = this.certificateCache.getCertificate(new Name(cachedCertUri));

  return cert;
};

/**
 * Search the configuration file for the first rule that matches the data or
 * signed interest name. In the case of interests, the name to match should
 * exclude the timestamp, nonce, and signature components.
 * @param {Name} objName The name to be matched.
 * @param {string} matchType The rule type to match, "data" or "interest".
 * @return {BoostInfoTree} The matching rule, or null if not found.
 */
ConfigPolicyManager.prototype.findMatchingRule = function(objName, matchType)
{
  var rules = this.config.getRoot().get("validator/rule");
  for (var iRule = 0; iRule < rules.length; ++iRule) {
    var r = rules[iRule];

    if (r.get('for')[0].getValue() == matchType) {
      var passed = true;
      var filters = r.get('filter');
      if (filters.length == 0)
        // No filters means we pass!
        return r;
      else {
        for (var iFilter = 0; iFilter < filters.length; ++iFilter) {
          var f = filters[iFilter];

          // Don't check the type - it can only be name for now.
          // We need to see if this is a regex or a relation.
          var regexPattern = f.getFirstValue("regex");
          if (regexPattern === null) {
            var matchRelation = f.get('relation')[0].getValue();
            var matchUri = f.get('name')[0].getValue();
            var matchName = new Name(matchUri);
            passed = ConfigPolicyManager.matchesRelation(objName, matchName, matchRelation);
          }
          else
            passed = (NdnRegexMatcher.match(regexPattern, objName) !== null);

          if (!passed)
            break;
        }

        if (passed)
          return r;
      }
    }
  }

  return null;
};

/**
 * Determines if a name satisfies the relation to matchName.
 * @param {Name} name
 * @param {Name} matchName
 * @param {string} matchRelation Can be one of:
 *   'is-prefix-of' - passes if the name is equal to or has the other
 *      name as a prefix
 *   'is-strict-prefix-of' - passes if the name has the other name as a
 *      prefix, and is not equal
 *   'equal' - passes if the two names are equal
 * @return {boolean}
 */
ConfigPolicyManager.matchesRelation = function(name, matchName, matchRelation)
{
  var passed = false;
  if (matchRelation == 'is-strict-prefix-of') {
    if (matchName.size() == name.size())
      passed = false;
    else if (matchName.match(name))
      passed = true;
  }
  else if (matchRelation == 'is-prefix-of') {
    if (matchName.match(name))
      passed = true;
  }
  else if (matchRelation == 'equal') {
    if (matchName.equals(name))
      passed = true;
  }
  return passed;
};

/**
 * Extract the signature information from the interest name or from the data
 * packet or interest.
 * @param {Data|Interest} dataOrInterest The object whose signature is needed.
 * @param {WireFormat} wireFormat (optional) The wire format used to decode
 * signature information from the interest name.
 * @return {Signature} The object of a sublcass of Signature or null if can't
 * decode.
 */
ConfigPolicyManager.extractSignature = function(dataOrInterest, wireFormat)
{
  if (dataOrInterest instanceof Data)
    return dataOrInterest.getSignature();
  else if (dataOrInterest instanceof Interest) {
    wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
    try {
      var signature = wireFormat.decodeSignatureInfoAndValue
        (dataOrInterest.getName().get(-2).getValue().buf(),
         dataOrInterest.getName().get(-1).getValue().buf(), false);
    }
    catch (e) {
      return null;
    }

    return signature;
  }

  return null;
};

/**
 * Determine whether the timestamp from the interest is newer than the last use
 * of this key, or within the grace interval on first use.
 * @param {Name} keyName The name of the public key used to sign the interest.
 * @param {number} timestamp The timestamp extracted from the interest name.
 * @param {Array<string>} failureReason If matching fails, set failureReason[0]
 * to the failure reason.
 * @return {boolean} True if timestamp is fresh as described above.
 */
ConfigPolicyManager.prototype.interestTimestampIsFresh = function
  (keyName, timestamp, failureReason)
{
  var lastTimestamp = this.keyTimestamps[keyName.toUri()];
  if (lastTimestamp == undefined) {
    var now = new Date().getTime();
    var notBefore = now - this.keyGraceInterval;
    var notAfter = now + this.keyGraceInterval;
    if (!(timestamp > notBefore && timestamp < notAfter)) {
      failureReason[0] =
        "The command interest timestamp is not within the first use grace period of " +
        this.keyGraceInterval + " milliseconds.";
      return false;
    }
    else
      return true;
  }
  else {
    if (timestamp <= lastTimestamp) {
      failureReason[0] =
        "The command interest timestamp is not newer than the previous timestamp";
      return false;
    }
    else
      return true;
  }
};

/**
 * Trim the table size down if necessary, and insert/update the latest interest
 * signing timestamp for the key. Any key which has not been used within the TTL
 * period is purged. If the table is still too large, the oldest key is purged.
 * @param {Name} keyName The name of the public key used to sign the interest.
 * @param {number} timestamp The timestamp extracted from the interest name.
 */
ConfigPolicyManager.prototype.updateTimestampForKey = function
  (keyName, timestamp)
{
  this.keyTimestamps[keyName.toUri()] = timestamp;

  // JavaScript does have a direct way to get the number of entries, so first
  //   get the keysToErase while counting.
  var keyTimestampsSize = 0;
  var keysToErase = [];

  var now = new Date().getTime();
  var oldestTimestamp = now;
  var oldestKey = null;
  for (var keyUri in this.keyTimestamps) {
    ++keyTimestampsSize;
    var ts = this.keyTimestamps[keyUri];
    if (now - ts > this.keyTimestampTtl)
      keysToErase.push(keyUri);
    else if (ts < oldestTimestamp) {
      oldestTimestamp = ts;
      oldestKey = keyUri;
    }
  }

  if (keyTimestampsSize >= this.maxTrackedKeys) {
    // Now delete the expired keys.
    for (var i = 0; i < keysToErase.length; ++i) {
      delete this.keyTimestamps[keysToErase[i]];
      --keyTimestampsSize;
    }

    if (keyTimestampsSize > this.maxTrackedKeys)
      // We have not removed enough.
      delete this.keyTimestamps[oldestKey];
  }
};

/**
 * Check the type of signatureInfo to get the KeyLocator. Look in the
 * IdentityStorage for the public key with the name in the KeyLocator and use it
 * to verify the signedBlob. If the public key can't be found, return false.
 * (This is a generalized method which can verify both a data packet and an
 * interest.)
 * @param {Signature} signatureInfo An object of a subclass of Signature, e.g.
 * Sha256WithRsaSignature.
 * @param {SignedBlob} signedBlob The SignedBlob with the signed portion to
 * verify.
 * @param {function} onComplete This calls onComplete(true, undefined) if the
 * signature verifies, otherwise onComplete(false, reason).
 */
ConfigPolicyManager.prototype.verify = function
  (signatureInfo, signedBlob, onComplete)
{
  // We have already checked once that there is a key locator.
  var keyLocator = KeyLocator.getFromSignature(signatureInfo);

  if (keyLocator.getType() == KeyLocatorType.KEYNAME) {
    // Assume the key name is a certificate name.
    var signatureName = keyLocator.getKeyName();
    var certificate = this.refreshManager.getCertificate(signatureName);
    if (certificate == null)
      certificate = this.certificateCache.getCertificate(signatureName);
    if (certificate == null) {
      onComplete(false,  "Cannot find a certificate with name " +
        signatureName.toUri());
      return;
    }

    var publicKeyDer = certificate.getPublicKeyInfo().getKeyDer();
    if (publicKeyDer.isNull()) {
      // Can't find the public key with the name.
      onComplete(false, "There is no public key in the certificate with name " +
        certificate.getName().toUri());
      return;
    }

    PolicyManager.verifySignature
      (signatureInfo, signedBlob, publicKeyDer, function(verified) {
        if (verified)
          onComplete(true);
        else
          onComplete
            (false,
             "The signature did not verify with the given public key");
      });
  }
  else
    onComplete(false, "The KeyLocator does not have a key name");
};

ConfigPolicyManager.TrustAnchorRefreshManager =
  function ConfigPolicyManagerTrustAnchorRefreshManager()
{
  this.certificateCache = new CertificateCache();
  // Maps the directory name to certificate names so they can be deleted when
  // necessary. The key is the directory name string. The value is the object
  //  {certificateNames,  // array of string
  //   nextRefresh,       // number
  //   refreshPeriod      // number
  //  }.
  this.refreshDirectories = {};
};

ConfigPolicyManager.TrustAnchorRefreshManager.loadIdentityCertificateFromFile =
  function(fileName)
{
  var encodedData = fs.readFileSync(fileName).toString();
  var decodedData = new Buffer(encodedData, 'base64');
  var cert = new IdentityCertificate();
  cert.wireDecode(new Blob(decodedData, false));
  return cert;
};

ConfigPolicyManager.TrustAnchorRefreshManager.prototype.getCertificate = function
  (certificateName)
{
  // This assumes the timestamp is already removed.
  return this.certificateCache.getCertificate(certificateName);
};

// refreshPeriod in milliseconds.
ConfigPolicyManager.TrustAnchorRefreshManager.prototype.addDirectory = function
  (directoryName, refreshPeriod)
{
  var allFiles;
  try {
    allFiles = fs.readdirSync(directoryName);
  }
  catch (e) {
    throw new SecurityException(new Error
      ("Cannot list files in directory " + directoryName));
  }

  var certificateNames = [];
  for (var i = 0; i < allFiles.length; ++i) {
    var cert;
    try {
      var fullPath = path.join(directoryName, allFiles[i]);
      cert = ConfigPolicyManager.TrustAnchorRefreshManager.loadIdentityCertificateFromFile
        (fullPath);
    }
    catch (e) {
      // Allow files that are not certificates.
      continue;
    }

    // Cut off the timestamp so it matches the KeyLocator Name format.
    var certUri = cert.getName().getPrefix(-1).toUri();
    this.certificateCache.insertCertificate(cert);
    certificateNames.push(certUri);
  }

  this.refreshDirectories[directoryName] = {
    certificates: certificateNames,
    nextRefresh: new Date().getTime() + refreshPeriod,
    refreshPeriod: refreshPeriod };
};

ConfigPolicyManager.TrustAnchorRefreshManager.prototype.refreshAnchors = function()
{
  var refreshTime =  new Date().getTime();
  for (var directory in this.refreshDirectories) {
    var info = this.refreshDirectories[directory];
    var nextRefreshTime = info.nextRefresh;
    if (nextRefreshTime <= refreshTime) {
      var certificateList = info.certificates.slice(0);
      // Delete the certificates associated with this directory if possible
      //   then re-import.
      // IdentityStorage subclasses may not support deletion.
      for (var c in certificateList)
        this.certificateCache.deleteCertificate(new Name(c));

      this.addDirectory(directory, info.refreshPeriod);
    }
  }
};
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
 *
 * 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.
 */

/** @ignore */
var Name = require('../../name.js').Name; /** @ignore */
var PolicyManager = require('./policy-manager.js').PolicyManager; /** @ignore */
var NdnCommon = require('../../util/ndn-common.js').NdnCommon;

/**
 * @constructor
 */
var NoVerifyPolicyManager = function NoVerifyPolicyManager()
{
  // Call the base constructor.
  PolicyManager.call(this);
};

NoVerifyPolicyManager.prototype = new PolicyManager();
NoVerifyPolicyManager.prototype.name = "NoVerifyPolicyManager";

exports.NoVerifyPolicyManager = NoVerifyPolicyManager;

/**
 * Override to always skip verification and trust as valid.
 *
 * @param {Data|Interest} dataOrInterest The received data packet or interest.
 * @return {boolean} True.
 */
NoVerifyPolicyManager.prototype.skipVerifyAndTrust = function(dataOrInterest)
{
  return true;
};

/**
 * Override to return false for no verification rule for the received data or
 * signed interest.
 *
 * @param {Data|Interest} dataOrInterest The received data packet or interest.
 * @return {boolean} False.
 */
NoVerifyPolicyManager.prototype.requireVerify = function(dataOrInterest)
{
  return false;
};

/**
 * Override to call onVerified(data) and to indicate no further verification
 * step.
 *
 * @param {Data|Interest} dataOrInterest The Data object or interest with the
 * signature to check.
 * @param {number} stepCount The number of verification steps that have been
 * done, used to track the verification progress.
 * @param {function} onVerified This does override to call
 * onVerified(dataOrInterest).
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onValidationFailed Override to ignore this.
 * @param {WireFormat} wireFormat
 * @return {ValidationRequest} null for no further step for looking up a
 * certificate chain.
 */
NoVerifyPolicyManager.prototype.checkVerificationPolicy = function
  (dataOrInterest, stepCount, onVerified, onValidationFailed, wireFormat)
{
  try {
    onVerified(dataOrInterest);
  } catch (ex) {
    console.log("Error in onVerified: " + NdnCommon.getErrorWithStackTrace(ex));
  }
  return null;
};

/**
 * Override to always indicate that the signing certificate name and data name
 * satisfy the signing policy.
 *
 * @param {Name} dataName The name of data to be signed.
 * @param {Name} certificateName The name of signing certificate.
 * @return {boolean} True to indicate that the signing certificate can be used
 * to sign the data.
 */
NoVerifyPolicyManager.prototype.checkSigningPolicy = function
  (dataName, certificateName)
{
  return true;
};

/**
 * Override to indicate that the signing identity cannot be inferred.
 *
 * @param {Name} dataName The name of data to be signed.
 * @return {Name} An empty name because cannot infer.
 */
NoVerifyPolicyManager.prototype.inferSigningIdentity = function(dataName)
{
  return new Name();
};
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
 *
 * 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.
 */

/** @ignore */
var Name = require('../../name.js').Name; /** @ignore */
var Interest = require('../../interest.js').Interest; /** @ignore */
var Data = require('../../data.js').Data; /** @ignore */
var Blob = require('../../util/blob.js').Blob; /** @ignore */
var IdentityCertificate = require('../certificate/identity-certificate.js').IdentityCertificate; /** @ignore */
var KeyLocator = require('../../key-locator.js').KeyLocator; /** @ignore */
var KeyLocatorType = require('../../key-locator.js').KeyLocatorType; /** @ignore */
var SecurityException = require('../security-exception.js').SecurityException; /** @ignore */
var WireFormat = require('../../encoding/wire-format.js').WireFormat; /** @ignore */
var SyncPromise = require('../../util/sync-promise.js').SyncPromise; /** @ignore */
var PolicyManager = require('./policy-manager.js').PolicyManager; /** @ignore */
var NdnCommon = require('../../util/ndn-common.js').NdnCommon;

/**
 * A SelfVerifyPolicyManager implements a PolicyManager to look in the
 * IdentityStorage for the public key with the name in the KeyLocator (if
 * available) and use it to verify the data packet, without searching a
 * certificate chain.  If the public key can't be found, the verification fails.
 *
 * @param {IdentityStorage} identityStorage (optional) The IdentityStorage for
 * looking up the public key. This object must remain valid during the life of
 * this SelfVerifyPolicyManager. If omitted, then don't look for a public key
 * with the name in the KeyLocator and rely on the KeyLocator having the full
 * public key DER.
 * @constructor
 */
var SelfVerifyPolicyManager = function SelfVerifyPolicyManager(identityStorage)
{
  // Call the base constructor.
  PolicyManager.call(this);

  this.identityStorage = identityStorage;
};

SelfVerifyPolicyManager.prototype = new PolicyManager();
SelfVerifyPolicyManager.prototype.name = "SelfVerifyPolicyManager";

exports.SelfVerifyPolicyManager = SelfVerifyPolicyManager;

/**
 * Never skip verification.
 *
 * @param {Data|Interest} dataOrInterest The received data packet or interest.
 * @return {boolean} False.
 */
SelfVerifyPolicyManager.prototype.skipVerifyAndTrust = function(dataOrInterest)
{
  return false;
};

/**
 * Always return true to use the self-verification rule for the received data.
 *
 * @param {Data|Interest} dataOrInterest The received data packet or interest.
 * @return {boolean} True.
 */
SelfVerifyPolicyManager.prototype.requireVerify = function(dataOrInterest)
{
  return true;
};

/**
 * Look in the IdentityStorage for the public key with the name in the
 * KeyLocator (if available) and use it to verify the data packet.  If the
 * public key can't be found, call onValidationFailed.
 *
 * @param {Data|Interest} dataOrInterest The Data object or interest with the
 * signature to check.
 * @param {number} stepCount The number of verification steps that have been
 * done, used to track the verification progress.
 * @param {function} onVerified If the signature is verified, this calls
 * onVerified(dataOrInterest).
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onValidationFailed If the signature check fails, this calls
 * onValidationFailed(dataOrInterest, reason).
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {WireFormat} wireFormat
 * @return {ValidationRequest} null for no further step for looking up a
 * certificate chain.
 */
SelfVerifyPolicyManager.prototype.checkVerificationPolicy = function
  (dataOrInterest, stepCount, onVerified, onValidationFailed, wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());

  if (dataOrInterest instanceof Data) {
    var data = dataOrInterest;
    // wireEncode returns the cached encoding if available.
    this.verify(data.getSignature(), data.wireEncode(), function(verified, reason) {
      if (verified) {
        try {
          onVerified(data);
        } catch (ex) {
          console.log("Error in onVerified: " + NdnCommon.getErrorWithStackTrace(ex));
        }
      }
      else {
        try {
          onValidationFailed(data, reason);
        } catch (ex) {
          console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
        }
      }
    });
  }
  else if (dataOrInterest instanceof Interest) {
    var interest = dataOrInterest;

    if (interest.getName().size() < 2) {
      try {
        onValidationFailed
          (interest, "The signed interest has less than 2 components: " +
             interest.getName().toUri());
      } catch (ex) {
        console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
      }
      return;
    }

    // Decode the last two name components of the signed interest
    var signature;
    try {
      signature = wireFormat.decodeSignatureInfoAndValue
        (interest.getName().get(-2).getValue().buf(),
         interest.getName().get(-1).getValue().buf(), false);
    } catch (ex) {
      try {
        onValidationFailed
          (interest, "Error decoding the signed interest signature: " + ex);
      } catch (ex) {
        console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
      }
      return;
    }

    // wireEncode returns the cached encoding if available.
    this.verify(signature, interest.wireEncode(), function(verified, reason) {
      if (verified) {
        try {
          onVerified(interest);
        } catch (ex) {
          console.log("Error in onVerified: " + NdnCommon.getErrorWithStackTrace(ex));
        }
      }
      else {
        try {
          onValidationFailed(interest, reason);
        } catch (ex) {
          console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
        }
      }
    });
  }
  else
    throw new SecurityException(new Error
      ("checkVerificationPolicy: unrecognized type for dataOrInterest"));

  // No more steps, so return null.
  return null;
};

/**
 * Override to always indicate that the signing certificate name and data name
 * satisfy the signing policy.
 *
 * @param {Name} dataName The name of data to be signed.
 * @param {Name} certificateName The name of signing certificate.
 * @return {boolean} True to indicate that the signing certificate can be used
 * to sign the data.
 */
SelfVerifyPolicyManager.prototype.checkSigningPolicy = function
  (dataName, certificateName)
{
  return true;
};

/**
 * Override to indicate that the signing identity cannot be inferred.
 *
 * @param {Name} dataName The name of data to be signed.
 * @return {Name} An empty name because cannot infer.
 */
SelfVerifyPolicyManager.prototype.inferSigningIdentity = function(dataName)
{
  return new Name();
};

/**
 * Check the type of signatureInfo to get the KeyLocator. Look in the
 * IdentityStorage for the public key with the name in the KeyLocator (if
 * available) and use it to verify the signedBlob. If the public key can't be
 * found, return false. (This is a generalized method which can verify both a
 * Data packet and an interest.)
 * @param {Signature} signatureInfo An object of a subclass of Signature, e.g.
 * Sha256WithRsaSignature.
 * @param {SignedBlob} signedBlob the SignedBlob with the signed portion to
 * verify.
 * @param {function} onComplete This calls onComplete(true, undefined) if the
 * signature verifies, otherwise onComplete(false, reason).
 */
SelfVerifyPolicyManager.prototype.verify = function
  (signatureInfo, signedBlob, onComplete)
{
  if (KeyLocator.canGetFromSignature(signatureInfo)) {
    this.getPublicKeyDer
      (KeyLocator.getFromSignature(signatureInfo), function(publicKeyDer, reason) {
        if (publicKeyDer.isNull())
          onComplete(false, reason);
        else {
          try {
            PolicyManager.verifySignature
              (signatureInfo, signedBlob, publicKeyDer, function(verified) {
                if (verified)
                  onComplete(true);
                else
                  onComplete
                    (false,
                     "The signature did not verify with the given public key");
              });
          } catch (ex) {
            onComplete(false, "Error in verifySignature: " + ex);
          }
        }
      });
  }
  else {
    try {
      // Assume that the signature type does not require a public key.
      PolicyManager.verifySignature
        (signatureInfo, signedBlob, null, function(verified) {
          if (verified)
            onComplete(true);
          else
            onComplete
              (false, "The signature did not verify with the given public key");
        });
    } catch (ex) {
      onComplete(false, "Error in verifySignature: " + ex);
    }
  }
};

/**
 * Look in the IdentityStorage for the public key with the name in the
 * KeyLocator (if available). If the public key can't be found, return and empty
 * Blob.
 * @param {KeyLocator} keyLocator The KeyLocator.
 * @param {function} onComplete This calls 
 * onComplete(publicKeyDer, reason) where publicKeyDer is the public key
 * DER Blob or an isNull Blob if not found and reason is the reason
 * string if not found.
 */
SelfVerifyPolicyManager.prototype.getPublicKeyDer = function
  (keyLocator, onComplete)
{
  if (keyLocator.getType() == KeyLocatorType.KEYNAME &&
      this.identityStorage != null) {
    var keyName;
    try {
      // Assume the key name is a certificate name.
      keyName = IdentityCertificate.certificateNameToPublicKeyName
        (keyLocator.getKeyName());
    } catch (ex) {
      onComplete
        (new Blob(), "Cannot get a public key name from the certificate named: " +
           keyLocator.getKeyName().toUri());
      return;
    }
    SyncPromise.complete
      (onComplete,
       function(err) {
         // The storage doesn't have the key.
         onComplete
           (new Blob(), "The identityStorage doesn't have the key named " +
              keyName.toUri());
       },
       this.identityStorage.getKeyPromise(keyName));
  }
  else
    // Can't find a key to verify.
    onComplete(new Blob(), "The signature KeyLocator doesn't have a key name");
};
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * From ndn-cxx security by Yingdi Yu <yingdi@cs.ucla.edu>.
 *
 * 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.
 */

/** @ignore */
var Crypto = require('../crypto.js'); /** @ignore */
var Name = require('../name.js').Name; /** @ignore */
var Interest = require('../interest.js').Interest; /** @ignore */
var Data = require('../data.js').Data; /** @ignore */
var Blob = require('../util/blob.js').Blob; /** @ignore */
var WireFormat = require('../encoding/wire-format.js').WireFormat; /** @ignore */
var SecurityException = require('./security-exception.js').SecurityException; /** @ignore */
var RsaKeyParams = require('./key-params.js').RsaKeyParams; /** @ignore */
var IdentityCertificate = require('./certificate/identity-certificate.js').IdentityCertificate; /** @ignore */
var SyncPromise = require('../util/sync-promise.js').SyncPromise; /** @ignore */
var NdnCommon = require('../util/ndn-common.js').NdnCommon; /** @ignore */
var IdentityManager = require('./identity/identity-manager.js').IdentityManager; /** @ignore */
var NoVerifyPolicyManager = require('./policy/no-verify-policy-manager.js').NoVerifyPolicyManager;

/**
 * A KeyChain provides a set of interfaces to the security library such as
 * identity management, policy configuration and packet signing and verification.
 * Note: This class is an experimental feature. See the API docs for more detail at
 * http://named-data.net/doc/ndn-ccl-api/key-chain.html .
 *
 * Create a new KeyChain with the identityManager and policyManager.
 * @param {IdentityManager} identityManager (optional) The identity manager as a
 * subclass of IdentityManager. If omitted, use the default IdentityManager
 * constructor.
 * @param {PolicyManager} policyManager (optional) The policy manager as a
 * subclass of PolicyManager. If omitted, use NoVerifyPolicyManager.
 * @throws SecurityException if this is not in Node.js and this uses the default
 * IdentityManager constructor. (See IdentityManager for details.)
 * @constructor
 */
var KeyChain = function KeyChain(identityManager, policyManager)
{
  if (!identityManager)
    identityManager = new IdentityManager();
  if (!policyManager)
    policyManager = new NoVerifyPolicyManager();

  this.identityManager = identityManager;
  this.policyManager = policyManager;
  this.face = null;
};

exports.KeyChain = KeyChain;

/*****************************************
 *          Identity Management          *
 *****************************************/

/**
 * Create an identity by creating a pair of Key-Signing-Key (KSK) for this
 * identity and a self-signed certificate of the KSK. If a key pair or
 * certificate for the identity already exists, use it.
 * @param {Name} identityName The name of the identity.
 * @param {KeyParams} params (optional) The key parameters if a key needs to be
 * generated for the identity. If omitted, use KeyChain.DEFAULT_KEY_PARAMS.
 * @param {function} onComplete (optional) This calls onComplete(certificateName)
 * with name of the default certificate of the identity. If omitted, the return
 * value is described below. (Some crypto libraries only use a callback, so
 * onComplete is required to use these.)
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onError (optional) If defined, then onComplete must be
 * defined and if there is an exception, then this calls onError(exception)
 * with the exception. If onComplete is defined but onError is undefined, then
 * this will log any thrown exception. (Some database libraries only use a
 * callback, so onError is required to be notified of an exception.)
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @return {Name} If onComplete is omitted, return the name of the default
 * certificate of the identity. Otherwise, if onComplete is supplied then return
 * undefined and use onComplete as described above.
 */
KeyChain.prototype.createIdentityAndCertificate = function
  (identityName, params, onComplete, onError)
{
  onError = (typeof params === "function") ? onComplete : onError;
  onComplete = (typeof params === "function") ? params : onComplete;
  params = (typeof params === "function" || !params) ?
    KeyChain.DEFAULT_KEY_PARAMS : params;

  return this.identityManager.createIdentityAndCertificate
    (identityName, params, onComplete, onError);
};

/**
 * Create an identity by creating a pair of Key-Signing-Key (KSK) for this
 * identity and a self-signed certificate of the KSK. If a key pair or
 * certificate for the identity already exists, use it.
 * @deprecated Use createIdentityAndCertificate which returns the
 * certificate name instead of the key name. You can use
 * IdentityCertificate.certificateNameToPublicKeyName to convert the
 * certificate name to the key name.
 * @param {Name} identityName The name of the identity.
 * @param {KeyParams} params (optional) The key parameters if a key needs to be
 * generated for the identity. If omitted, use KeyChain.DEFAULT_KEY_PARAMS.
 * @return {Name} The key name of the auto-generated KSK of the identity.
 */
KeyChain.prototype.createIdentity = function(identityName, params)
{
  return IdentityCertificate.certificateNameToPublicKeyName
    (this.createIdentityAndCertificate(identityName, params));
};

/**
 * Delete the identity from the public and private key storage. If the
 * identity to be deleted is the current default system default, this will not
 * delete the identity and will return immediately.
 * @param {Name} identityName The name of the identity.
 * @param {function} onComplete (optional) This calls onComplete() when the
 * operation is complete. If omitted, do not use it. (Some database libraries
 * only use a callback, so onComplete is required to use these.)
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onError (optional) If defined, then onComplete must be
 * defined and if there is an exception, then this calls onError(exception)
 * with the exception. If onComplete is defined but onError is undefined, then
 * this will log any thrown exception. (Some database libraries only use a
 * callback, so onError is required to be notified of an exception.)
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 */
KeyChain.prototype.deleteIdentity = function
  (identityName, onComplete, onError)
{
  this.identityManager.deleteIdentity(identityName, onComplete, onError);
};

/**
 * Get the default identity.
 * @param {function} onComplete (optional) This calls onComplete(identityName)
 * with name of the default identity. If omitted, the return value is described
 * below. (Some crypto libraries only use a callback, so onComplete is required
 * to use these.)
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onError (optional) If defined, then onComplete must be
 * defined and if there is an exception, then this calls onError(exception)
 * with the exception. If onComplete is defined but onError is undefined, then
 * this will log any thrown exception. (Some database libraries only use a
 * callback, so onError is required to be notified of an exception.)
 * @return {Name} If onComplete is omitted, return the name of the default
 * identity. Otherwise, if onComplete is supplied then return undefined and use
 * onComplete as described above.
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @throws SecurityException if the default identity is not set. However, if
 * onComplete and onError are defined, then if there is an exception return
 * undefined and call onError(exception).
 */
KeyChain.prototype.getDefaultIdentity = function(onComplete, onError)
{
  return this.identityManager.getDefaultIdentity(onComplete, onError);
};

/**
 * Get the default certificate name of the default identity, which will be used
 * when signing is based on identity and the identity is not specified.
 * @param {function} onComplete (optional) This calls onComplete(certificateName)
 * with name of the default certificate. If omitted, the return value is described
 * below. (Some crypto libraries only use a callback, so onComplete is required
 * to use these.)
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onError (optional) If defined, then onComplete must be
 * defined and if there is an exception, then this calls onError(exception)
 * with the exception. If onComplete is defined but onError is undefined, then
 * this will log any thrown exception. (Some database libraries only use a
 * callback, so onError is required to be notified of an exception.)
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @return {Name} If onComplete is omitted, return the default certificate name.
 * Otherwise, if onComplete is supplied then return undefined and use onComplete
 * as described above.
 * @throws SecurityException if the default identity is not set or the default
 * key name for the identity is not set or the default certificate name for
 * the key name is not set. However, if onComplete and onError are defined, then
 * if there is an exception return undefined and call onError(exception).
 */
KeyChain.prototype.getDefaultCertificateName = function(onComplete, onError)
{
  return this.identityManager.getDefaultCertificateName(onComplete, onError);
};

/**
 * Generate a pair of RSA keys for the specified identity.
 * @param {Name} identityName The name of the identity.
 * @param {boolean} isKsk (optional) true for generating a Key-Signing-Key (KSK),
 * false for a Data-Signing-Key (DSK). If omitted, generate a Data-Signing-Key.
 * @param {number} keySize (optional) The size of the key. If omitted, use a
 * default secure key size.
 * @return {Name} The generated key name.
 */
KeyChain.prototype.generateRSAKeyPair = function(identityName, isKsk, keySize)
{
  keySize = (typeof isKsk === "boolean") ? isKsk : keySize;
  isKsk = (typeof isKsk === "boolean") ? isKsk : false;

  if (!keySize)
    keySize = 2048;

  return this.identityManager.generateRSAKeyPair(identityName, isKsk, keySize);
};

/**
 * Set a key as the default key of an identity. The identity name is inferred
 * from keyName.
 * @param {Name} keyName The name of the key.
 * @param {Name} identityNameCheck (optional) The identity name to check that the
 * keyName contains the same identity name. If an empty name, it is ignored.
 * @param {function} onComplete (optional) This calls onComplete() when complete.
 * (Some database libraries only use a callback, so onComplete is required to
 * use these.)
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onError (optional) If defined, then onComplete must be
 * defined and if there is an exception, then this calls onError(exception)
 * with the exception. If onComplete is defined but onError is undefined, then
 * this will log any thrown exception. (Some database libraries only use a
 * callback, so onError is required to be notified of an exception.)
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 */
KeyChain.prototype.setDefaultKeyForIdentity = function
  (keyName, identityNameCheck, onComplete, onError)
{
  return this.identityManager.setDefaultKeyForIdentity
    (keyName, identityNameCheck, onComplete, onError);
};

/**
 * Generate a pair of RSA keys for the specified identity and set it as default
 * key for the identity.
 * @param {Name} identityName The name of the identity.
 * @param {boolean} isKsk (optional) true for generating a Key-Signing-Key (KSK),
 * false for a Data-Signing-Key (DSK). If omitted, generate a Data-Signing-Key.
 * @param {number} keySize (optional) The size of the key. If omitted, use a
 * default secure key size.
 * @return {Name} The generated key name.
 */
KeyChain.prototype.generateRSAKeyPairAsDefault = function
  (identityName, isKsk, keySize)
{
  return this.identityManager.generateRSAKeyPairAsDefault
    (identityName, isKsk, keySize);
};

/**
 * Create a public key signing request.
 * @param {Name} keyName The name of the key.
 * @return {Blob} The signing request data.
 */
KeyChain.prototype.createSigningRequest = function(keyName)
{
  return this.identityManager.getPublicKey(keyName).getKeyDer();
};

/**
 * Install an identity certificate into the public key identity storage.
 * @param {IdentityCertificate} certificate The certificate to to added.
 * @param {function} onComplete (optional) This calls onComplete() when complete.
 * (Some database libraries only use a callback, so onComplete is required to
 * use these.)
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onError (optional) If defined, then onComplete must be
 * defined and if there is an exception, then this calls onError(exception)
 * with the exception. If onComplete is defined but onError is undefined, then
 * this will log any thrown exception. (Some database libraries only use a
 * callback, so onError is required to be notified of an exception.)
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 */
KeyChain.prototype.installIdentityCertificate = function
  (certificate, onComplete, onError)
{
  this.identityManager.addCertificate(certificate, onComplete, onError);
};

/**
 * Set the certificate as the default for its corresponding key.
 * @param {IdentityCertificate} certificate The certificate.
 * @param {function} onComplete (optional) This calls onComplete() when complete.
 * (Some database libraries only use a callback, so onComplete is required to
 * use these.)
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onError (optional) If defined, then onComplete must be
 * defined and if there is an exception, then this calls onError(exception)
 * with the exception. If onComplete is defined but onError is undefined, then
 * this will log any thrown exception. (Some database libraries only use a
 * callback, so onError is required to be notified of an exception.)
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 */
KeyChain.prototype.setDefaultCertificateForKey = function
  (certificate, onComplete, onError)
{
  this.identityManager.setDefaultCertificateForKey
    (certificate, onComplete, onError);
};

/**
 * Get a certificate which is still valid with the specified name.
 * @param {Name} certificateName The name of the requested certificate.
 * @param {function} onComplete (optional) This calls onComplete(certificate)
 * with the requested IdentityCertificate. If omitted, the return value is 
 * described below. (Some crypto libraries only use a callback, so onComplete is
 * required to use these.)
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onError (optional) If defined, then onComplete must be
 * defined and if there is an exception, then this calls onError(exception)
 * with the exception. If onComplete is defined but onError is undefined, then
 * this will log any thrown exception. (Some database libraries only use a
 * callback, so onError is required to be notified of an exception.)
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @return {IdentityCertificate} If onComplete is omitted, return the requested
 * certificate. Otherwise, if onComplete is supplied then return undefined and
 * use onComplete as described above.
 */
KeyChain.prototype.getCertificate = function
  (certificateName, onComplete, onError)
{
  return this.identityManager.getCertificate
    (certificateName, onComplete, onError);
};

/**
 * @deprecated Use getCertificate.
 */
KeyChain.prototype.getIdentityCertificate = function
  (certificateName, onComplete, onError)
{
  return this.identityManager.getCertificate
    (certificateName, onComplete, onError);
};

/**
 * Revoke a key.
 * @param {Name} keyName The name of the key that will be revoked.
 */
KeyChain.prototype.revokeKey = function(keyName)
{
  //TODO: Implement
};

/**
 * Revoke a certificate.
 * @param {Name} certificateName The name of the certificate that will be
 * revoked.
 */
KeyChain.prototype.revokeCertificate = function(certificateName)
{
  //TODO: Implement
};

/**
 * Get the identity manager given to or created by the constructor.
 * @return {IdentityManager} The identity manager.
 */
KeyChain.prototype.getIdentityManager = function()
{
  return this.identityManager;
};

/*****************************************
 *           Policy Management           *
 *****************************************/

/**
 * Get the policy manager given to or created by the constructor.
 * @return {PolicyManager} The policy manager.
 */
KeyChain.prototype.getPolicyManager = function()
{
  return this.policyManager;
};

/*****************************************
 *              Sign/Verify              *
 *****************************************/

/**
 * Sign the target. If it is a Data or Interest object, set its signature. If it
 * is an array, produce a Signature object. There are two forms of sign:
 * sign(target, certificateName [, wireFormat] [, onComplete] [, onError]).
 * sign(target [, wireFormat] [, onComplete] [, onError]).
 * @param {Data|Interest|Buffer} target If this is a Data object, wire encode for
 * signing, update its signature and key locator field and wireEncoding. If this
 * is an Interest object, wire encode for signing, append a SignatureInfo to the
 * Interest name, sign the name components and append a final name component
 * with the signature bits. If it is an array, sign it and produce a Signature
 * object.
 * @param {Name} certificateName (optional) The certificate name of the key to
 * use for signing. If omitted, use the default identity in the identity storage.
 * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
 * the input. If omitted, use WireFormat getDefaultWireFormat().
 * @param {function} onComplete (optional) If target is a Data object, this calls
 * onComplete(data) with the supplied Data object which has been modified to set
 * its signature. If target is an Interest object, this calls
 * onComplete(interest) with the supplied Interest object which has been
 * modified to set its signature. If target is a Buffer, this calls
 * onComplete(signature) where signature is the produced Signature object. If
 * omitted, the return value is described below. (Some crypto libraries only use
 * a callback, so onComplete is required to use these.)
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onError (optional) If defined, then onComplete must be
 * defined and if there is an exception, then this calls onError(exception)
 * with the exception. If onComplete is defined but onError is undefined, then
 * this will log any thrown exception. (Some database libraries only use a
 * callback, so onError is required to be notified of an exception.)
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @return {Signature} If onComplete is omitted, return the generated Signature
 * object (if target is a Buffer) or the target (if target is Data or Interest).
 * Otherwise, if onComplete is supplied then return undefined and use onComplete as
 * described above.
 */
KeyChain.prototype.sign = function
  (target, certificateName, wireFormat, onComplete, onError)
{
  var arg2 = certificateName;
  var arg3 = wireFormat;
  var arg4 = onComplete;
  var arg5 = onError;
  // arg2,            arg3,       arg4,       arg5
  // certificateName, wireFormat, onComplete, onError
  // certificateName, wireFormat, null,       null
  // certificateName, onComplete, onError,    null
  // certificateName, null,       null,       null
  // wireFormat,      onComplete, onError,    null
  // wireFormat,      null,       null,       null
  // onComplete,      onError,    null,       null
  // null,            null,       null,       null
  if (arg2 instanceof Name)
    certificateName = arg2;
  else
    certificateName = null;

  if (arg2 instanceof WireFormat)
    wireFormat = arg2;
  else if (arg3 instanceof WireFormat)
    wireFormat = arg3;
  else
    wireFormat = null;

  if (typeof arg2 === "function") {
    onComplete = arg2;
    onError = arg3;
  }
  else if (typeof arg3 === "function") {
    onComplete = arg3;
    onError = arg4;
  }
  else if (typeof arg4 === "function") {
    onComplete = arg4;
    onError = arg5;
  }
  else {
    onComplete = null;
    onError = null;
  }

  return SyncPromise.complete(onComplete, onError,
    this.signPromise(target, certificateName, wireFormat, !onComplete));
};

/**
 * Sign the target. If it is a Data or Interest object, set its signature. If it
 * is an array, produce a Signature object. There are two forms of signPromise:
 * signPromise(target, certificateName [, wireFormat] [, useSync]).
 * sign(target [, wireFormat] [, useSync]).
 * @param {Data|Interest|Buffer} target If this is a Data object, wire encode for
 * signing, update its signature and key locator field and wireEncoding. If this
 * is an Interest object, wire encode for signing, append a SignatureInfo to the
 * Interest name, sign the name components and append a final name component
 * with the signature bits. If it is an array, sign it and produce a Signature
 * object.
 * @param {Name} certificateName (optional) The certificate name of the key to
 * use for signing. If omitted, use the default identity in the identity storage.
 * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
 * the input. If omitted, use WireFormat getDefaultWireFormat().
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that returns the generated Signature
 * object (if target is a Buffer) or the target (if target is Data or Interest).
 */
KeyChain.prototype.signPromise = function
  (target, certificateName, wireFormat, useSync)
{
  var arg2 = certificateName;
  var arg3 = wireFormat;
  var arg4 = useSync;
  // arg2,            arg3,       arg4
  // certificateName, wireFormat, useSync
  // certificateName, wireFormat, null
  // certificateName, useSync,    null
  // certificateName, null,       null
  // wireFormat,      useSync,    null
  // wireFormat,      null,       null
  // useSync,         null,       null
  // null,            null,       null
  if (arg2 instanceof Name)
    certificateName = arg2;
  else
    certificateName = null;

  if (arg2 instanceof WireFormat)
    wireFormat = arg2;
  else if (arg3 instanceof WireFormat)
    wireFormat = arg3;
  else
    wireFormat = null;

  if (typeof arg2 === 'boolean')
    useSync = arg2;
  else if (typeof arg3 === 'boolean')
    useSync = arg3;
  else if (typeof arg4 === 'boolean')
    useSync = arg4;
  else
    useSync = false;

  var thisKeyChain = this;
  return SyncPromise.resolve()
  .then(function() {
    if (certificateName != null)
      return SyncPromise.resolve();

    // Get the default certificate name.
    return thisKeyChain.identityManager.getDefaultCertificatePromise(useSync)
    .then(function(signingCertificate) {
      if (signingCertificate != null) {
        certificateName = signingCertificate.getName();
        return SyncPromise.resolve();
      }

      // Set the default certificate and default certificate name again.
      return thisKeyChain.prepareDefaultCertificateNamePromise_(useSync)
      .then(function(localCertificateName) {
        certificateName =localCertificateName;
        return SyncPromise.resolve();
      });
    });
  })
  .then(function() {
    // certificateName is now set. Do the actual signing.
    if (target instanceof Interest)
      return thisKeyChain.identityManager.signInterestByCertificatePromise
        (target, certificateName, wireFormat, useSync);
    else if (target instanceof Data)
      return thisKeyChain.identityManager.signByCertificatePromise
        (target, certificateName, wireFormat, useSync);
    else
      return thisKeyChain.identityManager.signByCertificatePromise
        (target, certificateName, useSync);
  });
};

/**
 * Sign the target. If it is a Data object, set its signature. If it is an
 * array, produce a signature object.
 * @param {Data|Buffer} target If this is a Data object, wire encode for
 * signing, update its signature and key locator field and wireEncoding. If it
 * is an array, sign it and return a Signature object.
 * @param {Name} identityName (optional) The identity name for the key to use for
 * signing.  If omitted, infer the signing identity from the data packet name.
 * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
 * the input. If omitted, use WireFormat getDefaultWireFormat().
 * @param {function} onComplete (optional) If target is a Data object, this calls
 * onComplete(data) with the supplied Data object which has been modified to set
 * its signature. If target is a Buffer, this calls
 * onComplete(signature) where signature is the produced Signature object. If
 * omitted, the return value is described below. (Some crypto libraries only use
 * a callback, so onComplete is required to use these.)
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onError (optional) If defined, then onComplete must be
 * defined and if there is an exception, then this calls onError(exception)
 * with the exception. If onComplete is defined but onError is undefined, then
 * this will log any thrown exception. (Some database libraries only use a
 * callback, so onError is required to be notified of an exception.)
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @return {Signature} If onComplete is omitted, return the generated Signature
 * object (if target is a Buffer) or undefined (if target is Data).
 * Otherwise, if onComplete is supplied then return undefined and use onComplete
 * as described above.
 */
KeyChain.prototype.signByIdentity = function
  (target, identityName, wireFormat, onComplete, onError)
{
  onError = (typeof wireFormat === "function") ? onComplete : onError;
  onComplete = (typeof wireFormat === "function") ? wireFormat : onComplete;
  wireFormat = (typeof wireFormat === "function" || !wireFormat) ? WireFormat.getDefaultWireFormat() : wireFormat;

  var useSync = !onComplete;
  var thisKeyChain = this;

  if (identityName == null)
    identityName = new Name();

  if (target instanceof Data) {
    var data = target;

    var mainPromise = SyncPromise.resolve()
    .then(function() {
      if (identityName.size() == 0) {
        var inferredIdentity = thisKeyChain.policyManager.inferSigningIdentity
          (data.getName());
        if (inferredIdentity.size() == 0)
          return thisKeyChain.identityManager.getDefaultCertificateNamePromise
            (useSync);
        else
          return thisKeyChain.identityManager.getDefaultCertificateNameForIdentityPromise
              (inferredIdentity, useSync);
      }
      else
        return thisKeyChain.identityManager.getDefaultCertificateNameForIdentityPromise
          (identityName, useSync);
    })
    .then(function(signingCertificateName) {
      if (signingCertificateName.size() == 0)
        throw new SecurityException(new Error
          ("No qualified certificate name found!"));

      if (!thisKeyChain.policyManager.checkSigningPolicy
           (data.getName(), signingCertificateName))
        throw new SecurityException(new Error
          ("Signing Cert name does not comply with signing policy"));

      return thisKeyChain.identityManager.signByCertificatePromise
        (data, signingCertificateName, wireFormat, useSync);
    });

    return SyncPromise.complete(onComplete, onError, mainPromise);
  }
  else {
    var array = target;

    return SyncPromise.complete(onComplete, onError,
      this.identityManager.getDefaultCertificateNameForIdentityPromise
        (identityName, useSync)
      .then(function(signingCertificateName) {
        if (signingCertificateName.size() == 0)
          throw new SecurityException(new Error
            ("No qualified certificate name found!"));

        return thisKeyChain.identityManager.signByCertificatePromise
          (array, signingCertificateName, wireFormat, useSync);
      }));
  }
};

/**
 * Sign the target using DigestSha256.
 * @param {Data|Interest} target If this is a Data object, wire encode for
 * signing, digest it and set its SignatureInfo to a DigestSha256, updating its
 * signature and wireEncoding. If this is an Interest object, wire encode for
 * signing, append a SignatureInfo for DigestSha256 to the Interest name, digest
 * the name components and append a final name component with the signature bits.
 * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
 * the input. If omitted, use WireFormat getDefaultWireFormat().
 */
KeyChain.prototype.signWithSha256 = function(target, wireFormat)
{
  if (target instanceof Interest)
    this.identityManager.signInterestWithSha256(target, wireFormat);
  else
    this.identityManager.signWithSha256(target, wireFormat);
};

/**
 * Check the signature on the Data object and call either onVerify or
 * onValidationFailed. We use callback functions because verify may fetch
 * information to check the signature.
 * @param {Data} data The Data object with the signature to check.
 * @param {function} onVerified If the signature is verified, this calls
 * onVerified(data).
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onValidationFailed If the signature check fails, this calls
 * onValidationFailed(data, reason) with the Data object and reason string.
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {number} stepCount
 */
KeyChain.prototype.verifyData = function
  (data, onVerified, onValidationFailed, stepCount)
{
  if (stepCount == null)
    stepCount = 0;

  if (this.policyManager.requireVerify(data)) {
    var nextStep = this.policyManager.checkVerificationPolicy
      (data, stepCount, onVerified, onValidationFailed);
    if (nextStep != null) {
      var thisKeyChain = this;
      this.face.expressInterest
        (nextStep.interest,
         function(callbackInterest, callbackData) {
           thisKeyChain.onCertificateData(callbackInterest, callbackData, nextStep);
         },
         function(callbackInterest) {
           thisKeyChain.onCertificateInterestTimeout
             (callbackInterest, nextStep.retry, onValidationFailed, data, nextStep);
         });
    }
  }
  else if (this.policyManager.skipVerifyAndTrust(data)) {
    try {
      onVerified(data);
    } catch (ex) {
      console.log("Error in onVerified: " + NdnCommon.getErrorWithStackTrace(ex));
    }
  }
  else {
    try {
      onValidationFailed
        (data, "The packet has no verify rule but skipVerifyAndTrust is false");
    } catch (ex) {
      console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
    }
  }
};

/**
 * Check the signature on the signed interest and call either onVerify or
 * onValidationFailed. We use callback functions because verify may fetch
 * information to check the signature.
 * @param {Interest} interest The interest with the signature to check.
 * @param {function} onVerified If the signature is verified, this calls
 * onVerified(interest).
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onValidationFailed If the signature check fails, this calls
 * onValidationFailed(interest, reason) with the Interest object and reason
 * string.
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 */
KeyChain.prototype.verifyInterest = function
  (interest, onVerified, onValidationFailed, stepCount, wireFormat)
{
  if (stepCount == null)
    stepCount = 0;
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());

  if (this.policyManager.requireVerify(interest)) {
    var nextStep = this.policyManager.checkVerificationPolicy
      (interest, stepCount, onVerified, onValidationFailed, wireFormat);
    if (nextStep != null) {
      var thisKeyChain = this;
      this.face.expressInterest
        (nextStep.interest,
         function(callbackInterest, callbackData) {
           thisKeyChain.onCertificateData(callbackInterest, callbackData, nextStep);
         },
         function(callbackInterest) {
           thisKeyChain.onCertificateInterestTimeout
             (callbackInterest, nextStep.retry, onValidationFailed, interest,
              nextStep);
         });
    }
  }
  else if (this.policyManager.skipVerifyAndTrust(interest)) {
    try {
      onVerified(interest);
    } catch (ex) {
      console.log("Error in onVerified: " + NdnCommon.getErrorWithStackTrace(ex));
    }
  }
  else {
    try {
      onValidationFailed
        (interest,
         "The packet has no verify rule but skipVerifyAndTrust is false");
    } catch (ex) {
      console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
    }
  }
};

/**
 * Set the Face which will be used to fetch required certificates.
 * @param {Face} face A pointer to the Face object.
 */
KeyChain.prototype.setFace = function(face)
{
  this.face = face;
};

/**
 * Wire encode the target, compute an HmacWithSha256 and update the signature
 * value.
 * Note: This method is an experimental feature. The API may change.
 * @param {Data} target If this is a Data object, update its signature and wire
 * encoding.
 * @param {Blob} key The key for the HmacWithSha256.
 * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
 * the target. If omitted, use WireFormat getDefaultWireFormat().
 */
KeyChain.signWithHmacWithSha256 = function(target, key, wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());

  if (target instanceof Data) {
    var data = target;
    // Encode once to get the signed portion.
    var encoding = data.wireEncode(wireFormat);

    var signer = Crypto.createHmac('sha256', key.buf());
    signer.update(encoding.signedBuf());
    data.getSignature().setSignature(
      new Blob(signer.digest(), false));
  }
  else
    throw new SecurityException(new Error
      ("signWithHmacWithSha256: Unrecognized target type"));
};

/**
 * Compute a new HmacWithSha256 for the target and verify it against the
 * signature value.
 * Note: This method is an experimental feature. The API may change.
 * @param {Data} target The Data object to verify.
 * @param {Blob} key The key for the HmacWithSha256.
 * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
 * the target. If omitted, use WireFormat getDefaultWireFormat().
 * @return {boolean} True if the signature verifies, otherwise false.
 */
KeyChain.verifyDataWithHmacWithSha256 = function(data, key, wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());

  // wireEncode returns the cached encoding if available.
  var encoding = data.wireEncode(wireFormat);

  var signer = Crypto.createHmac('sha256', key.buf());
  signer.update(encoding.signedBuf());
  var newSignatureBits = new Blob(signer.digest(), false);

  // Use the flexible Blob.equals operator.
  return newSignatureBits.equals(data.getSignature().getSignature());
};

KeyChain.DEFAULT_KEY_PARAMS = new RsaKeyParams();

KeyChain.prototype.onCertificateData = function(interest, data, nextStep)
{
  // Try to verify the certificate (data) according to the parameters in nextStep.
  this.verifyData
    (data, nextStep.onVerified, nextStep.onValidationFailed, nextStep.stepCount);
};

KeyChain.prototype.onCertificateInterestTimeout = function
  (interest, retry, onValidationFailed, originalDataOrInterest, nextStep)
{
  if (retry > 0) {
    // Issue the same expressInterest as in verifyData except decrement retry.
    var thisKeyChain = this;
    this.face.expressInterest
      (interest,
       function(callbackInterest, callbackData) {
         thisKeyChain.onCertificateData(callbackInterest, callbackData, nextStep);
       },
       function(callbackInterest) {
         thisKeyChain.onCertificateInterestTimeout
           (callbackInterest, retry - 1, onValidationFailed,
            originalDataOrInterest, nextStep);
       });
  }
  else {
    try {
      onValidationFailed
        (originalDataOrInterest, "The retry count is zero after timeout for fetching " +
          interest.getName().toUri());
    } catch (ex) {
      console.log("Error in onValidationFailed: " + NdnCommon.getErrorWithStackTrace(ex));
    }
  }
};

/**
 * Get the default certificate from the identity storage and return its name.
 * If there is no default identity or default certificate, then create one.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that returns the default certificate
 * name.
 */
KeyChain.prototype.prepareDefaultCertificateNamePromise_ = function(useSync)
{
  var signingCertificate;
  var thisKeyChain = this;
  return this.identityManager.getDefaultCertificatePromise(useSync)
  .then(function(localCertificate) {
    signingCertificate = localCertificate;
    if (signingCertificate != null)
      return SyncPromise.resolve();

    // Set the default certificate and get the certificate again.
    return thisKeyChain.setDefaultCertificatePromise_(useSync)
    .then(function() {
      return thisKeyChain.identityManager.getDefaultCertificatePromise(useSync);
    })
    .then(function(localCertificate) {
      signingCertificate = localCertificate;
      return SyncPromise.resolve();
    });
  })
  .then(function() {
    return SyncPromise.resolve(signingCertificate.getName());
  });
}

/**
 * Create the default certificate if it is not initialized. If there is no
 * default identity yet, creating a new tmp-identity.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that resolves when the default
 * certificate is set.
 */
KeyChain.prototype.setDefaultCertificatePromise_ = function(useSync)
{
  var thisKeyChain = this;

  return this.identityManager.getDefaultCertificatePromise(useSync)
  .then(function(certificate) {
    if (certificate != null)
      // We already have a default certificate.
      return SyncPromise.resolve();

    var defaultIdentity;
    return thisKeyChain.identityManager.getDefaultIdentityPromise(useSync)
    .then(function(localDefaultIdentity) {
      defaultIdentity = localDefaultIdentity;
      return SyncPromise.resolve();
    }, function(ex) {
      // Create a default identity name.
      randomComponent = Crypto.randomBytes(4);
      defaultIdentity = new Name().append("tmp-identity")
        .append(new Blob(randomComponent, false));

      return SyncPromise.resolve();
    })
    .then(function() {
      return thisKeyChain.identityManager.createIdentityAndCertificatePromise
        (defaultIdentity, KeyChain.DEFAULT_KEY_PARAMS, useSync);
    })
    .then(function() {
      return thisKeyChain.identityManager.setDefaultIdentityPromise
        (defaultIdentity, useSync);
    });
  });
};
/**
 * This class represents an Interest Exclude.
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Meki Cheraoui
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var Name = require('./name.js').Name; /** @ignore */
var DataUtils = require('./encoding/data-utils.js').DataUtils; /** @ignore */
var Blob = require('./util/blob.js').Blob;

/**
 * Create a new Exclude.
 * @constructor
 * @param {Array<Name.Component|Buffer|Exclude.ANY>} values (optional) An array where each element is either a Name.Component, Buffer component or Exclude.ANY.
 */
var Exclude = function Exclude(values)
{
  this.values = [];

  if (typeof values === 'object' && values instanceof Exclude)
    // Copy the exclude.
    this.values = values.values.slice(0);
  else if (values) {
    // Set the changeCount now since append expects it.
    this.changeCount = 0;
    for (var i = 0; i < values.length; ++i) {
      if (values[i] == Exclude.ANY)
        this.appendAny();
      else
        this.appendComponent(values[i]);
    }
  }

  this.changeCount = 0;
};

exports.Exclude = Exclude;

Exclude.ANY = "*";

/**
 * Get the number of entries.
 * @return {number} The number of entries.
 */
Exclude.prototype.size = function() { return this.values.length; };

/**
 * Get the entry at the given index.
 * @param {number} i The index of the entry, starting from 0.
 * @return {Exclude.ANY|Name.Component} Exclude.ANY or a Name.Component.
 */
Exclude.prototype.get = function(i) { return this.values[i]; };

/**
 * Append an Exclude.ANY element.
 * @return This Exclude so that you can chain calls to append.
 */
Exclude.prototype.appendAny = function()
{
  this.values.push(Exclude.ANY);
  ++this.changeCount;
  return this;
};

/**
 * Append a component entry, copying from component.
 * @param {Name.Component|Buffer} component
 * @return This Exclude so that you can chain calls to append.
 */
Exclude.prototype.appendComponent = function(component)
{
  this.values.push(new Name.Component(component));
  ++this.changeCount;
  return this;
};

/**
 * Clear all the entries.
 */
Exclude.prototype.clear = function()
{
  ++this.changeCount;
  this.values = [];
};

/**
 * Return a string with elements separated by "," and Exclude.ANY shown as "*".
 */
Exclude.prototype.toUri = function()
{
  if (this.values == null || this.values.length == 0)
    return "";

  var result = "";
  for (var i = 0; i < this.values.length; ++i) {
    if (i > 0)
      result += ",";

    if (this.values[i] == Exclude.ANY)
      result += "*";
    else
      result += this.values[i].toEscapedString();
  }
  return result;
};

/**
 * Return true if the component matches any of the exclude criteria.
 */
Exclude.prototype.matches = function(component)
{
  if (!(typeof component == 'object' && component instanceof Name.Component))
    component = new Name.Component(component);

  for (var i = 0; i < this.values.length; ++i) {
    if (this.values[i] == Exclude.ANY) {
      var lowerBound = null;
      if (i > 0)
        lowerBound = this.values[i - 1];

      // Find the upper bound, possibly skipping over multiple ANY in a row.
      var iUpperBound;
      var upperBound = null;
      for (iUpperBound = i + 1; iUpperBound < this.values.length; ++iUpperBound) {
        if (this.values[iUpperBound] != Exclude.ANY) {
          upperBound = this.values[iUpperBound];
          break;
        }
      }

      // If lowerBound != null, we already checked component equals lowerBound on the last pass.
      // If upperBound != null, we will check component equals upperBound on the next pass.
      if (upperBound != null) {
        if (lowerBound != null) {
          if (component.compare(lowerBound) > 0 &&
              component.compare(upperBound) < 0)
            return true;
        }
        else {
          if (component.compare(upperBound) < 0)
            return true;
        }

        // Make i equal iUpperBound on the next pass.
        i = iUpperBound - 1;
      }
      else {
        if (lowerBound != null) {
            if (component.compare(lowerBound) > 0)
              return true;
        }
        else
          // this.values has only ANY.
          return true;
      }
    }
    else {
      if (component.equals(this.values[i]))
        return true;
    }
  }

  return false;
};

/**
 * Return -1 if component1 is less than component2, 1 if greater or 0 if equal.
 * A component is less if it is shorter, otherwise if equal length do a byte comparison.
 */
Exclude.compareComponents = function(component1, component2)
{
  if (typeof component1 == 'object' && component1 instanceof Name.Component)
    component1 = component1.getValue().buf();
  if (typeof component2 == 'object' && component2 instanceof Name.Component)
    component2 = component2.getValue().buf();

  return Name.Component.compareBuffers(component1, component2);
};

/**
 * Get the change count, which is incremented each time this object is changed.
 * @return {number} The change count.
 */
Exclude.prototype.getChangeCount = function()
{
  return this.changeCount;
};
/**
 * This class represents Interest Objects
 * Copyright (C) 2013-2016 Regents of the University of California.
 * @author: Meki Cheraoui
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var Crypto = require('./crypto.js'); /** @ignore */
var Blob = require('./util/blob.js').Blob; /** @ignore */
var SignedBlob = require('./util/signed-blob.js').SignedBlob; /** @ignore */
var ChangeCounter = require('./util/change-counter.js').ChangeCounter; /** @ignore */
var Name = require('./name.js').Name; /** @ignore */
var Exclude = require('./exclude.js').Exclude; /** @ignore */
var Link = require('./link.js').Link; /** @ignore */
var KeyLocator = require('./key-locator.js').KeyLocator; /** @ignore */
var IncomingFaceId = require('./lp/incoming-face-id.js').IncomingFaceId; /** @ignore */
var WireFormat = require('./encoding/wire-format.js').WireFormat;

/**
 * Create a new Interest with the optional values.
 *
 * @constructor
 * @param {Name|Interest} nameOrInterest If this is an Interest, copy values from the interest and ignore the
 * other arguments.  Otherwise this is the optional name for the new Interest.
 * @param {number} minSuffixComponents
 * @param {number} maxSuffixComponents
 */
var Interest = function Interest
   (nameOrInterest, minSuffixComponents, maxSuffixComponents,
    publisherPublicKeyDigest, exclude, childSelector, answerOriginKind, scope,
    interestLifetimeMilliseconds, nonce)
{
  if (publisherPublicKeyDigest)
    throw new Error
      ("Interest constructor: PublisherPublicKeyDigest support has been removed.");
  if (answerOriginKind)
    throw new Error
      ("Interest constructor: answerOriginKind support has been removed. Use setMustBeFresh().");
  if (scope)
    throw new Error("Interest constructor: scope support has been removed.");

  if (typeof nameOrInterest === 'object' && nameOrInterest instanceof Interest) {
    // Special case: this is a copy constructor.  Ignore all but the first argument.
    var interest = nameOrInterest;
    // Copy the name.
    this.name_ = new ChangeCounter(new Name(interest.getName()));
    this.maxSuffixComponents_ = interest.maxSuffixComponents_;
    this.minSuffixComponents_ = interest.minSuffixComponents_;

    this.keyLocator_ = new ChangeCounter(new KeyLocator(interest.getKeyLocator()));
    this.exclude_ = new ChangeCounter(new Exclude(interest.getExclude()));
    this.childSelector_ = interest.childSelector_;
    this.mustBeFresh_ = interest.mustBeFresh_;
    this.interestLifetimeMilliseconds_ = interest.interestLifetimeMilliseconds_;
    this.nonce_ = interest.nonce_;
    this.linkWireEncoding_ = interest.linkWireEncoding_;
    this.linkWireEncodingFormat_ = interest.linkWireEncodingFormat_;
    this.link_ = new ChangeCounter(null);
    if (interest.link_.get() != null)
      this.link_.set(new Link(interest.link_.get()));
    this.selectedDelegationIndex_ = interest.selectedDelegationIndex_;
    this.defaultWireEncoding_ = interest.getDefaultWireEncoding();
    this.defaultWireEncodingFormat_ = interest.defaultWireEncodingFormat_;
  }
  else {
    this.name_ = new ChangeCounter(typeof nameOrInterest === 'object' &&
                                   nameOrInterest instanceof Name ?
      new Name(nameOrInterest) : new Name());
    this.maxSuffixComponents_ = maxSuffixComponents;
    this.minSuffixComponents_ = minSuffixComponents;

    this.keyLocator_ = new ChangeCounter(new KeyLocator());
    this.exclude_ = new ChangeCounter(typeof exclude === 'object' && exclude instanceof Exclude ?
      new Exclude(exclude) : new Exclude());
    this.childSelector_ = childSelector;
    this.mustBeFresh_ = true;
    this.interestLifetimeMilliseconds_ = interestLifetimeMilliseconds;
    this.nonce_ = typeof nonce === 'object' && nonce instanceof Blob ?
      nonce : new Blob(nonce, true);
    this.linkWireEncoding_ = new Blob();
    this.linkWireEncodingFormat_ = null;
    this.link_ = new ChangeCounter(null);
    this.selectedDelegationIndex_ = null;
    this.defaultWireEncoding_ = new SignedBlob();
    this.defaultWireEncodingFormat_ = null;
  }

  this.getNonceChangeCount_ = 0;
  this.getDefaultWireEncodingChangeCount_ = 0;
  this.changeCount_ = 0;
  this.lpPacket_ = null;
};

exports.Interest = Interest;

Interest.RECURSIVE_POSTFIX = "*";

Interest.CHILD_SELECTOR_LEFT = 0;
Interest.CHILD_SELECTOR_RIGHT = 1;

/**
 * Check if this interest's name matches the given name (using Name.match) and
 * the given name also conforms to the interest selectors.
 * @param {Name} name The name to check.
 * @return {boolean} True if the name and interest selectors match, False otherwise.
 */
Interest.prototype.matchesName = function(name)
{
  if (!this.getName().match(name))
    return false;

  if (this.minSuffixComponents_ != null &&
      // Add 1 for the implicit digest.
      !(name.size() + 1 - this.getName().size() >= this.minSuffixComponents_))
    return false;
  if (this.maxSuffixComponents_ != null &&
      // Add 1 for the implicit digest.
      !(name.size() + 1 - this.getName().size() <= this.maxSuffixComponents_))
    return false;
  if (this.getExclude() != null && name.size() > this.getName().size() &&
      this.getExclude().matches(name.get(this.getName().size())))
    return false;

  return true;
};

/**
 * @deprecated Use matchesName.
 */
Interest.prototype.matches_name = function(/*Name*/ name)
{
  return this.matchesName(name);
};

/**
 * Check if the given Data packet can satisfy this Interest. This method
 * considers the Name, MinSuffixComponents, MaxSuffixComponents,
 * PublisherPublicKeyLocator, and Exclude. It does not consider the
 * ChildSelector or MustBeFresh. This uses the given wireFormat to get the
 * Data packet encoding for the full Name.
 * @param {Data} data The Data packet to check.
 * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
 * the Data packet to get its full Name. If omitted, use
 * WireFormat.getDefaultWireFormat().
 * @return {boolean} True if the given Data packet can satisfy this Interest.
 */
Interest.prototype.matchesData = function(data, wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());

  // Imitate ndn-cxx Interest::matchesData.
  var interestNameLength = this.getName().size();
  var dataName = data.getName();
  var fullNameLength = dataName.size() + 1;

  // Check MinSuffixComponents.
  var hasMinSuffixComponents = (this.getMinSuffixComponents() != null);
  var minSuffixComponents =
    hasMinSuffixComponents ? this.getMinSuffixComponents() : 0;
  if (!(interestNameLength + minSuffixComponents <= fullNameLength))
    return false;

  // Check MaxSuffixComponents.
  var hasMaxSuffixComponents = (this.getMaxSuffixComponents() != null);
  if (hasMaxSuffixComponents &&
      !(interestNameLength + this.getMaxSuffixComponents() >= fullNameLength))
    return false;

  // Check the prefix.
  if (interestNameLength === fullNameLength) {
    if (this.getName().get(-1).isImplicitSha256Digest()) {
      if (!this.getName().equals(data.getFullName(wireFormat)))
        return false;
    }
    else
      // The Interest Name is the same length as the Data full Name, but the
      //   last component isn't a digest so there's no possibility of matching.
      return false;
  }
  else {
    // The Interest Name should be a strict prefix of the Data full Name.
    if (!this.getName().isPrefixOf(dataName))
      return false;
  }

  // Check the Exclude.
  // The Exclude won't be violated if the Interest Name is the same as the
  //   Data full Name.
  if (this.getExclude().size() > 0 && fullNameLength > interestNameLength) {
    if (interestNameLength == fullNameLength - 1) {
      // The component to exclude is the digest.
      if (this.getExclude().matches
          (data.getFullName(wireFormat).get(interestNameLength)))
        return false;
    }
    else {
      // The component to exclude is not the digest.
      if (this.getExclude().matches(dataName.get(interestNameLength)))
        return false;
    }
  }

  // Check the KeyLocator.
  var publisherPublicKeyLocator = this.getKeyLocator();
  if (publisherPublicKeyLocator.getType()) {
    var signature = data.getSignature();
    if (!KeyLocator.canGetFromSignature(signature))
      // No KeyLocator in the Data packet.
      return false;
    if (!publisherPublicKeyLocator.equals
        (KeyLocator.getFromSignature(signature)))
      return false;
  }

  return true;
};

/**
 * Return a new Interest with the same fields as this Interest.
 */
Interest.prototype.clone = function()
{
  return new Interest(this);
};

/**
 * Get the interest Name.
 * @return {Name} The name.  The name size() may be 0 if not specified.
 */
Interest.prototype.getName = function() { return this.name_.get(); };

/**
 * Get the min suffix components.
 * @return {number} The min suffix components, or null if not specified.
 */
Interest.prototype.getMinSuffixComponents = function()
{
  return this.minSuffixComponents_;
};

/**
 * Get the max suffix components.
 * @return {number} The max suffix components, or null if not specified.
 */
Interest.prototype.getMaxSuffixComponents = function()
{
  return this.maxSuffixComponents_;
};

/**
 * Get the interest key locator.
 * @return {KeyLocator} The key locator. If its getType() is null,
 * then the key locator is not specified.
 */
Interest.prototype.getKeyLocator = function()
{
  return this.keyLocator_.get();
};

/**
 * Get the exclude object.
 * @return {Exclude} The exclude object. If the exclude size() is zero, then
 * the exclude is not specified.
 */
Interest.prototype.getExclude = function() { return this.exclude_.get(); };

/**
 * Get the child selector.
 * @return {number} The child selector, or null if not specified.
 */
Interest.prototype.getChildSelector = function()
{
  return this.childSelector_;
};

/**
 * Get the must be fresh flag. If not specified, the default is true.
 * @return {boolean} The must be fresh flag.
 */
Interest.prototype.getMustBeFresh = function()
{
  return this.mustBeFresh_;
};

/**
 * Return the nonce value from the incoming interest.  If you change any of the
 * fields in this Interest object, then the nonce value is cleared.
 * @return {Blob} The nonce. If not specified, the value isNull().
 */
Interest.prototype.getNonce = function()
{
  if (this.getNonceChangeCount_ != this.getChangeCount()) {
    // The values have changed, so the existing nonce is invalidated.
    this.nonce_ = new Blob();
    this.getNonceChangeCount_ = this.getChangeCount();
  }

  return this.nonce_;
};

/**
 * @deprecated Use getNonce. This method returns a Buffer which is the former
 * behavior of getNonce, and should only be used while updating your code.
 */
Interest.prototype.getNonceAsBuffer = function()
{
  return this.getNonce().buf();
};

/**
 * Check if this interest has a link object (or a link wire encoding which
 * can be decoded to make the link object).
 * @return {boolean} True if this interest has a link object, false if not.
 */
Interest.prototype.hasLink = function()
{
  return this.link_.get() != null || !this.linkWireEncoding_.isNull();
};

/**
 * Get the link object. If necessary, decode it from the link wire encoding.
 * @return {Link} The link object, or null if not specified.
 * @throws DecodingException For error decoding the link wire encoding (if
 * necessary).
 */
Interest.prototype.getLink = function()
{
  if (this.link_.get() != null)
    return this.link_.get();
  else if (!this.linkWireEncoding_.isNull()) {
    // Decode the link object from linkWireEncoding_.
    var link = new Link();
    link.wireDecode(this.linkWireEncoding_, this.linkWireEncodingFormat_);
    this.link_.set(link);

    // Clear linkWireEncoding_ since it is now managed by the link object.
    this.linkWireEncoding_ = new Blob();
    this.linkWireEncodingFormat_ = null;

    return link;
  }
  else
    return null;
};

/**
 * Get the wire encoding of the link object. If there is already a wire
 * encoding then return it. Otherwise encode from the link object (if
 * available).
 * @param {WireFormat} wireFormat (optional) A WireFormat object  used to encode
 * the Link. If omitted, use WireFormat.getDefaultWireFormat().
 * @return {Blob} The wire encoding, or an isNull Blob if the link is not
 * specified.
 */
Interest.prototype.getLinkWireEncoding = function(wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());

  if (!this.linkWireEncoding_.isNull() && this.linkWireEncodingFormat_ == wireFormat)
    return this.linkWireEncoding_;

  var link = this.getLink();
  if (link != null)
    return link.wireEncode(wireFormat);
  else
    return new Blob();
};

/**
 * Get the selected delegation index.
 * @return {number} The selected delegation index. If not specified, return null.
 */
Interest.prototype.getSelectedDelegationIndex = function()
{
  return this.selectedDelegationIndex_;
};

/**
 * Get the interest lifetime.
 * @return {number} The interest lifetime in milliseconds, or null if not
 * specified.
 */
Interest.prototype.getInterestLifetimeMilliseconds = function()
{
  return this.interestLifetimeMilliseconds_;
};

/**
 * Return the default wire encoding, which was encoded with
 * getDefaultWireEncodingFormat().
 * @return {SignedBlob} The default wire encoding, whose isNull() may be true
 * if there is no default wire encoding.
 */
Interest.prototype.getDefaultWireEncoding = function()
{
  if (this.getDefaultWireEncodingChangeCount_ != this.getChangeCount()) {
    // The values have changed, so the default wire encoding is invalidated.
    this.defaultWireEncoding_ = new SignedBlob();
    this.defaultWireEncodingFormat_ = null;
    this.getDefaultWireEncodingChangeCount_ = this.getChangeCount();
  }

  return this.defaultWireEncoding_;
};

/**
 * Get the WireFormat which is used by getDefaultWireEncoding().
 * @return {WireFormat} The WireFormat, which is only meaningful if the
 * getDefaultWireEncoding() is not isNull().
 */
Interest.prototype.getDefaultWireEncodingFormat = function()
{
  return this.defaultWireEncodingFormat_;
};

/**
 * Get the incoming face ID according to the incoming packet header.
 * @return {number} The incoming face ID. If not specified, return null.
 */
Interest.prototype.getIncomingFaceId = function()
{
  var field =
    this.lpPacket_ === null ? null : IncomingFaceId.getFirstHeader(this.lpPacket_);
  return field === null ? null : field.getFaceId();
};

/**
 * Set the interest name.
 * Note: You can also call getName and change the name values directly.
 * @param {Name} name The interest name. This makes a copy of the name.
 * @return {Interest} This Interest so that you can chain calls to update values.
 */
Interest.prototype.setName = function(name)
{
  this.name_.set(typeof name === 'object' && name instanceof Name ?
    new Name(name) : new Name());
  ++this.changeCount_;
  return this;
};

/**
 * Set the min suffix components count.
 * @param {number} minSuffixComponents The min suffix components count. If not
 * specified, set to undefined.
 * @return {Interest} This Interest so that you can chain calls to update values.
 */
Interest.prototype.setMinSuffixComponents = function(minSuffixComponents)
{
  this.minSuffixComponents_ = minSuffixComponents;
  ++this.changeCount_;
  return this;
};

/**
 * Set the max suffix components count.
 * @param {number} maxSuffixComponents The max suffix components count. If not
 * specified, set to undefined.
 * @return {Interest} This Interest so that you can chain calls to update values.
 */
Interest.prototype.setMaxSuffixComponents = function(maxSuffixComponents)
{
  this.maxSuffixComponents_ = maxSuffixComponents;
  ++this.changeCount_;
  return this;
};

/**
 * Set this interest to use a copy of the given KeyLocator object.
 * Note: You can also call getKeyLocator and change the key locator directly.
 * @param {KeyLocator} keyLocator The KeyLocator object. This makes a copy of the object.
 * If no key locator is specified, set to a new default KeyLocator(), or to a
 * KeyLocator with an unspecified type.
 * @return {Interest} This Interest so that you can chain calls to update values.
 */
Interest.prototype.setKeyLocator = function(keyLocator)
{
  this.keyLocator_.set
    (typeof keyLocator === 'object' && keyLocator instanceof KeyLocator ?
     new KeyLocator(keyLocator) : new KeyLocator());
  ++this.changeCount_;
  return this;
};

/**
 * Set this interest to use a copy of the given exclude object. Note: You can
 * also call getExclude and change the exclude entries directly.
 * @param {Exclude} exclude The Exclude object. This makes a copy of the object.
 * If no exclude is specified, set to a new default Exclude(), or to an Exclude
 * with size() 0.
 * @return {Interest} This Interest so that you can chain calls to update values.
 */
Interest.prototype.setExclude = function(exclude)
{
  this.exclude_.set(typeof exclude === 'object' && exclude instanceof Exclude ?
    new Exclude(exclude) : new Exclude());
  ++this.changeCount_;
  return this;
};

/**
 * Set the link wire encoding bytes, without decoding them. If there is
 * a link object, set it to null. If you later call getLink(), it will
 * decode the wireEncoding to create the link object.
 * @param {Blob} encoding The Blob with the bytes of the link wire encoding.
 * If no link is specified, set to an empty Blob() or call unsetLink().
 * @param {WireFormat} wireFormat The wire format of the encoding, to be used
 * later if necessary to decode. If omitted, use WireFormat.getDefaultWireFormat().
 * @return {Interest} This Interest so that you can chain calls to update values.
 */
Interest.prototype.setLinkWireEncoding = function(encoding, wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());

  this.linkWireEncoding_ = encoding;
  this.linkWireEncodingFormat_ = wireFormat;

  // Clear the link object, assuming that it has a different encoding.
  this.link_.set(null);

  ++this.changeCount_;
  return this;
};

/**
 * Clear the link wire encoding and link object so that getLink() returns null.
 * @return {Interest} This Interest so that you can chain calls to update values.
 */
Interest.prototype.unsetLink = function()
{
  return this.setLinkWireEncoding(new Blob(), null);
};

/**
 * Set the selected delegation index.
 * @param {number} selectedDelegationIndex The selected delegation index. If not
 * specified, set to null.
 * @return {Interest} This Interest so that you can chain calls to update values.
 */
Interest.prototype.setSelectedDelegationIndex = function(selectedDelegationIndex)
{
  this.selectedDelegationIndex_ = selectedDelegationIndex;
  ++this.changeCount_;
  return this;
};

/**
 * Set the child selector.
 * @param {number} childSelector The child selector. If not specified, set to
 * undefined.
 * @return {Interest} This Interest so that you can chain calls to update values.
 */
Interest.prototype.setChildSelector = function(childSelector)
{
  this.childSelector_ = childSelector;
  ++this.changeCount_;
  return this;
};

/**
 * Set the MustBeFresh flag.
 * @param {boolean} mustBeFresh True if the content must be fresh, otherwise
 * false. If you do not set this flag, the default value is true.
 * @return {Interest} This Interest so that you can chain calls to update values.
 */
Interest.prototype.setMustBeFresh = function(mustBeFresh)
{
  this.mustBeFresh_ = (mustBeFresh ? true : false);
  ++this.changeCount_;
  return this;
};

/**
 * Set the interest lifetime.
 * @param {number} interestLifetimeMilliseconds The interest lifetime in
 * milliseconds. If not specified, set to undefined.
 * @return {Interest} This Interest so that you can chain calls to update values.
 */
Interest.prototype.setInterestLifetimeMilliseconds = function(interestLifetimeMilliseconds)
{
  this.interestLifetimeMilliseconds_ = interestLifetimeMilliseconds;
  ++this.changeCount_;
  return this;
};

/**
 * @deprecated You should let the wire encoder generate a random nonce
 * internally before sending the interest.
 */
Interest.prototype.setNonce = function(nonce)
{
  this.nonce_ = typeof nonce === 'object' && nonce instanceof Blob ?
    nonce : new Blob(nonce, true);
  // Set getNonceChangeCount_ so that the next call to getNonce() won't clear
  // this.nonce_.
  ++this.changeCount_;
  this.getNonceChangeCount_ = this.getChangeCount();
  return this;
};

/**
 * Encode the name according to the "NDN URI Scheme".  If there are interest selectors, append "?" and
 * added the selectors as a query string.  For example "/test/name?ndn.ChildSelector=1".
 * Note: This is an experimental feature.  See the API docs for more detail at
 * http://named-data.net/doc/ndn-ccl-api/interest.html#interest-touri-method .
 * @return {string} The URI string.
 */
Interest.prototype.toUri = function()
{
  var selectors = "";

  if (this.minSuffixComponents_ != null)
    selectors += "&ndn.MinSuffixComponents=" + this.minSuffixComponents_;
  if (this.maxSuffixComponents_ != null)
    selectors += "&ndn.MaxSuffixComponents=" + this.maxSuffixComponents_;
  if (this.childSelector_ != null)
    selectors += "&ndn.ChildSelector=" + this.childSelector_;
  selectors += "&ndn.MustBeFresh=" + (this.mustBeFresh_ ? 1 : 0);
  if (this.interestLifetimeMilliseconds_ != null)
    selectors += "&ndn.InterestLifetime=" + this.interestLifetimeMilliseconds_;
  if (this.getNonce().size() > 0)
    selectors += "&ndn.Nonce=" + Name.toEscapedString(this.getNonce().buf());
  if (this.getExclude() != null && this.getExclude().size() > 0)
    selectors += "&ndn.Exclude=" + this.getExclude().toUri();

  var result = this.getName().toUri();
  if (selectors != "")
    // Replace the first & with ?.
    result += "?" + selectors.substr(1);

  return result;
};

/**
 * Encode this Interest for a particular wire format. If wireFormat is the
 * default wire format, also set the defaultWireEncoding field to the encoded
 * result.
 * @param {WireFormat} wireFormat (optional) A WireFormat object  used to encode
 * this object. If omitted, use WireFormat.getDefaultWireFormat().
 * @return {SignedBlob} The encoded buffer in a SignedBlob object.
 */
Interest.prototype.wireEncode = function(wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());

  if (!this.getDefaultWireEncoding().isNull() &&
      this.getDefaultWireEncodingFormat() == wireFormat)
    // We already have an encoding in the desired format.
    return this.getDefaultWireEncoding();

  var result = wireFormat.encodeInterest(this);
  var wireEncoding = new SignedBlob
    (result.encoding, result.signedPortionBeginOffset,
     result.signedPortionEndOffset);

  if (wireFormat == WireFormat.getDefaultWireFormat())
    // This is the default wire encoding.
    this.setDefaultWireEncoding
      (wireEncoding, WireFormat.getDefaultWireFormat());
  return wireEncoding;
};

/**
 * Decode the input using a particular wire format and update this Interest. If
 * wireFormat is the default wire format, also set the defaultWireEncoding to
 * another pointer to the input.
 * @param {Blob|Buffer} input The buffer with the bytes to decode.
 * @param {WireFormat} wireFormat (optional) A WireFormat object used to decode
 * this object. If omitted, use WireFormat.getDefaultWireFormat().
 */
Interest.prototype.wireDecode = function(input, wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());

  var result;
  if (typeof input === 'object' && input instanceof Blob)
    // Input is a blob, so get its buf() and set copy false.
    result = wireFormat.decodeInterest(this, input.buf(), false);
  else
    result = wireFormat.decodeInterest(this, input, true);

  if (wireFormat == WireFormat.getDefaultWireFormat())
    // This is the default wire encoding.  In the Blob constructor, set copy
    // true, but if input is already a Blob, it won't copy.
    this.setDefaultWireEncoding(new SignedBlob
      (new Blob(input, true), result.signedPortionBeginOffset,
       result.signedPortionEndOffset),
      WireFormat.getDefaultWireFormat());
  else
    this.setDefaultWireEncoding(new SignedBlob(), null);
};

/**
 * Update the bytes of the nonce with new random values. This ensures that the
 * new nonce value is different than the current one. If the current nonce is
 * not specified, this does nothing.
 */
Interest.prototype.refreshNonce = function()
{
  var currentNonce = this.getNonce();
  if (currentNonce.size() === 0)
    return;

  var newNonce;
  while (true) {
    newNonce = new Blob(Crypto.randomBytes(currentNonce.size()), false);
    if (!newNonce.equals(currentNonce))
      break;
  }

  this.nonce_ = newNonce;
  // Set getNonceChangeCount_ so that the next call to getNonce() won't clear
  // this.nonce_.
  ++this.changeCount_;
  this.getNonceChangeCount_ = this.getChangeCount();
};

/**
 * An internal library method to set the LpPacket for an incoming packet. The
 * application should not call this.
 * @param {LpPacket} lpPacket The LpPacket. This does not make a copy.
 * @return {Interest} This Interest so that you can chain calls to update values.
 * @note This is an experimental feature. This API may change in the future.
 */
Interest.prototype.setLpPacket = function(lpPacket)
{
  this.lpPacket_ = lpPacket;
  // Don't update changeCount_ since this doesn't affect the wire encoding.
  return this;
}

/**
 * Get the change count, which is incremented each time this object (or a child
 * object) is changed.
 * @return {number} The change count.
 */
Interest.prototype.getChangeCount = function()
{
  // Make sure each of the checkChanged is called.
  var changed = this.name_.checkChanged();
  changed = this.keyLocator_.checkChanged() || changed;
  changed = this.exclude_.checkChanged() || changed;
  if (changed)
    // A child object has changed, so update the change count.
    ++this.changeCount_;

  return this.changeCount_;
};

Interest.prototype.setDefaultWireEncoding = function
  (defaultWireEncoding, defaultWireEncodingFormat)
{
  this.defaultWireEncoding_ = defaultWireEncoding;
  this.defaultWireEncodingFormat_ = defaultWireEncodingFormat;
  // Set getDefaultWireEncodingChangeCount_ so that the next call to
  // getDefaultWireEncoding() won't clear _defaultWireEncoding.
  this.getDefaultWireEncodingChangeCount_ = this.getChangeCount();
};

// Define properties so we can change member variable types and implement changeCount_.
Object.defineProperty(Interest.prototype, "name",
  { get: function() { return this.getName(); },
    set: function(val) { this.setName(val); } });
Object.defineProperty(Interest.prototype, "minSuffixComponents",
  { get: function() { return this.getMinSuffixComponents(); },
    set: function(val) { this.setMinSuffixComponents(val); } });
Object.defineProperty(Interest.prototype, "maxSuffixComponents",
  { get: function() { return this.getMaxSuffixComponents(); },
    set: function(val) { this.setMaxSuffixComponents(val); } });
Object.defineProperty(Interest.prototype, "keyLocator",
  { get: function() { return this.getKeyLocator(); },
    set: function(val) { this.setKeyLocator(val); } });
Object.defineProperty(Interest.prototype, "exclude",
  { get: function() { return this.getExclude(); },
    set: function(val) { this.setExclude(val); } });
Object.defineProperty(Interest.prototype, "childSelector",
  { get: function() { return this.getChildSelector(); },
    set: function(val) { this.setChildSelector(val); } });
/**
 * @deprecated Use getInterestLifetimeMilliseconds and setInterestLifetimeMilliseconds.
 */
Object.defineProperty(Interest.prototype, "interestLifetime",
  { get: function() { return this.getInterestLifetimeMilliseconds(); },
    set: function(val) { this.setInterestLifetimeMilliseconds(val); } });
/**
 * @deprecated Use getNonce and setNonce.
 */
Object.defineProperty(Interest.prototype, "nonce",
  { get: function() { return this.getNonceAsBuffer(); },
    set: function(val) { this.setNonce(val); } });
/**
 * Copyright (C) 2013-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/**
 * A ForwardingFlags object holds the flags which specify how the forwarding daemon should forward an interest for
 * a registered prefix.  We use a separate ForwardingFlags object to retain future compatibility if the daemon forwarding
 * bits are changed, amended or deprecated.
 * Create a new ForwardingFlags with "childInherit" set and all other flags cleared.
 * @constructor
 */
var ForwardingFlags = function ForwardingFlags(value)
{
  if (typeof value === 'object' && value instanceof ForwardingFlags) {
    // Make a copy.
    this.childInherit = value.childInherit;
    this.capture = value.capture;
  }
  else {
    this.childInherit = true;
    this.capture = false;
  }
};

exports.ForwardingFlags = ForwardingFlags;

ForwardingFlags.NfdForwardingFlags_CHILD_INHERIT = 1;
ForwardingFlags.NfdForwardingFlags_CAPTURE       = 2;

/**
 * Get an integer with the bits set according to the NFD forwarding flags as
 * used in the ControlParameters of the command interest.
 * @return {number} An integer with the bits set.
 */
ForwardingFlags.prototype.getNfdForwardingFlags = function()
{
  var result = 0;

  if (this.childInherit)
    result |= ForwardingFlags.NfdForwardingFlags_CHILD_INHERIT;
  if (this.capture)
    result |= ForwardingFlags.NfdForwardingFlags_CAPTURE;

  return result;
};

/**
 * Set the flags according to the NFD forwarding flags as used in the
 * ControlParameters of the command interest.
 * @param {number} nfdForwardingFlags An integer with the bits set.
 */
ForwardingFlags.prototype.setNfdForwardingFlags = function(nfdForwardingFlags)
{
  this.childInherit =
    ((nfdForwardingFlags & ForwardingFlags.NfdForwardingFlags_CHILD_INHERIT) != 0);
  this.capture =
    ((nfdForwardingFlags & ForwardingFlags.NfdForwardingFlags_CAPTURE) != 0);
};

/**
 * Get the value of the "childInherit" flag.
 * @return {Boolean} true if the flag is set, false if it is cleared.
 */
ForwardingFlags.prototype.getChildInherit = function() { return this.childInherit; };

/**
 * Get the value of the "capture" flag.
 * @return {Boolean} true if the flag is set, false if it is cleared.
 */
ForwardingFlags.prototype.getCapture = function() { return this.capture; };

/**
 * Set the value of the "childInherit" flag
 * @param {number} value true to set the flag, false to clear it.
 */
ForwardingFlags.prototype.setChildInherit = function(value) { this.childInherit = value; };

/**
 * Set the value of the "capture" flag
 * @param {number} value true to set the flag, false to clear it.
 */
ForwardingFlags.prototype.setCapture = function(value) { this.capture = value; };
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var ForwardingFlags = require('./forwarding-flags.js').ForwardingFlags; /** @ignore */
var Name = require('./name.js').Name; /** @ignore */
var WireFormat = require('./encoding/wire-format.js').WireFormat; /** @ignore */
var Blob = require('./util/blob.js').Blob;

/**
 * A ControlParameters which holds a Name and other fields for a
 * ControlParameters which is used, for example, in the command interest to
 * register a prefix with a forwarder. See
 * http://redmine.named-data.net/projects/nfd/wiki/ControlCommand#ControlParameters
 * @constructor
 */
var ControlParameters = function ControlParameters(value)
{
  if (typeof value === 'object' && value instanceof ControlParameters) {
    // Make a deep copy.
    this.name = value.name == null ? null : new Name(value.name);
    this.faceId = value.faceId;
    this.uri = value.uri;
    this.localControlFeature = value.localControlFeature;
    this.origin = value.origin;
    this.cost = value.cost;
    this.forwardingFlags = new ForwardingFlags(value.forwardingFlags);
    this.strategy = new Name(value.strategy);
    this.expirationPeriod = value.expirationPeriod;
  }
  else {
    this.name = null;
    this.faceId = null;
    this.uri = '';
    this.localControlFeature = null;
    this.origin = null;
    this.cost = null;
    this.forwardingFlags = new ForwardingFlags();
    this.strategy = new Name();
    this.expirationPeriod = null;
  }
};

exports.ControlParameters = ControlParameters;

ControlParameters.prototype.clear = function()
{
  this.name = null;
  this.faceId = null;
  this.uri = '';
  this.localControlFeature = null;
  this.origin = null;
  this.cost = null;
  this.forwardingFlags = new ForwardingFlags();
  this.strategy = new Name();
  this.expirationPeriod = null;
};

/**
 * Encode this ControlParameters for a particular wire format.
 * @param {WireFormat} wireFormat (optional) A WireFormat object  used to encode
 * this object. If omitted, use WireFormat.getDefaultWireFormat().
 * @return {Blob} The encoded buffer in a Blob object.
 */
ControlParameters.prototype.wireEncode = function(wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
  return wireFormat.encodeControlParameters(this);
};

/**
 * Decode the input using a particular wire format and update this
 * ControlParameters.
 * @param {Blob|Buffer} input The buffer with the bytes to decode.
 * @param {WireFormat} wireFormat (optional) A WireFormat object used to decode
 * this object. If omitted, use WireFormat.getDefaultWireFormat().
 */
ControlParameters.prototype.wireDecode = function(input, wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
  if (typeof input === 'object' && input instanceof Blob)
    // Input is a blob, so get its buf() and set copy false.
    wireFormat.decodeControlParameters(this, input.buf(), false);
  else
    wireFormat.decodeControlParameters(this, input, true);
};

/**
 * Get the name.
 * @return {Name} The name. If not specified, return null.
 */
ControlParameters.prototype.getName = function()
{
  return this.name;
};

/**
 * Get the face ID.
 * @return {number} The face ID, or null if not specified.
 */
ControlParameters.prototype.getFaceId = function()
{
  return this.faceId;
};

/**
 * Get the URI.
 * @return {string} The face URI, or an empty string if not specified.
 */
ControlParameters.prototype.getUri = function()
{
  return this.uri;
};

/**
 * Get the local control feature value.
 * @return {number} The local control feature value, or null if not specified.
 */
ControlParameters.prototype.getLocalControlFeature = function()
{
  return this.localControlFeature;
};

/**
 * Get the origin value.
 * @return {number} The origin value, or null if not specified.
 */
ControlParameters.prototype.getOrigin = function()
{
  return this.origin;
};

/**
 * Get the cost value.
 * @return {number} The cost value, or null if not specified.
 */
ControlParameters.prototype.getCost = function()
{
  return this.cost;
};

/**
 * Get the ForwardingFlags object.
 * @return {ForwardingFlags} The ForwardingFlags object.
 */
ControlParameters.prototype.getForwardingFlags = function()
{
  return this.forwardingFlags;
};

/**
 * Get the strategy.
 * @return {Name} The strategy or an empty Name
 */
ControlParameters.prototype.getStrategy = function()
{
  return this.strategy;
};

/**
 * Get the expiration period.
 * @return {number} The expiration period in milliseconds, or null if not specified.
 */
ControlParameters.prototype.getExpirationPeriod = function()
{
  return this.expirationPeriod;
};

/**
 * Set the name.
 * @param {Name} name The name. If not specified, set to null. If specified, this
 * makes a copy of the name.
 */
ControlParameters.prototype.setName = function(name)
{
  this.name = typeof name === 'object' && name instanceof Name ?
              new Name(name) : null;
};

/**
 * Set the Face ID.
 * @param {number} faceId The new face ID, or null for not specified.
 */
ControlParameters.prototype.setFaceId = function(faceId)
{
  this.faceId = faceId;
};

/**
 * Set the URI.
 * @param {string} uri The new uri, or an empty string for not specified.
 */
ControlParameters.prototype.setUri = function(uri)
{
  this.uri = uri || '';
};

/**
 * Set the local control feature value.
 * @param {number} localControlFeature The new local control feature value, or
 * null for not specified.
 */
ControlParameters.prototype.setLocalControlFeature = function(localControlFeature)
{
  this.localControlFeature = localControlFeature;
};

/**
 * Set the origin value.
 * @param {number} origin The new origin value, or null for not specified.
 */
ControlParameters.prototype.setOrigin = function(origin)
{
  this.origin = origin;
};

/**
 * Set the cost value.
 * @param {number} cost The new cost value, or null for not specified.
 */
ControlParameters.prototype.setCost = function(cost)
{
  this.cost = cost;
};

/**
 * Set the ForwardingFlags object to a copy of forwardingFlags. You can use
 * getForwardingFlags() and change the existing ForwardingFlags object.
 * @param {ForwardingFlags} forwardingFlags The new cost value, or null for not specified.
 */
ControlParameters.prototype.setForwardingFlags = function(forwardingFlags)
{
  this.forwardingFlags =
    typeof forwardingFlags === 'object' && forwardingFlags instanceof ForwardingFlags ?
      new ForwardingFlags(forwardingFlags) : new ForwardingFlags();
};

/**
 * Set the strategy to a copy of the given Name.
 * @param {Name} strategy The Name to copy, or an empty Name if not specified.
 */
ControlParameters.prototype.setStrategy = function(strategy)
{
  this.strategy = typeof strategy === 'object' && strategy instanceof Name ?
              new Name(strategy) : new Name();
};

/**
 * Set the expiration period.
 * @param {number} expirationPeriod The expiration period in milliseconds, or
 * null for not specified.
 */
ControlParameters.prototype.setExpirationPeriod = function(expirationPeriod)
{
  this.expirationPeriod = expirationPeriod;
};
/**
 * Copyright (C) 2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var ControlParameters = require('./control-parameters.js').ControlParameters; /** @ignore */
var WireFormat = require('./encoding/wire-format.js').WireFormat; /** @ignore */
var Blob = require('./util/blob.js').Blob;

/**
 * A ControlResponse holds a status code, status text and other fields for a
 * ControlResponse which is used, for example, in the response from sending a
 * register prefix control command to a forwarder.
 * @see http://redmine.named-data.net/projects/nfd/wiki/ControlCommand
 * @constructor
 */
var ControlResponse = function ControlResponse(value)
{
  if (typeof value === 'object' && value instanceof ControlResponse) {
    // Make a deep copy.
    this.statusCode_ = value.statusCode_;
    this.statusText_ = value.statusText_;
    this.bodyAsControlParameters_ = value.bodyAsControlParameters_ == null ? null
      : new ControlParameters(value.bodyAsControlParameters_);
  }
  else {
    this.statusCode_ = null;
    this.statusText_ = "";
    this.bodyAsControlParameters_ = null;
  }
};

exports.ControlResponse = ControlResponse;

ControlResponse.prototype.clear = function()
{
  this.statusCode_ = null;
  this.statusText_ = "";
  this.bodyAsControlParameters_ = null;
};

/**
 * Encode this ControlResponse for a particular wire format.
 * @param {WireFormat} wireFormat (optional) A WireFormat object  used to encode
 * this object. If omitted, use WireFormat.getDefaultWireFormat().
 * @return {Blob} The encoded buffer in a Blob object.
 */
ControlResponse.prototype.wireEncode = function(wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
  return wireFormat.encodeControlResponse(this);
};

/**
 * Decode the input using a particular wire format and update this
 * ControlResponse.
 * @param {Blob|Buffer} input The buffer with the bytes to decode.
 * @param {WireFormat} wireFormat (optional) A WireFormat object used to decode
 * this object. If omitted, use WireFormat.getDefaultWireFormat().
 */
ControlResponse.prototype.wireDecode = function(input, wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
  if (typeof input === 'object' && input instanceof Blob)
    // Input is a blob, so get its buf() and set copy false.
    wireFormat.decodeControlResponse(this, input.buf(), false);
  else
    wireFormat.decodeControlResponse(this, input, true);
};

/**
 * Get the status code.
 * @return {number} The status code. If not specified, return null.
 */
ControlResponse.prototype.getStatusCode = function()
{
  return this.statusCode_;
};

/**
 * Get the status text.
 * @return {string} The status text. If not specified, return "".
 */
ControlResponse.prototype.getStatusText = function()
{
  return this.statusText_;
};

/**
 * Get the control response body as a ControlParameters.
 * @return {ControlParameters} The ControlParameters, or null if the body is not
 * specified or if it is not a ControlParameters.
 */
ControlResponse.prototype.getBodyAsControlParameters = function()
{
  return this.bodyAsControlParameters_;
};

/**
 * Set the status code.
 * @param statusCode {number} The status code. If not specified, set to null.
 * @return {ControlResponse} This ControlResponse so that you can chain calls to
 * update values.
 */
ControlResponse.prototype.setStatusCode = function(statusCode)
{
  this.statusCode_ = statusCode;
  return this;
};

/**
 * Set the status text.
 * @param statusText {string} The status text. If not specified, set to "".
 * @return {ControlResponse} This ControlResponse so that you can chain calls to
 * update values.
 */
ControlResponse.prototype.setStatusText = function(statusText)
{
  this.statusText_ = statusText || "";
  return this;
};

/**
 * Set the control response body as a ControlParameters.
 * @param {ControlParameters} controlParameters The ControlParameters for the
 * body. This makes a copy of the ControlParameters. If not specified or if the
 * body is not a ControlParameters, set to null.
 * @return {ControlResponse} This ControlResponse so that you can chain calls to
 * update values.
 */
ControlResponse.prototype.setBodyAsControlParameters = function(controlParameters)
{
  this.bodyAsControlParameters_ =
    typeof controlParameters === 'object' && controlParameters instanceof ControlParameters ?
      new ControlParameters(controlParameters) : null;
  return this;
};
/**
 * Copyright (C) 2015-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var Name = require('./name.js').Name; /** @ignore */
var NdnRegexMatcher = require('./util/ndn-regex-matcher.js').NdnRegexMatcher;

/**
 * An InterestFilter holds a Name prefix and optional regex match expression for
 * use in Face.setInterestFilter.
 *
 * Create an InterestFilter to match any Interest whose name starts with the
 * given prefix. If the optional regexFilter is provided then the remaining
 * components match the regexFilter regular expression as described in doesMatch.
 * @param {InterestFilter|Name|string} prefix If prefix is another
 * InterestFilter copy its values. If prefix is a Name then this makes a copy of
 * the Name. Otherwise this creates a Name from the URI string.
 * @param {string} regexFilter (optional) The regular expression for matching
 * the remaining name components.
 * @constructor
 */
var InterestFilter = function InterestFilter(prefix, regexFilter)
{
  if (typeof prefix === 'object' && prefix instanceof InterestFilter) {
    // The copy constructor.
    var interestFilter = prefix;
    this.prefix = new Name(interestFilter.prefix);
    this.regexFilter = interestFilter.regexFilter;
    this.regexFilterPattern = interestFilter.regexFilterPattern;
  }
  else {
    this.prefix = new Name(prefix);
    if (regexFilter) {
      this.regexFilter = regexFilter;
      this.regexFilterPattern = InterestFilter.makePattern(regexFilter);
    }
    else {
      this.regexFilter = null;
      this.regexFilterPattern = null;
    }
  }
};

exports.InterestFilter = InterestFilter;

/**
 * Check if the given name matches this filter. Match if name starts with this
 * filter's prefix. If this filter has the optional regexFilter then the
 * remaining components match the regexFilter regular expression.
 * For example, the following InterestFilter:
 *
 *    InterestFilter("/hello", "<world><>+")
 *
 * will match all Interests, whose name has the prefix `/hello` which is
 * followed by a component `world` and has at least one more component after it.
 * Examples:
 *
 *    /hello/world/!
 *    /hello/world/x/y/z
 *
 * Note that the regular expression will need to match all remaining components
 * (e.g., there are implicit heading `^` and trailing `$` symbols in the
 * regular expression).
 * @param {Name} name The name to check against this filter.
 * @return {boolean} True if name matches this filter, otherwise false.
 */
InterestFilter.prototype.doesMatch = function(name)
{
  if (name.size() < this.prefix.size())
    return false;

  if (this.hasRegexFilter()) {
    // Perform a prefix match and regular expression match for the remaining
    // components.
    if (!this.prefix.match(name))
      return false;

    return null != NdnRegexMatcher.match
      (this.regexFilterPattern, name.getSubName(this.prefix.size()));
  }
  else
    // Just perform a prefix match.
    return this.prefix.match(name);
};

/**
 * Get the prefix given to the constructor.
 * @return {Name} The prefix Name which you should not modify.
 */
InterestFilter.prototype.getPrefix = function() { return this.prefix; };

/**
 * Check if a regexFilter was supplied to the constructor.
 * @return {boolean} True if a regexFilter was supplied to the constructor.
 */
InterestFilter.prototype.hasRegexFilter = function()
{
  return this.regexFilter != null;
};

/**
 * Get the regex filter. This is only valid if hasRegexFilter() is true.
 * @return {string} The regular expression for matching the remaining name
 * components.
 */
InterestFilter.prototype.getRegexFilter = function() { return this.regexFilter; };

/**
 * If regexFilter doesn't already have them, add ^ to the beginning and $ to
 * the end since these are required by NdnRegexMatcher.match.
 * @param {string} regexFilter The regex filter.
 * @return {string} The regex pattern with ^ and $.
 */
InterestFilter.makePattern = function(regexFilter)
{
  if (regexFilter.length == 0)
    // We don't expect this.
    return "^$";

  var pattern = regexFilter;
  if (pattern[0] != '^')
    pattern = "^" + pattern;
  if (pattern[pattern.length - 1] != '$')
    pattern = pattern + "$";

  return pattern;
};
/**
 * Copyright (C) 2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var Name = require('./name.js').Name; /** @ignore */
var Blob = require('./util/blob.js').Blob; /** @ignore */
var WireFormat = require('./encoding/wire-format.js').WireFormat;

/**
 * A DelegationSet holds a list of DelegationSet.Delegation entries which is
 * used as the content of a Link instance. If you add elements with add(), then
 * the list is a set sorted by preference number then by name. But wireDecode
 * will add the elements from the wire encoding, preserving the given order and
 * possible duplicates (in which case a DelegationSet really holds a "list" and
 * not necessarily a "set").
 *
 * Create a new DelegationSet object, possibly copying values from another
 * object.
 *
 * @param {DelegationSet} value (optional) If value is a DelegationSet, copy its
 * values.
 * @constructor
 */
var DelegationSet = function DelegationSet(value)
{
  if (typeof value === 'object' && value instanceof DelegationSet)
    // Copy the list.
    this.delegations_ = value.delegations_.slice(0);
  else
    this.delegations_ = []; // of DelegationSet.Delegation.
};

exports.DelegationSet = DelegationSet;

/**
 * A DelegationSet.Delegation holds a preference number and delegation name.
 * Create a new DelegationSet.Delegation with the given values.
 * @param {number} preference The preference number.
 * @param {Name} name The delegation name. This makes a copy of the name.
 * @constructor
 */
DelegationSet.Delegation = function DelegationSetDelegation(preference, name)
{
  this.preference_ = preference;
  this.name_ = new Name(name);
};

/**
 * Get the preference number.
 * @return {number} The preference number.
 */
DelegationSet.Delegation.prototype.getPreference = function()
{
  return this.preference_;
};

/**
 * Get the delegation name.
 * @return {Name} The delegation name. NOTE: You must not change the name object -
 * if you need to change it then make a copy.
 */
DelegationSet.Delegation.prototype.getName = function()
{
  return this.name_;
};

/**
 * Compare this Delegation with other according to the ordering, based first
 * on the preference number, then on the delegation name.
 * @param {DelegationSet.Delegation} other The other Delegation to compare with.
 * @return {number} 0 If they compare equal, -1 if this Delegation comes before
 * other in the ordering, or 1 if this Delegation comes after.
 */
DelegationSet.Delegation.prototype.compare = function(other)
{
  if (this.preference_ < other.preference_)
    return -1;
  if (this.preference_ > other.preference_)
    return 1;

  return this.name_.compare(other.name_);
};

/**
 * Add a new DelegationSet.Delegation to the list of delegations, sorted by
 * preference number then by name. If there is already a delegation with the
 * same name, update its preference, and remove any extra delegations with the
 * same name.
 * @param {number} preference The preference number.
 * @param {Name} name The delegation name. This makes a copy of the name.
 */
DelegationSet.prototype.add = function(preference, name)
{
  this.remove(name);

  var newDelegation = new DelegationSet.Delegation(preference, name);
  // Find the index of the first entry where it is not less than newDelegation.
  var i = 0;
  while (i < this.delegations_.length) {
    if (this.delegations_[i].compare(newDelegation) >= 0)
      break;

    ++i;
  }

  this.delegations_.splice(i, 0, newDelegation);
};

/**
 * Add a new DelegationSet.Delegation to the end of the list of delegations,
 * without sorting or updating any existing entries. This is useful for adding
 * preferences from a wire encoding, preserving the supplied ordering and
 * possible duplicates.
 * @param {number} preference The preference number.
 * @param {Name} name The delegation name. This makes a copy of the name.
 */
DelegationSet.prototype.addUnsorted = function(preference, name)
{
  this.delegations_.push(new DelegationSet.Delegation(preference, name));
};

/**
 * Remove every DelegationSet.Delegation with the given name.
 * @param {Name} name The name to match the name of the delegation(s) to be
 * removed.
 * @return {boolean} True if a DelegationSet.Delegation was removed, otherwise
 * false.
 */
DelegationSet.prototype.remove = function(name)
{
  var wasRemoved = false;
  // Go backwards through the list so we can remove entries.
  for (var i = this.delegations_.length - 1; i >= 0; --i) {
    if (this.delegations_[i].getName().equals(name)) {
      wasRemoved = true;
      this.delegations_.splice(i, 1);
    }
  }

  return wasRemoved;
};

/**
 * Clear the list of delegations.
 */
DelegationSet.prototype.clear = function() { this.delegations_ = []; };

/**
 * Get the number of delegation entries.
 * @return {number} The number of delegation entries.
 */
DelegationSet.prototype.size = function() { return this.delegations_.length; };

/**
 * Get the delegation at the given index, according to the ordering described
 * in add().
 * @param {number} i The index of the component, starting from 0.
 * @return {DelegationSet.Delegation} The delegation at the index.
 */
DelegationSet.prototype.get = function(i) { return this.delegations_[i]; };

/**
 * Find the first delegation with the given name and return its index.
 * @param {Name} name Then name of the delegation to find.
 * @return {number} The index of the delegation, or -1 if not found.
 */
DelegationSet.prototype.find = function(name)
{
  for (var i = 0; i < this.delegations_.length; ++i) {
    if (this.delegations_[i].getName().equals(name))
      return i;
  }

  return -1;
};

/**
 * Encode this DelegationSet for a particular wire format.
 * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
 * this object. If omitted, use WireFormat.getDefaultWireFormat().
 * @return {Blob} The encoded buffer in a Blob object.
 */
DelegationSet.prototype.wireEncode = function(wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
  return wireFormat.encodeDelegationSet(this);
};

/**
 * Decode the input using a particular wire format and update this DelegationSet.
 * @param {Blob|Buffer} input The buffer with the bytes to decode.
 * @param {WireFormat} wireFormat (optional) A WireFormat object used to decode
 * this object. If omitted, use WireFormat.getDefaultWireFormat().
 */
DelegationSet.prototype.wireDecode = function(input, wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
  if (typeof input === 'object' && input instanceof Blob)
    // Input is a blob, so get its buf() and set copy false.
    wireFormat.decodeDelegationSet(this, input.buf(), false);
  else
    wireFormat.decodeDelegationSet(this, input, true);
};
/**
 * Copyright (C) 2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var DelegationSet = require('./delegation-set.js').DelegationSet; /** @ignore */
var ContentType = require('./meta-info.js').ContentType; /** @ignore */
var WireFormat = require('./encoding/wire-format.js').WireFormat; /** @ignore */
var Data = require('./data.js').Data;

/**
 * The Link class extends Data and represents a Link instance where the Data
 * content is an encoded delegation set. The format is defined in "link.pdf"
 * attached to Redmine issue http://redmine.named-data.net/issues/2587 .
 *
 * Create a new Link with the optional values. There are 3 forms of the constructor:
 * Link(name);
 * Link(data);
 * Link();
 * @param {Name} name The name for constructing the base Data.
 * @param {Data} data The Data object to copy values from. If the content can be
 * decoded using the default wire encoding, then update the list of delegations.
 * @constructor
 */
var Link = function Link(value)
{
  this.delegations_ = new DelegationSet();

  if (value instanceof Data) {
    // Call the base constructor.
    Data.call(this, value);

    if (!this.getContent().isNull()) {
      try {
        this.delegations_.wireDecode(this.getContent());
        this.getMetaInfo().setType(ContentType.LINK);
      }
      catch (ex) {
        this.delegations_.clear();
      }
    }
  }
  else {
    if (value != undefined)
      // value is a Name.
      Data.call(this, value);
    else
      Data.call(this);

    this.getMetaInfo().setType(ContentType.LINK);
  }
};

Link.prototype = new Data();
Link.prototype.name = "Link";

exports.Link = Link;

/**
 * Override to call the base class wireDecode then populate the list of
 * delegations from the content.
 * @param {Blob|Buffer} input The buffer with the bytes to decode.
 * @param {WireFormat} wireFormat (optional) A WireFormat object used to decode
 * this object. If omitted, use WireFormat.getDefaultWireFormat().
 */
Link.prototype.wireDecode = function(input, wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());

  Data.prototype.wireDecode.call(this, input, wireFormat);
  if (this.getMetaInfo().getType() != ContentType.LINK)
    throw new Error
      ("Link.wireDecode: MetaInfo ContentType is not LINK.");

  this.delegations_.wireDecode(this.getContent());
};

/**
 * Add a new delegation to the list of delegations, sorted by preference number
 * then by name. Re-encode this object's content using the optional wireFormat.
 * @param {number} preference The preference number.
 * @param {Name} name The delegation name. This makes a copy of the name. If
 * there is already a delegation with the same name, this updates its preference.
 * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
 * the DelegationSet. If omitted, use WireFormat.getDefaultWireFormat().
 * @return {Link} This Link so that you can chain calls to update values.
 */
Link.prototype.addDelegation = function(preference, name, wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());

  this.delegations_.add(preference, name);
  this.encodeContent(wireFormat);

  return this;
};

/**
 * Remove every delegation with the given name. Re-encode this object's content
 * using the optional wireFormat.
 * @param {Name} name Then name to match the name of the delegation(s) to be
 * removed.
 * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
 * the DelegationSet. If omitted, use WireFormat.getDefaultWireFormat().
 * @return {boolean} True if a delegation was removed, otherwise false.
 */
Link.prototype.removeDelegation = function(name, wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());

  var wasRemoved = this.delegations_.remove(name);
  if (wasRemoved)
    this.encodeContent(wireFormat);

  return wasRemoved;
};

/**
 * Get the list of delegation for read only.
 * @return {DelegationSet} The list of delegation, which you should treat as
 * read-only. To modify it, call Link.addDelegation, etc.
 */
Link.prototype.getDelegations = function() { return this.delegations_; };

/**
 * A private method to encode the delegations_ and set this object's content.
 * Also set the meta info content type to LINK.
 * @param {WireFormat} wireFormat A WireFormat object used to encode the
 * DelegationSet.
 */
Link.prototype.encodeContent = function(wireFormat)
{
  this.setContent(this.delegations_.wireEncode(wireFormat));
  this.getMetaInfo().setType(ContentType.LINK);
};
/**
 * Copyright (C) 2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * @author: From ndn-cxx nack.hpp https://github.com/named-data/ndn-cxx/blob/master/src/lp/nack.hpp
 *
 * 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.
 */

/**
 * NetworkNack represents a network Nack packet and includes a Nack reason.
 * @constructor
 */
var NetworkNack = function NetworkNack()
{
  this.reason_ = NetworkNack.Reason.NONE;
  this.otherReasonCode_ = -1;
};

exports.NetworkNack = NetworkNack;

/**
 * A NetworkNack.Reason specifies the reason in a NetworkNack packet. If the
 * reason code in the packet is not a recognized enum value, then we use
 * Reason.OTHER_CODE and you can call getOtherReasonCode(). We do this to keep
 * the recognized reason values independent of packet encoding formats.
 */
NetworkNack.Reason = {
  NONE:         0,
  CONGESTION:  50,
  DUPLICATE:  100,
  NO_ROUTE:   150,
  OTHER_CODE: 0x7fff
};

/**
 * Get the network Nack reason.
 * @return {number} The reason enum value from NetworkNack.Reason. If this is
 * Reason.OTHER_CODE, then call getOtherReasonCode() to get the unrecognized
 * reason code.
 */
NetworkNack.prototype.getReason = function() { return this.reason_; };

/**
 * Get the reason code from the packet which is other than a recognized
 * Reason enum value. This is only meaningful if getReason() is
 * Reason.OTHER_CODE.
 * @return {number} The reason code.
 */
NetworkNack.prototype.getOtherReasonCode = function()
{ 
  return this.otherReasonCode_;
};

/**
 * Set the network Nack reason.
 * @param {number} reason The network Nack reason enum value from 
 * NetworkNack.Reason. If the packet's reason code is not a recognized Reason
 * enum value, use Reason.OTHER_CODE and call setOtherReasonCode().
 */
NetworkNack.prototype.setReason = function(reason) { this.reason_ = reason; };

/**
 * Set the packet's reason code to use when the reason enum is
 * Reason.OTHER_CODE. If the packet's reason code is a recognized enum value,
 * just call setReason().
 * @param {number} otherReasonCode The packet's unrecognized reason code, which
 * must be non-negative.
 */
NetworkNack.prototype.setOtherReasonCode = function(otherReasonCode)
{
  if (otherReasonCode < 0)
    throw new Error("NetworkNack other reason code must be non-negative");
  this.otherReasonCode_ = otherReasonCode;
};

/**
 * Get the first header field in lpPacket which is a NetworkNack. This is
 * an internal method which the application normally would not use.
 * @param {LpPacket} lpPacket The LpPacket with the header fields to search.
 * @return {NetworkNack} The first NetworkNack header field, or null if not
 * found.
 */
NetworkNack.getFirstHeader = function(lpPacket)
{
  for (var i = 0; i < lpPacket.countHeaderFields(); ++i) {
    var field = lpPacket.getHeaderField(i);
    if (field instanceof NetworkNack)
      return field;
  }

  return null;
};
/**
 * Copyright (C) 2013-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var Crypto = require('../crypto.js'); /** @ignore */
var Blob = require('../util/blob.js').Blob; /** @ignore */
var Name = require('../name.js').Name; /** @ignore */
var ForwardingFlags = require('../forwarding-flags').ForwardingFlags; /** @ignore */
var Tlv = require('./tlv/tlv.js').Tlv; /** @ignore */
var TlvEncoder = require('./tlv/tlv-encoder.js').TlvEncoder; /** @ignore */
var TlvDecoder = require('./tlv/tlv-decoder.js').TlvDecoder; /** @ignore */
var WireFormat = require('./wire-format.js').WireFormat; /** @ignore */
var Exclude = require('../exclude.js').Exclude; /** @ignore */
var ContentType = require('../meta-info.js').ContentType; /** @ignore */
var KeyLocatorType = require('../key-locator.js').KeyLocatorType; /** @ignore */
var Sha256WithRsaSignature = require('../sha256-with-rsa-signature.js').Sha256WithRsaSignature; /** @ignore */
var Sha256WithEcdsaSignature = require('../sha256-with-ecdsa-signature.js').Sha256WithEcdsaSignature; /** @ignore */
var GenericSignature = require('../generic-signature.js').GenericSignature; /** @ignore */
var HmacWithSha256Signature = require('../hmac-with-sha256-signature.js').HmacWithSha256Signature; /** @ignore */
var DigestSha256Signature = require('../digest-sha256-signature.js').DigestSha256Signature; /** @ignore */
var ControlParameters = require('../control-parameters.js').ControlParameters; /** @ignore */
var ForwardingFlags = require('../forwarding-flags.js').ForwardingFlags; /** @ignore */
var NetworkNack = require('../network-nack.js').NetworkNack; /** @ignore */
var IncomingFaceId = require('../lp/incoming-face-id.js').IncomingFaceId; /** @ignore */
var DecodingException = require('./decoding-exception.js').DecodingException;

/**
 * A Tlv0_2WireFormat implements the WireFormat interface for encoding and
 * decoding with the NDN-TLV wire format, version 0.2.
 * @constructor
 */
var Tlv0_2WireFormat = function Tlv0_2WireFormat()
{
  // Inherit from WireFormat.
  WireFormat.call(this);
};

Tlv0_2WireFormat.prototype = new WireFormat();
Tlv0_2WireFormat.prototype.name = "Tlv0_2WireFormat";

exports.Tlv0_2WireFormat = Tlv0_2WireFormat;

// Default object.
Tlv0_2WireFormat.instance = null;

/**
 * Encode name as an NDN-TLV Name and return the encoding.
 * @param {Name} name The Name to encode.
 * @return {Blobl} A Blob containing the encoding.
 */
Tlv0_2WireFormat.prototype.encodeName = function(name)
{
  var encoder = new TlvEncoder();
  Tlv0_2WireFormat.encodeName(name, encoder);
  return new Blob(encoder.getOutput(), false);
};

/**
 * Decode input as a NDN-TLV name and set the fields of the Name object.
 * @param {Name} name The Name object whose fields are updated.
 * @param {Buffer} input The buffer with the bytes to decode.
 * @param {boolean} copy (optional) If true, copy from the input when making new
 * Blob values. If false, then Blob values share memory with the input, which
 * must remain unchanged while the Blob values are used. If omitted, use true.
 */
Tlv0_2WireFormat.prototype.decodeName = function(name, input, copy)
{
  if (copy == null)
    copy = true;

  var decoder = new TlvDecoder(input);
  Tlv0_2WireFormat.decodeName(name, decoder, copy);
};

/**
 * Encode the interest using NDN-TLV and return a Buffer.
 * @param {Interest} interest The Interest object to encode.
 * @return {object} An associative array with fields
 * (encoding, signedPortionBeginOffset, signedPortionEndOffset) where encoding
 * is a Blob containing the encoding, signedPortionBeginOffset is the offset in
 * the encoding of the beginning of the signed portion, and
 * signedPortionEndOffset is the offset in the encoding of the end of the signed
 * portion. The signed portion starts from the first name component and ends
 * just before the final name component (which is assumed to be a signature for
 * a signed interest).
 */
Tlv0_2WireFormat.prototype.encodeInterest = function(interest)
{
  var encoder = new TlvEncoder(256);
  var saveLength = encoder.getLength();

  // Encode backwards.
  encoder.writeOptionalNonNegativeIntegerTlv
    (Tlv.SelectedDelegation, interest.getSelectedDelegationIndex());
  var linkWireEncoding = interest.getLinkWireEncoding(this);
  if (!linkWireEncoding.isNull())
    // Encode the entire link as is.
    encoder.writeBuffer(linkWireEncoding.buf());

  encoder.writeOptionalNonNegativeIntegerTlv
    (Tlv.InterestLifetime, interest.getInterestLifetimeMilliseconds());

  // Encode the Nonce as 4 bytes.
  if (interest.getNonce().isNull() || interest.getNonce().size() == 0)
    // This is the most common case. Generate a nonce.
    encoder.writeBlobTlv(Tlv.Nonce, Crypto.randomBytes(4));
  else if (interest.getNonce().size() < 4) {
    var nonce = Buffer(4);
    // Copy existing nonce bytes.
    interest.getNonce().buf().copy(nonce);

    // Generate random bytes for remaining bytes in the nonce.
    for (var i = interest.getNonce().size(); i < 4; ++i)
      nonce[i] = Crypto.randomBytes(1)[0];

    encoder.writeBlobTlv(Tlv.Nonce, nonce);
  }
  else if (interest.getNonce().size() == 4)
    // Use the nonce as-is.
    encoder.writeBlobTlv(Tlv.Nonce, interest.getNonce().buf());
  else
    // Truncate.
    encoder.writeBlobTlv(Tlv.Nonce, interest.getNonce().buf().slice(0, 4));

  Tlv0_2WireFormat.encodeSelectors(interest, encoder);
  var tempOffsets = Tlv0_2WireFormat.encodeName(interest.getName(), encoder);
  var signedPortionBeginOffsetFromBack =
    encoder.getLength() - tempOffsets.signedPortionBeginOffset;
  var signedPortionEndOffsetFromBack =
    encoder.getLength() - tempOffsets.signedPortionEndOffset;

  encoder.writeTypeAndLength(Tlv.Interest, encoder.getLength() - saveLength);
  var signedPortionBeginOffset =
    encoder.getLength() - signedPortionBeginOffsetFromBack;
  var signedPortionEndOffset =
    encoder.getLength() - signedPortionEndOffsetFromBack;

  return { encoding: new Blob(encoder.getOutput(), false),
           signedPortionBeginOffset: signedPortionBeginOffset,
           signedPortionEndOffset: signedPortionEndOffset };
};

/**
 * Decode input as an NDN-TLV interest and set the fields of the interest
 * object.
 * @param {Interest} interest The Interest object whose fields are updated.
 * @param {Buffer} input The buffer with the bytes to decode.
 * @param {boolean} copy (optional) If true, copy from the input when making new
 * Blob values. If false, then Blob values share memory with the input, which
 * must remain unchanged while the Blob values are used. If omitted, use true.
 * @return {object} An associative array with fields
 * (signedPortionBeginOffset, signedPortionEndOffset) where
 * signedPortionBeginOffset is the offset in the encoding of the beginning of
 * the signed portion, and signedPortionEndOffset is the offset in the encoding
 * of the end of the signed portion. The signed portion starts from the first
 * name component and ends just before the final name component (which is
 * assumed to be a signature for a signed interest).
 */
Tlv0_2WireFormat.prototype.decodeInterest = function(interest, input, copy)
{
  if (copy == null)
    copy = true;

  var decoder = new TlvDecoder(input);

  var endOffset = decoder.readNestedTlvsStart(Tlv.Interest);
  var offsets = Tlv0_2WireFormat.decodeName(interest.getName(), decoder, copy);
  if (decoder.peekType(Tlv.Selectors, endOffset))
    Tlv0_2WireFormat.decodeSelectors(interest, decoder, copy);
  // Require a Nonce, but don't force it to be 4 bytes.
  var nonce = decoder.readBlobTlv(Tlv.Nonce);
  interest.setInterestLifetimeMilliseconds
    (decoder.readOptionalNonNegativeIntegerTlv(Tlv.InterestLifetime, endOffset));

  if (decoder.peekType(Tlv.Data, endOffset)) {
    // Get the bytes of the Link TLV.
    var linkBeginOffset = decoder.getOffset();
    var linkEndOffset = decoder.readNestedTlvsStart(Tlv.Data);
    decoder.seek(linkEndOffset);

    interest.setLinkWireEncoding
      (new Blob(decoder.getSlice(linkBeginOffset, linkEndOffset), copy), this);
  }
  else
    interest.unsetLink();
  interest.setSelectedDelegationIndex
    (decoder.readOptionalNonNegativeIntegerTlv(Tlv.SelectedDelegation, endOffset));
  if (interest.getSelectedDelegationIndex() != null &&
      interest.getSelectedDelegationIndex() >= 0 && !interest.hasLink())
    throw new Error("Interest has a selected delegation, but no link object");

  // Set the nonce last because setting other interest fields clears it.
  interest.setNonce(new Blob(nonce, copy));

  decoder.finishNestedTlvs(endOffset);
  return offsets;
};

/**
 * Encode data as NDN-TLV and return the encoding and signed offsets.
 * @param {Data} data The Data object to encode.
 * @return {object} An associative array with fields
 * (encoding, signedPortionBeginOffset, signedPortionEndOffset) where encoding
 * is a Blob containing the encoding, signedPortionBeginOffset is the offset in
 * the encoding of the beginning of the signed portion, and
 * signedPortionEndOffset is the offset in the encoding of the end of the
 * signed portion.
 */
Tlv0_2WireFormat.prototype.encodeData = function(data)
{
  var encoder = new TlvEncoder(1500);
  var saveLength = encoder.getLength();

  // Encode backwards.
  encoder.writeBlobTlv(Tlv.SignatureValue, data.getSignature().getSignature().buf());
  var signedPortionEndOffsetFromBack = encoder.getLength();

  Tlv0_2WireFormat.encodeSignatureInfo_(data.getSignature(), encoder);
  encoder.writeBlobTlv(Tlv.Content, data.getContent().buf());
  Tlv0_2WireFormat.encodeMetaInfo(data.getMetaInfo(), encoder);
  Tlv0_2WireFormat.encodeName(data.getName(), encoder);
  var signedPortionBeginOffsetFromBack = encoder.getLength();

  encoder.writeTypeAndLength(Tlv.Data, encoder.getLength() - saveLength);
  var signedPortionBeginOffset =
    encoder.getLength() - signedPortionBeginOffsetFromBack;
  var signedPortionEndOffset = encoder.getLength() - signedPortionEndOffsetFromBack;

  return { encoding: new Blob(encoder.getOutput(), false),
           signedPortionBeginOffset: signedPortionBeginOffset,
           signedPortionEndOffset: signedPortionEndOffset };
};

/**
 * Decode input as an NDN-TLV data packet, set the fields in the data object,
 * and return the signed offsets.
 * @param {Data} data The Data object whose fields are updated.
 * @param {Buffer} input The buffer with the bytes to decode.
 * @param {boolean} copy (optional) If true, copy from the input when making new
 * Blob values. If false, then Blob values share memory with the input, which
 * must remain unchanged while the Blob values are used. If omitted, use true.
 * @return {object} An associative array with fields
 * (signedPortionBeginOffset, signedPortionEndOffset) where
 * signedPortionBeginOffset is the offset in the encoding of the beginning of
 * the signed portion, and signedPortionEndOffset is the offset in the encoding
 * of the end of the signed portion.
 */
Tlv0_2WireFormat.prototype.decodeData = function(data, input, copy)
{
  if (copy == null)
    copy = true;

  var decoder = new TlvDecoder(input);

  var endOffset = decoder.readNestedTlvsStart(Tlv.Data);
  var signedPortionBeginOffset = decoder.getOffset();

  Tlv0_2WireFormat.decodeName(data.getName(), decoder, copy);
  Tlv0_2WireFormat.decodeMetaInfo(data.getMetaInfo(), decoder, copy);
  data.setContent(new Blob(decoder.readBlobTlv(Tlv.Content), copy));
  Tlv0_2WireFormat.decodeSignatureInfo(data, decoder, copy);

  var signedPortionEndOffset = decoder.getOffset();
  data.getSignature().setSignature
    (new Blob(decoder.readBlobTlv(Tlv.SignatureValue), copy));

  decoder.finishNestedTlvs(endOffset);
  return { signedPortionBeginOffset: signedPortionBeginOffset,
           signedPortionEndOffset: signedPortionEndOffset };
};

/**
 * Encode controlParameters as NDN-TLV and return the encoding.
 * @param {ControlParameters} controlParameters The ControlParameters object to
 * encode.
 * @return {Blob} A Blob containing the encoding.
 */
Tlv0_2WireFormat.prototype.encodeControlParameters = function(controlParameters)
{
  var encoder = new TlvEncoder(256);
  Tlv0_2WireFormat.encodeControlParameters(controlParameters, encoder);
  return new Blob(encoder.getOutput(), false);
};

/**
  * Decode controlParameters in NDN-TLV and return the encoding.
  * @param {ControlParameters} controlParameters The ControlParameters object to
  * encode.
  * @param {Buffer} input The buffer with the bytes to decode.
 * @param {boolean} copy (optional) If true, copy from the input when making new
 * Blob values. If false, then Blob values share memory with the input, which
 * must remain unchanged while the Blob values are used. If omitted, use true.
  * @throws DecodingException For invalid encoding
  */
Tlv0_2WireFormat.prototype.decodeControlParameters = function
  (controlParameters, input, copy)
{
  if (copy == null)
    copy = true;

  var decoder = new TlvDecoder(input);
  Tlv0_2WireFormat.decodeControlParameters(controlParameters, decoder, copy);
};

/**
 * Encode controlResponse as NDN-TLV and return the encoding.
 * @param {ControlResponse} controlResponse The ControlResponse object to
 * encode.
 * @return {Blob} A Blob containing the encoding.
 */
Tlv0_2WireFormat.prototype.encodeControlResponse = function(controlResponse)
{
  var encoder = new TlvEncoder(256);
  var saveLength = encoder.getLength();

  // Encode backwards.

  // Encode the body.
  if (controlResponse.getBodyAsControlParameters() != null)
    Tlv0_2WireFormat.encodeControlParameters
      (controlResponse.getBodyAsControlParameters(), encoder);

  encoder.writeBlobTlv
    (Tlv.NfdCommand_StatusText, new Blob(controlResponse.getStatusText()).buf());
  encoder.writeNonNegativeIntegerTlv
    (Tlv.NfdCommand_StatusCode, controlResponse.getStatusCode());

  encoder.writeTypeAndLength
    (Tlv.NfdCommand_ControlResponse, encoder.getLength() - saveLength);

  return new Blob(encoder.getOutput(), false);
};

/**
 * Decode controlResponse in NDN-TLV and return the encoding.
 * @param {ControlResponse} controlResponse The ControlResponse object to
 * encode.
 * @param {Buffer} input The buffer with the bytes to decode.
 * @param {boolean} copy (optional) If true, copy from the input when making new
 * Blob values. If false, then Blob values share memory with the input, which
 * must remain unchanged while the Blob values are used. If omitted, use true.
 * @throws DecodingException For invalid encoding
 */
Tlv0_2WireFormat.prototype.decodeControlResponse = function
  (controlResponse, input, copy)
{
  if (copy == null)
    copy = true;

  var decoder = new TlvDecoder(input);
  var endOffset = decoder.readNestedTlvsStart(Tlv.NfdCommand_ControlResponse);

  controlResponse.setStatusCode(decoder.readNonNegativeIntegerTlv
    (Tlv.NfdCommand_StatusCode));
  // Set copy false since we just immediately get a string.
  var statusText = new Blob
    (decoder.readBlobTlv(Tlv.NfdCommand_StatusText), false);
  controlResponse.setStatusText(statusText.toString());

  // Decode the body.
  if (decoder.peekType(Tlv.ControlParameters_ControlParameters, endOffset)) {
    controlResponse.setBodyAsControlParameters(new ControlParameters());
    // Decode into the existing ControlParameters to avoid copying.
    Tlv0_2WireFormat.decodeControlParameters
      (controlResponse.getBodyAsControlParameters(), decoder, copy);
  }
  else
    controlResponse.setBodyAsControlParameters(null);

  decoder.finishNestedTlvs(endOffset);
};

/**
 * Encode signature as an NDN-TLV SignatureInfo and return the encoding.
 * @param {Signature} signature An object of a subclass of Signature to encode.
 * @return {Blob} A Blob containing the encoding.
 */
Tlv0_2WireFormat.prototype.encodeSignatureInfo = function(signature)
{
  var encoder = new TlvEncoder(256);
  Tlv0_2WireFormat.encodeSignatureInfo_(signature, encoder);

  return new Blob(encoder.getOutput(), false);
};

// SignatureHolder is used by decodeSignatureInfoAndValue.
Tlv0_2WireFormat.SignatureHolder = function Tlv0_2WireFormatSignatureHolder()
{
};

Tlv0_2WireFormat.SignatureHolder.prototype.setSignature = function(signature)
{
  this.signature = signature;
};

Tlv0_2WireFormat.SignatureHolder.prototype.getSignature = function()
{
  return this.signature;
};

/**
 * Decode signatureInfo as an NDN-TLV SignatureInfo and signatureValue as the
 * related SignatureValue, and return a new object which is a subclass of Signature.
 * @param {Buffer} signatureInfo The buffer with the signature info bytes to
 * decode.
 * @param {Buffer} signatureValue The buffer with the signature value to decode.
 * @param {boolean} copy (optional) If true, copy from the input when making new
 * Blob values. If false, then Blob values share memory with the input, which
 * must remain unchanged while the Blob values are used. If omitted, use true.
 * @return {Signature} A new object which is a subclass of Signature.
 */
Tlv0_2WireFormat.prototype.decodeSignatureInfoAndValue = function
  (signatureInfo, signatureValue, copy)
{
  if (copy == null)
    copy = true;

  // Use a SignatureHolder to imitate a Data object for decodeSignatureInfo.
  var signatureHolder = new Tlv0_2WireFormat.SignatureHolder();
  var decoder = new TlvDecoder(signatureInfo);
  Tlv0_2WireFormat.decodeSignatureInfo(signatureHolder, decoder, copy);

  decoder = new TlvDecoder(signatureValue);
  signatureHolder.getSignature().setSignature
    (new Blob(decoder.readBlobTlv(Tlv.SignatureValue), copy));

  return signatureHolder.getSignature();
};

/**
 * Encode the signatureValue in the Signature object as an NDN-TLV
 * SignatureValue (the signature bits) and return the encoding.
 * @param {Signature} signature An object of a subclass of Signature with the
 * signature value to encode.
 * @return {Blob} A Blob containing the encoding.
 */
Tlv0_2WireFormat.prototype.encodeSignatureValue = function(signature)
{
  var encoder = new TlvEncoder(256);
  encoder.writeBlobTlv(Tlv.SignatureValue, signature.getSignature().buf());

  return new Blob(encoder.getOutput(), false);
};

/**
 * Decode input as an NDN-TLV LpPacket and set the fields of the lpPacket object.
 * @param {LpPacket} lpPacket The LpPacket object whose fields are updated.
 * @param {Buffer} input The buffer with the bytes to decode.
 * @param {boolean} copy (optional) If true, copy from the input when making new
 * Blob values. If false, then Blob values share memory with the input, which
 * must remain unchanged while the Blob values are used. If omitted, use true.
 */
Tlv0_2WireFormat.prototype.decodeLpPacket = function(lpPacket, input, copy)
{
  if (copy == null)
    copy = true;

  lpPacket.clear();

  var decoder = new TlvDecoder(input);
  var endOffset = decoder.readNestedTlvsStart(Tlv.LpPacket_LpPacket);

  while (decoder.getOffset() < endOffset) {
    // Imitate TlvDecoder.readTypeAndLength.
    var fieldType = decoder.readVarNumber();
    var fieldLength = decoder.readVarNumber();
    var fieldEndOffset = decoder.getOffset() + fieldLength;
    if (fieldEndOffset > input.length)
      throw new DecodingException(new Error("TLV length exceeds the buffer length"));

    if (fieldType == Tlv.LpPacket_Fragment) {
      // Set the fragment to the bytes of the TLV value.
      lpPacket.setFragmentWireEncoding
        (new Blob(decoder.getSlice(decoder.getOffset(), fieldEndOffset), copy));
      decoder.seek(fieldEndOffset);

      // The fragment is supposed to be the last field.
      break;
    }
    else if (fieldType == Tlv.LpPacket_Nack) {
      var networkNack = new NetworkNack();
      var code = decoder.readOptionalNonNegativeIntegerTlv
        (Tlv.LpPacket_NackReason, fieldEndOffset);
      var reason;
      // The enum numeric values are the same as this wire format, so use as is.
      if (code < 0 || code == NetworkNack.Reason.NONE)
        // This includes an omitted NackReason.
        networkNack.setReason(NetworkNack.Reason.NONE);
      else if (code == NetworkNack.Reason.CONGESTION ||
               code == NetworkNack.Reason.DUPLICATE ||
               code == NetworkNack.Reason.NO_ROUTE)
        networkNack.setReason(code);
      else {
        // Unrecognized reason.
        networkNack.setReason(NetworkNack.Reason.OTHER_CODE);
        networkNack.setOtherReasonCode(code);
      }

      lpPacket.addHeaderField(networkNack);
    }
    else if (fieldType == Tlv.LpPacket_IncomingFaceId) {
      var incomingFaceId = new IncomingFaceId();
      incomingFaceId.setFaceId(decoder.readNonNegativeInteger(fieldLength));
      lpPacket.addHeaderField(incomingFaceId);
    }
    else {
      // Unrecognized field type. The conditions for ignoring are here:
      // http://redmine.named-data.net/projects/nfd/wiki/NDNLPv2
      var canIgnore =
        (fieldType >= Tlv.LpPacket_IGNORE_MIN &&
         fieldType <= Tlv.LpPacket_IGNORE_MAX &&
         (fieldType & 0x01) === 1);
      if  (!canIgnore)
        throw new DecodingException(new Error("Did not get the expected TLV type"));

      // Ignore.
      decoder.seek(fieldEndOffset);
    }

    decoder.finishNestedTlvs(fieldEndOffset);
  }

  decoder.finishNestedTlvs(endOffset);
};

/**
 * Encode delegationSet as a sequence of NDN-TLV Delegation, and return the
 * encoding. Note that the sequence of Delegation does not have an outer TLV
 * type and length because it is intended to use the type and length of a Data
 * packet's Content.
 * @param {DelegationSet} delegationSet The DelegationSet object to encode.
 * @return {Blob} A Blob containing the encoding.
 */
Tlv0_2WireFormat.prototype.encodeDelegationSet = function(delegationSet)
{
  var encoder = new TlvEncoder(256);

  // Encode backwards.
  for (var i = delegationSet.size() - 1; i >= 0; --i) {
    var saveLength = encoder.getLength();

    Tlv0_2WireFormat.encodeName(delegationSet.get(i).getName(), encoder);
    encoder.writeNonNegativeIntegerTlv
      (Tlv.Link_Preference, delegationSet.get(i).getPreference());

    encoder.writeTypeAndLength
      (Tlv.Link_Delegation, encoder.getLength() - saveLength);
  }

  return new Blob(encoder.getOutput(), false);
};

/**
 * Decode input as a sequence of NDN-TLV Delegation and set the fields of the
 * delegationSet object. Note that the sequence of Delegation does not have an
 * outer TLV type and length because it is intended to use the type and length
 * of a Data packet's Content. This ignores any elements after the sequence
 * of Delegation.
 * @param {DelegationSet} delegationSet The DelegationSet object
 * whose fields are updated.
 * @param {Buffer} input The buffer with the bytes to decode.
 * @param {boolean} copy (optional) If true, copy from the input when making new
 * Blob values. If false, then Blob values share memory with the input, which
 * must remain unchanged while the Blob values are used. If omitted, use true.
 */
Tlv0_2WireFormat.prototype.decodeDelegationSet = function
  (delegationSet, input, copy)
{
  if (copy == null)
    copy = true;

  var decoder = new TlvDecoder(input);
  var endOffset = input.length;

  delegationSet.clear();
  while (decoder.getOffset() < endOffset) {
    decoder.readTypeAndLength(Tlv.Link_Delegation);
    var preference = decoder.readNonNegativeIntegerTlv(Tlv.Link_Preference);
    var name = new Name();
    Tlv0_2WireFormat.decodeName(name, decoder, copy);

    // Add unsorted to preserve the order so that Interest selected delegation
    // index will work.
    delegationSet.addUnsorted(preference, name);
  }
};

/**
 * Encode the EncryptedContent in NDN-TLV and return the encoding.
 * @param {EncryptedContent} encryptedContent The EncryptedContent object to
 * encode.
 * @return {Blob} A Blob containing the encoding.
 */
Tlv0_2WireFormat.prototype.encodeEncryptedContent = function(encryptedContent)
{
  var encoder = new TlvEncoder(256);
  var saveLength = encoder.getLength();

  // Encode backwards.
  encoder.writeBlobTlv
    (Tlv.Encrypt_EncryptedPayload, encryptedContent.getPayload().buf());
  encoder.writeOptionalBlobTlv
    (Tlv.Encrypt_InitialVector, encryptedContent.getInitialVector().buf());
  // Assume the algorithmType value is the same as the TLV type.
  encoder.writeNonNegativeIntegerTlv
    (Tlv.Encrypt_EncryptionAlgorithm, encryptedContent.getAlgorithmType());
  Tlv0_2WireFormat.encodeKeyLocator
    (Tlv.KeyLocator, encryptedContent.getKeyLocator(), encoder);

  encoder.writeTypeAndLength
    (Tlv.Encrypt_EncryptedContent, encoder.getLength() - saveLength);

  return new Blob(encoder.getOutput(), false);
};

/**
 * Decode input as an EncryptedContent in NDN-TLV and set the fields of the
 * encryptedContent object.
 * @param {EncryptedContent} encryptedContent The EncryptedContent object
 * whose fields are updated.
 * @param {Buffer} input The buffer with the bytes to decode.
 * @param {boolean} copy (optional) If true, copy from the input when making new
 * Blob values. If false, then Blob values share memory with the input, which
 * must remain unchanged while the Blob values are used. If omitted, use true.
 */
Tlv0_2WireFormat.prototype.decodeEncryptedContent = function
  (encryptedContent, input, copy)
{
  if (copy == null)
    copy = true;

  var decoder = new TlvDecoder(input);
  var endOffset = decoder.
    readNestedTlvsStart(Tlv.Encrypt_EncryptedContent);

  Tlv0_2WireFormat.decodeKeyLocator
    (Tlv.KeyLocator, encryptedContent.getKeyLocator(), decoder, copy);
  encryptedContent.setAlgorithmType
    (decoder.readNonNegativeIntegerTlv(Tlv.Encrypt_EncryptionAlgorithm));
  encryptedContent.setInitialVector
    (new Blob(decoder.readOptionalBlobTlv
     (Tlv.Encrypt_InitialVector, endOffset), copy));
  encryptedContent.setPayload
    (new Blob(decoder.readBlobTlv(Tlv.Encrypt_EncryptedPayload), copy));

  decoder.finishNestedTlvs(endOffset);
};

/**
 * Get a singleton instance of a Tlv0_2WireFormat.  To always use the
 * preferred version NDN-TLV, you should use TlvWireFormat.get().
 * @return {Tlv0_2WireFormat} The singleton instance.
 */
Tlv0_2WireFormat.get = function()
{
  if (Tlv0_2WireFormat.instance === null)
    Tlv0_2WireFormat.instance = new Tlv0_2WireFormat();
  return Tlv0_2WireFormat.instance;
};

/**
 * Encode the name component to the encoder as NDN-TLV. This handles different
 * component types such as ImplicitSha256DigestComponent.
 * @param {Name.Component} component The name component to encode.
 * @param {TlvEncoder} encoder The encoder to receive the encoding.
 */
Tlv0_2WireFormat.encodeNameComponent = function(component, encoder)
{
  var type = component.isImplicitSha256Digest() ?
      Tlv.ImplicitSha256DigestComponent : Tlv.NameComponent;
  encoder.writeBlobTlv(type, component.getValue().buf());
};

/**
 * Decode the name component as NDN-TLV and return the component. This handles
 * different component types such as ImplicitSha256DigestComponent.
 * @param {TlvDecoder} decoder The decoder with the input.
 * @param {boolean} copy (optional) If true, copy from the input when making new
 * Blob values. If false, then Blob values share memory with the input, which
 * must remain unchanged while the Blob values are used. If omitted, use true.
 * @return {Name.Component} A new Name.Component.
 */
Tlv0_2WireFormat.decodeNameComponent = function(decoder, copy)
{
  if (copy == null)
    copy = true;

  var savePosition = decoder.getOffset();
  var type = decoder.readVarNumber();
  // Restore the position.
  decoder.seek(savePosition);

  var value = new Blob(decoder.readBlobTlv(type), copy);
  if (type === Tlv.ImplicitSha256DigestComponent)
    return Name.Component.fromImplicitSha256Digest(value);
  else
    return new Name.Component(value);
};

/**
 * Encode the name to the encoder.
 * @param {Name} name The name to encode.
 * @param {TlvEncoder} encoder The encoder to receive the encoding.
 * @return {object} An associative array with fields
 * (signedPortionBeginOffset, signedPortionEndOffset) where
 * signedPortionBeginOffset is the offset in the encoding of the beginning of
 * the signed portion, and signedPortionEndOffset is the offset in the encoding
 * of the end of the signed portion. The signed portion starts from the first
 * name component and ends just before the final name component (which is
 * assumed to be a signature for a signed interest).
 */
Tlv0_2WireFormat.encodeName = function(name, encoder)
{
  var saveLength = encoder.getLength();

  // Encode the components backwards.
  var signedPortionEndOffsetFromBack;
  for (var i = name.size() - 1; i >= 0; --i) {
    Tlv0_2WireFormat.encodeNameComponent(name.get(i), encoder);
    if (i == name.size() - 1)
      signedPortionEndOffsetFromBack = encoder.getLength();
  }

  var signedPortionBeginOffsetFromBack = encoder.getLength();
  encoder.writeTypeAndLength(Tlv.Name, encoder.getLength() - saveLength);

  var signedPortionBeginOffset =
    encoder.getLength() - signedPortionBeginOffsetFromBack;
  var signedPortionEndOffset;
  if (name.size() == 0)
    // There is no "final component", so set signedPortionEndOffset arbitrarily.
    signedPortionEndOffset = signedPortionBeginOffset;
  else
    signedPortionEndOffset = encoder.getLength() - signedPortionEndOffsetFromBack;

  return { signedPortionBeginOffset: signedPortionBeginOffset,
           signedPortionEndOffset: signedPortionEndOffset };
};

/**
 * Clear the name, decode a Name from the decoder and set the fields of the name
 * object.
 * @param {Name} name The name object whose fields are updated.
 * @param {TlvDecoder} decoder The decoder with the input.
 * @return {object} An associative array with fields
 * (signedPortionBeginOffset, signedPortionEndOffset) where
 * signedPortionBeginOffset is the offset in the encoding of the beginning of
 * the signed portion, and signedPortionEndOffset is the offset in the encoding
 * of the end of the signed portion. The signed portion starts from the first
 * name component and ends just before the final name component (which is
 * assumed to be a signature for a signed interest).
 */
Tlv0_2WireFormat.decodeName = function(name, decoder, copy)
{
  name.clear();

  var endOffset = decoder.readNestedTlvsStart(Tlv.Name);
  var signedPortionBeginOffset = decoder.getOffset();
  // In case there are no components, set signedPortionEndOffset arbitrarily.
  var signedPortionEndOffset = signedPortionBeginOffset;

  while (decoder.getOffset() < endOffset) {
    signedPortionEndOffset = decoder.getOffset();
    name.append(Tlv0_2WireFormat.decodeNameComponent(decoder, copy));
  }

  decoder.finishNestedTlvs(endOffset);

  return { signedPortionBeginOffset: signedPortionBeginOffset,
           signedPortionEndOffset: signedPortionEndOffset };
};

/**
 * Encode the interest selectors.  If no selectors are written, do not output a
 * Selectors TLV.
 */
Tlv0_2WireFormat.encodeSelectors = function(interest, encoder)
{
  var saveLength = encoder.getLength();

  // Encode backwards.
  if (interest.getMustBeFresh())
    encoder.writeTypeAndLength(Tlv.MustBeFresh, 0);
  encoder.writeOptionalNonNegativeIntegerTlv(
    Tlv.ChildSelector, interest.getChildSelector());
  if (interest.getExclude().size() > 0)
    Tlv0_2WireFormat.encodeExclude(interest.getExclude(), encoder);

  if (interest.getKeyLocator().getType() != null)
    Tlv0_2WireFormat.encodeKeyLocator
      (Tlv.PublisherPublicKeyLocator, interest.getKeyLocator(), encoder);

  encoder.writeOptionalNonNegativeIntegerTlv(
    Tlv.MaxSuffixComponents, interest.getMaxSuffixComponents());
  encoder.writeOptionalNonNegativeIntegerTlv(
    Tlv.MinSuffixComponents, interest.getMinSuffixComponents());

  // Only output the type and length if values were written.
  if (encoder.getLength() != saveLength)
    encoder.writeTypeAndLength(Tlv.Selectors, encoder.getLength() - saveLength);
};

Tlv0_2WireFormat.decodeSelectors = function(interest, decoder, copy)
{
  if (copy == null)
    copy = true;

  var endOffset = decoder.readNestedTlvsStart(Tlv.Selectors);

  interest.setMinSuffixComponents(decoder.readOptionalNonNegativeIntegerTlv
    (Tlv.MinSuffixComponents, endOffset));
  interest.setMaxSuffixComponents(decoder.readOptionalNonNegativeIntegerTlv
    (Tlv.MaxSuffixComponents, endOffset));

  if (decoder.peekType(Tlv.PublisherPublicKeyLocator, endOffset))
    Tlv0_2WireFormat.decodeKeyLocator
      (Tlv.PublisherPublicKeyLocator, interest.getKeyLocator(), decoder, copy);
  else
    interest.getKeyLocator().clear();

  if (decoder.peekType(Tlv.Exclude, endOffset))
    Tlv0_2WireFormat.decodeExclude(interest.getExclude(), decoder, copy);
  else
    interest.getExclude().clear();

  interest.setChildSelector(decoder.readOptionalNonNegativeIntegerTlv
    (Tlv.ChildSelector, endOffset));
  interest.setMustBeFresh(decoder.readBooleanTlv(Tlv.MustBeFresh, endOffset));

  decoder.finishNestedTlvs(endOffset);
};

Tlv0_2WireFormat.encodeExclude = function(exclude, encoder)
{
  var saveLength = encoder.getLength();

  // TODO: Do we want to order the components (except for ANY)?
  // Encode the entries backwards.
  for (var i = exclude.size() - 1; i >= 0; --i) {
    var entry = exclude.get(i);

    if (entry == Exclude.ANY)
      encoder.writeTypeAndLength(Tlv.Any, 0);
    else
      Tlv0_2WireFormat.encodeNameComponent(entry, encoder);
  }

  encoder.writeTypeAndLength(Tlv.Exclude, encoder.getLength() - saveLength);
};

Tlv0_2WireFormat.decodeExclude = function(exclude, decoder, copy)
{
  if (copy == null)
    copy = true;

  var endOffset = decoder.readNestedTlvsStart(Tlv.Exclude);

  exclude.clear();
  while (decoder.getOffset() < endOffset) {
    if (decoder.peekType(Tlv.Any, endOffset)) {
      // Read past the Any TLV.
      decoder.readBooleanTlv(Tlv.Any, endOffset);
      exclude.appendAny();
    }
    else
      exclude.appendComponent(Tlv0_2WireFormat.decodeNameComponent(decoder, copy));
  }

  decoder.finishNestedTlvs(endOffset);
};

Tlv0_2WireFormat.encodeKeyLocator = function(type, keyLocator, encoder)
{
  var saveLength = encoder.getLength();

  // Encode backwards.
  if (keyLocator.getType() != null) {
    if (keyLocator.getType() == KeyLocatorType.KEYNAME)
      Tlv0_2WireFormat.encodeName(keyLocator.getKeyName(), encoder);
    else if (keyLocator.getType() == KeyLocatorType.KEY_LOCATOR_DIGEST &&
             keyLocator.getKeyData().size() > 0)
      encoder.writeBlobTlv(Tlv.KeyLocatorDigest, keyLocator.getKeyData().buf());
    else
      throw new Error("Unrecognized KeyLocatorType " + keyLocator.getType());
  }

  encoder.writeTypeAndLength(type, encoder.getLength() - saveLength);
};

Tlv0_2WireFormat.decodeKeyLocator = function
  (expectedType, keyLocator, decoder, copy)
{
  if (copy == null)
    copy = true;

  var endOffset = decoder.readNestedTlvsStart(expectedType);

  keyLocator.clear();

  if (decoder.getOffset() == endOffset)
    // The KeyLocator is omitted, so leave the fields as none.
    return;

  if (decoder.peekType(Tlv.Name, endOffset)) {
    // KeyLocator is a Name.
    keyLocator.setType(KeyLocatorType.KEYNAME);
    Tlv0_2WireFormat.decodeName(keyLocator.getKeyName(), decoder, copy);
  }
  else if (decoder.peekType(Tlv.KeyLocatorDigest, endOffset)) {
    // KeyLocator is a KeyLocatorDigest.
    keyLocator.setType(KeyLocatorType.KEY_LOCATOR_DIGEST);
    keyLocator.setKeyData
      (new Blob(decoder.readBlobTlv(Tlv.KeyLocatorDigest), copy));
  }
  else
    throw new DecodingException(new Error
      ("decodeKeyLocator: Unrecognized key locator type"));

  decoder.finishNestedTlvs(endOffset);
};

/**
 * An internal method to encode signature as the appropriate form of
 * SignatureInfo in NDN-TLV.
 * @param {Signature} signature An object of a subclass of Signature to encode.
 * @param {TlvEncoder} encoder The encoder.
 */
Tlv0_2WireFormat.encodeSignatureInfo_ = function(signature, encoder)
{
  if (signature instanceof GenericSignature) {
    // Handle GenericSignature separately since it has the entire encoding.
    var encoding = signature.getSignatureInfoEncoding();

    // Do a test decoding to sanity check that it is valid TLV.
    try {
      var decoder = new TlvDecoder(encoding.buf());
      var endOffset = decoder.readNestedTlvsStart(Tlv.SignatureInfo);
      decoder.readNonNegativeIntegerTlv(Tlv.SignatureType);
      decoder.finishNestedTlvs(endOffset);
    } catch (ex) {
      throw new Error
        ("The GenericSignature encoding is not a valid NDN-TLV SignatureInfo: " +
         ex.message);
    }

    encoder.writeBuffer(encoding.buf());
    return;
  }

  var saveLength = encoder.getLength();

  // Encode backwards.
  if (signature instanceof Sha256WithRsaSignature) {
    Tlv0_2WireFormat.encodeKeyLocator
      (Tlv.KeyLocator, signature.getKeyLocator(), encoder);
    encoder.writeNonNegativeIntegerTlv
      (Tlv.SignatureType, Tlv.SignatureType_SignatureSha256WithRsa);
  }
  else if (signature instanceof Sha256WithEcdsaSignature) {
    Tlv0_2WireFormat.encodeKeyLocator
      (Tlv.KeyLocator, signature.getKeyLocator(), encoder);
    encoder.writeNonNegativeIntegerTlv
      (Tlv.SignatureType, Tlv.SignatureType_SignatureSha256WithEcdsa);
  }
  else if (signature instanceof HmacWithSha256Signature) {
    Tlv0_2WireFormat.encodeKeyLocator
      (Tlv.KeyLocator, signature.getKeyLocator(), encoder);
    encoder.writeNonNegativeIntegerTlv
      (Tlv.SignatureType, Tlv.SignatureType_SignatureHmacWithSha256);
  }
  else if (signature instanceof DigestSha256Signature)
    encoder.writeNonNegativeIntegerTlv
      (Tlv.SignatureType, Tlv.SignatureType_DigestSha256);
  else
    throw new Error("encodeSignatureInfo: Unrecognized Signature object type");

  encoder.writeTypeAndLength(Tlv.SignatureInfo, encoder.getLength() - saveLength);
};

Tlv0_2WireFormat.decodeSignatureInfo = function(data, decoder, copy)
{
  if (copy == null)
    copy = true;

  var beginOffset = decoder.getOffset();
  var endOffset = decoder.readNestedTlvsStart(Tlv.SignatureInfo);

  var signatureType = decoder.readNonNegativeIntegerTlv(Tlv.SignatureType);
  if (signatureType == Tlv.SignatureType_SignatureSha256WithRsa) {
    data.setSignature(new Sha256WithRsaSignature());
    // Modify data's signature object because if we create an object
    //   and set it, then data will have to copy all the fields.
    var signatureInfo = data.getSignature();
    Tlv0_2WireFormat.decodeKeyLocator
      (Tlv.KeyLocator, signatureInfo.getKeyLocator(), decoder, copy);
  }
  else if (signatureType == Tlv.SignatureType_SignatureSha256WithEcdsa) {
    data.setSignature(new Sha256WithEcdsaSignature());
    var signatureInfo = data.getSignature();
    Tlv0_2WireFormat.decodeKeyLocator
      (Tlv.KeyLocator, signatureInfo.getKeyLocator(), decoder, copy);
  }
  else if (signatureType == Tlv.SignatureType_SignatureHmacWithSha256) {
    data.setSignature(new HmacWithSha256Signature());
    var signatureInfo = data.getSignature();
    Tlv0_2WireFormat.decodeKeyLocator
      (Tlv.KeyLocator, signatureInfo.getKeyLocator(), decoder, copy);
  }
  else if (signatureType == Tlv.SignatureType_DigestSha256)
    data.setSignature(new DigestSha256Signature());
  else {
    data.setSignature(new GenericSignature());
    var signatureInfo = data.getSignature();

    // Get the bytes of the SignatureInfo TLV.
    signatureInfo.setSignatureInfoEncoding
      (new Blob(decoder.getSlice(beginOffset, endOffset), copy), signatureType);
  }

  decoder.finishNestedTlvs(endOffset);
};

Tlv0_2WireFormat.encodeMetaInfo = function(metaInfo, encoder)
{
  var saveLength = encoder.getLength();

  // Encode backwards.
  var finalBlockIdBuf = metaInfo.getFinalBlockId().getValue().buf();
  if (finalBlockIdBuf != null && finalBlockIdBuf.length > 0) {
    // FinalBlockId has an inner NameComponent.
    var finalBlockIdSaveLength = encoder.getLength();
    Tlv0_2WireFormat.encodeNameComponent(metaInfo.getFinalBlockId(), encoder);
    encoder.writeTypeAndLength
      (Tlv.FinalBlockId, encoder.getLength() - finalBlockIdSaveLength);
  }

  encoder.writeOptionalNonNegativeIntegerTlv
    (Tlv.FreshnessPeriod, metaInfo.getFreshnessPeriod());
  if (metaInfo.getType() != ContentType.BLOB) {
    // Not the default, so we need to encode the type.
    if (metaInfo.getType() == ContentType.LINK ||
        metaInfo.getType() == ContentType.KEY ||
        metaInfo.getType() == ContentType.NACK)
      // The ContentType enum is set up with the correct integer for
      // each NDN-TLV ContentType.
      encoder.writeNonNegativeIntegerTlv(Tlv.ContentType, metaInfo.getType());
    else if (metaInfo.getType() == ContentType.OTHER_CODE)
      encoder.writeNonNegativeIntegerTlv
        (Tlv.ContentType, metaInfo.getOtherTypeCode());
    else
      // We don't expect this to happen.
      throw new Error("unrecognized TLV ContentType");
  }

  encoder.writeTypeAndLength(Tlv.MetaInfo, encoder.getLength() - saveLength);
};

Tlv0_2WireFormat.decodeMetaInfo = function(metaInfo, decoder, copy)
{
  if (copy == null)
    copy = true;

  var endOffset = decoder.readNestedTlvsStart(Tlv.MetaInfo);

  var type = decoder.readOptionalNonNegativeIntegerTlv
    (Tlv.ContentType, endOffset);
  if (type == null || type < 0 || type === ContentType.BLOB)
    metaInfo.setType(ContentType.BLOB);
  else if (type === ContentType.LINK ||
           type === ContentType.KEY ||
           type === ContentType.NACK)
    // The ContentType enum is set up with the correct integer for each NDN-TLV
    // ContentType.
    metaInfo.setType(type);
  else {
    // Unrecognized content type.
    metaInfo.setType(ContentType.OTHER_CODE);
    metaInfo.setOtherTypeCode(type);
  }

  metaInfo.setFreshnessPeriod
    (decoder.readOptionalNonNegativeIntegerTlv(Tlv.FreshnessPeriod, endOffset));
  if (decoder.peekType(Tlv.FinalBlockId, endOffset)) {
    var finalBlockIdEndOffset = decoder.readNestedTlvsStart(Tlv.FinalBlockId);
    metaInfo.setFinalBlockId(Tlv0_2WireFormat.decodeNameComponent(decoder, copy));
    decoder.finishNestedTlvs(finalBlockIdEndOffset);
  }
  else
    metaInfo.setFinalBlockId(null);

  decoder.finishNestedTlvs(endOffset);
};

Tlv0_2WireFormat.encodeControlParameters = function(controlParameters, encoder)
{
  var saveLength = encoder.getLength();

  // Encode backwards.
  encoder.writeOptionalNonNegativeIntegerTlv
    (Tlv.ControlParameters_ExpirationPeriod,
     controlParameters.getExpirationPeriod());

  if (controlParameters.getStrategy().size() > 0){
    var strategySaveLength = encoder.getLength();
    Tlv0_2WireFormat.encodeName(controlParameters.getStrategy(), encoder);
    encoder.writeTypeAndLength(Tlv.ControlParameters_Strategy,
      encoder.getLength() - strategySaveLength);
  }

  var flags = controlParameters.getForwardingFlags().getNfdForwardingFlags();
  if (flags != new ForwardingFlags().getNfdForwardingFlags())
      // The flags are not the default value.
      encoder.writeNonNegativeIntegerTlv
        (Tlv.ControlParameters_Flags, flags);

  encoder.writeOptionalNonNegativeIntegerTlv
    (Tlv.ControlParameters_Cost, controlParameters.getCost());
  encoder.writeOptionalNonNegativeIntegerTlv
    (Tlv.ControlParameters_Origin, controlParameters.getOrigin());
  encoder.writeOptionalNonNegativeIntegerTlv
    (Tlv.ControlParameters_LocalControlFeature,
     controlParameters.getLocalControlFeature());

  if (controlParameters.getUri().length != 0)
    encoder.writeBlobTlv
      (Tlv.ControlParameters_Uri, new Blob(controlParameters.getUri()).buf());

  encoder.writeOptionalNonNegativeIntegerTlv
    (Tlv.ControlParameters_FaceId, controlParameters.getFaceId());
  if (controlParameters.getName() != null)
    Tlv0_2WireFormat.encodeName(controlParameters.getName(), encoder);

  encoder.writeTypeAndLength
    (Tlv.ControlParameters_ControlParameters, encoder.getLength() - saveLength);
};

Tlv0_2WireFormat.decodeControlParameters = function
  (controlParameters, decoder, copy)
{
  if (copy == null)
    copy = true;

  controlParameters.clear();
  var endOffset = decoder.
    readNestedTlvsStart(Tlv.ControlParameters_ControlParameters);

  // decode name
  if (decoder.peekType(Tlv.Name, endOffset)) {
    var name = new Name();
    Tlv0_2WireFormat.decodeName(name, decoder, copy);
    controlParameters.setName(name);
  }

  // decode face ID
  controlParameters.setFaceId(decoder.readOptionalNonNegativeIntegerTlv
    (Tlv.ControlParameters_FaceId, endOffset));

  // decode URI
  if (decoder.peekType(Tlv.ControlParameters_Uri, endOffset)) {
    // Set copy false since we just immediately get the string.
    var uri = new Blob
      (decoder.readOptionalBlobTlv(Tlv.ControlParameters_Uri, endOffset), false);
    controlParameters.setUri(uri.toString());
  }

  // decode integers
  controlParameters.setLocalControlFeature(decoder.
    readOptionalNonNegativeIntegerTlv(
      Tlv.ControlParameters_LocalControlFeature, endOffset));
  controlParameters.setOrigin(decoder.
    readOptionalNonNegativeIntegerTlv(Tlv.ControlParameters_Origin,
      endOffset));
  controlParameters.setCost(decoder.readOptionalNonNegativeIntegerTlv(
    Tlv.ControlParameters_Cost, endOffset));

  // set forwarding flags
  if (decoder.peekType(Tlv.ControlParameters_Flags, endOffset)) {
    var flags = new ForwardingFlags();
    flags.setNfdForwardingFlags(decoder.
      readNonNegativeIntegerTlv(Tlv.ControlParameters_Flags, endOffset));
    controlParameters.setForwardingFlags(flags);
  }

  // decode strategy
  if (decoder.peekType(Tlv.ControlParameters_Strategy, endOffset)) {
    var strategyEndOffset = decoder.readNestedTlvsStart(Tlv.ControlParameters_Strategy);
    Tlv0_2WireFormat.decodeName(controlParameters.getStrategy(), decoder, copy);
    decoder.finishNestedTlvs(strategyEndOffset);
  }

  // decode expiration period
  controlParameters.setExpirationPeriod(
    decoder.readOptionalNonNegativeIntegerTlv(
      Tlv.ControlParameters_ExpirationPeriod, endOffset));

  decoder.finishNestedTlvs(endOffset);
};
/**
 * Copyright (C) 2013-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var Tlv0_2WireFormat = require('./tlv-0_2-wire-format.js').Tlv0_2WireFormat;

/**
 * A Tlv0_1_1WireFormat extends Tlv0_2WireFormat so that it is an alias in case
 * any applications use Tlv0_1_1WireFormat directly.  These two wire formats are
 * the same except that Tlv0_2WireFormat adds support for the name component
 * type ImplicitSha256Digest.
 * @constructor
 */
var Tlv0_1_1WireFormat = function Tlv0_1_1WireFormat()
{
  // Inherit from Tlv0_2WireFormat.
  Tlv0_2WireFormat.call(this);
};

Tlv0_1_1WireFormat.prototype = new Tlv0_2WireFormat();
Tlv0_1_1WireFormat.prototype.name = "Tlv0_1_1WireFormat";

exports.Tlv0_1_1WireFormat = Tlv0_1_1WireFormat;

// Default object.
Tlv0_1_1WireFormat.instance = null;

/**
 * Get a singleton instance of a Tlv0_1_1WireFormat.
 * @return {Tlv0_1_1WireFormat} The singleton instance.
 */
Tlv0_1_1WireFormat.get = function()
{
  if (Tlv0_1_1WireFormat.instance === null)
    Tlv0_1_1WireFormat.instance = new Tlv0_1_1WireFormat();
  return Tlv0_1_1WireFormat.instance;
};
/**
 * Copyright (C) 2013-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var WireFormat = require('./wire-format.js').WireFormat; /** @ignore */
var Tlv0_1_1WireFormat = require('./tlv-0_1_1-wire-format.js').Tlv0_1_1WireFormat;

/**
 * A Tlv0_1WireFormat extends Tlv0_1_1WireFormat so that it is an alias in case
 * any applications use Tlv0_1WireFormat directly.  These two wire formats are
 * the same except that Tlv0_1_1WireFormat adds support for
 * Sha256WithEcdsaSignature.
 * @constructor
 */
var Tlv0_1WireFormat = function Tlv0_1WireFormat()
{
  // Inherit from Tlv0_1_1WireFormat.
  Tlv0_1_1WireFormat.call(this);
};

Tlv0_1WireFormat.prototype = new Tlv0_1_1WireFormat();
Tlv0_1WireFormat.prototype.name = "Tlv0_1WireFormat";

exports.Tlv0_1WireFormat = Tlv0_1WireFormat;

// Default object.
Tlv0_1WireFormat.instance = null;

/**
 * Get a singleton instance of a Tlv0_1WireFormat.
 * @return {Tlv0_1WireFormat} The singleton instance.
 */
Tlv0_1WireFormat.get = function()
{
  if (Tlv0_1WireFormat.instance === null)
    Tlv0_1WireFormat.instance = new Tlv0_1WireFormat();
  return Tlv0_1WireFormat.instance;
};
/**
 * Copyright (C) 2013-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var WireFormat = require('./wire-format.js').WireFormat; /** @ignore */
var Tlv0_2WireFormat = require('./tlv-0_2-wire-format.js').Tlv0_2WireFormat;

/**
 * A TlvWireFormat extends WireFormat to override its methods to
 * implement encoding and decoding using the preferred implementation of NDN-TLV.
 * @constructor
 */
var TlvWireFormat = function TlvWireFormat()
{
  // Inherit from Tlv0_2WireFormat.
  Tlv0_2WireFormat.call(this);
};

TlvWireFormat.prototype = new Tlv0_2WireFormat();
TlvWireFormat.prototype.name = "TlvWireFormat";

exports.TlvWireFormat = TlvWireFormat;

// Default object.
TlvWireFormat.instance = null;

/**
 * Get a singleton instance of a TlvWireFormat.  Assuming that the default
 * wire format was set with WireFormat.setDefaultWireFormat(TlvWireFormat.get()),
 * you can check if this is the default wire encoding with
 * if WireFormat.getDefaultWireFormat() == TlvWireFormat.get().
 * @return {TlvWireFormat} The singleton instance.
 */
TlvWireFormat.get = function()
{
  if (TlvWireFormat.instance === null)
    TlvWireFormat.instance = new TlvWireFormat();
  return TlvWireFormat.instance;
};

// On loading this module, make this the default wire format.
// This module will be loaded because WireFormat loads it.
WireFormat.setDefaultWireFormat(TlvWireFormat.get());
/**
 * This file contains utilities to help encode and decode NDN objects.
 * Copyright (C) 2013-2016 Regents of the University of California.
 * author: Meki Cheraoui
 *
 * 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.
 */

/** @ignore */
var DataUtils = require('./data-utils.js').DataUtils; /** @ignore */
var KeyLocatorType = require('../key-locator.js').KeyLocatorType; /** @ignore */
var Interest = require('../interest.js').Interest; /** @ignore */
var Data = require('../data.js').Data; /** @ignore */
var Sha256WithRsaSignature = require('../sha256-with-rsa-signature.js').Sha256WithRsaSignature; /** @ignore */
var Sha256WithEcdsaSignature = require('../sha256-with-ecdsa-signature.js').Sha256WithEcdsaSignature; /** @ignore */
var HmacWithSha256Signature = require('../hmac-with-sha256-signature.js').HmacWithSha256Signature; /** @ignore */
var DigestSha256Signature = require('../digest-sha256-signature.js').DigestSha256Signature; /** @ignore */
var ContentType = require('../meta-info.js').ContentType; /** @ignore */
var WireFormat = require('./wire-format.js').WireFormat;

/**
 * An EncodingUtils has static methods for encoding data.
 * @constructor
 */
var EncodingUtils = function EncodingUtils()
{
};

exports.EncodingUtils = EncodingUtils;

EncodingUtils.encodeToHexInterest = function(interest, wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
  return DataUtils.toHex(interest.wireEncode(wireFormat).buf());
};

EncodingUtils.encodeToHexData = function(data, wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
  return DataUtils.toHex(data.wireEncode(wireFormat).buf());
};

EncodingUtils.decodeHexInterest = function(input, wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
  var interest = new Interest();
  interest.wireDecode(DataUtils.toNumbers(input), wireFormat);
  return interest;
};

EncodingUtils.decodeHexData = function(input, wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
  var data = new Data();
  data.wireDecode(DataUtils.toNumbers(input), wireFormat);
  return data;
};

/**
 * Decode the Buffer array which holds SubjectPublicKeyInfo and return an RSAKey.
 */
EncodingUtils.decodeSubjectPublicKeyInfo = function(array)
{
  var hex = DataUtils.toHex(array).toLowerCase();
  var a = _x509_getPublicKeyHexArrayFromCertHex(hex, _x509_getSubjectPublicKeyPosFromCertHex(hex, 0));
  var rsaKey = new RSAKey();
  rsaKey.setPublic(a[0], a[1]);
  return rsaKey;
}

/**
 * Return a user friendly HTML string with the contents of data.
 */
EncodingUtils.dataToHtml = function(/* Data */ data)
{
  if (data == -1)
    return "NO CONTENT FOUND";
  if (data == -2)
    return "CONTENT NAME IS EMPTY";

  var output = "";
  function append(message) {
    message = message.replace(/&/g, "&amp;");
    message = message.replace(/</g, "&lt;");

    output += message;
    output += "<br/>";
  }

  // Imitate dumpData in examples/node/test-encode-decode-data.js

  append("name: " + data.getName().toUri());
  if (data.getContent().size() > 0) {
    append("content (raw): " + data.getContent().buf().toString('binary'));
    append("content (hex): " + data.getContent().toHex());
  }
  else
    append("content: <empty>");

  if (!(data.getMetaInfo().getType() == ContentType.BLOB)) {
    if (data.getMetaInfo().getType() == ContentType.KEY)
      append("metaInfo.type: KEY");
    else if (data.getMetaInfo().getType() == ContentType.LINK)
      append("metaInfo.type: LINK");
    else if (data.getMetaInfo().getType() == ContentType.NACK)
      append("metaInfo.type: NACK");
    else if (data.getMetaInfo().getType() == ContentType.OTHER_CODE)
      append("metaInfo.type: other code " + data.getMetaInfo().getOtherTypeCode());
  }
  append("metaInfo.freshnessPeriod (milliseconds): " +
    (data.getMetaInfo().getFreshnessPeriod() >= 0 ?
      "" + data.getMetaInfo().getFreshnessPeriod() : "<none>"));
  append("metaInfo.finalBlockId: " +
    (data.getMetaInfo().getFinalBlockId().getValue().size() > 0 ?
     data.getMetaInfo().getFinalBlockId().getValue().toHex() : "<none>"));

  var keyLocator = null;
  var signature = data.getSignature();
  if (signature instanceof Sha256WithRsaSignature) {
    var signature = data.getSignature();
    append("Sha256WithRsa signature.signature: " +
      (signature.getSignature().size() > 0 ?
       signature.getSignature().toHex() : "<none>"));
    keyLocator = signature.getKeyLocator();
  }
  else if (signature instanceof Sha256WithEcdsaSignature) {
    var signature = data.getSignature();
    append("Sha256WithEcdsa signature.signature: " +
      (signature.getSignature().size() > 0 ?
       signature.getSignature().toHex() : "<none>"));
    keyLocator = signature.getKeyLocator();
  }
  else if (signature instanceof HmacWithSha256Signature) {
    var signature = data.getSignature();
    append("HmacWithSha256 signature.signature: " +
      (signature.getSignature().size() > 0 ?
       signature.getSignature().toHex() : "<none>"));
    keyLocator = signature.getKeyLocator();
  }
  else if (signature instanceof DigestSha256Signature) {
    var signature = data.getSignature();
    append("DigestSha256 signature.signature: " +
      (signature.getSignature().size() > 0 ?
       signature.getSignature().toHex() : "<none>"));
  }
  if (keyLocator !== null) {
    if (keyLocator.getType() == null)
      append("signature.keyLocator: <none>");
    else if (keyLocator.getType() == KeyLocatorType.KEY_LOCATOR_DIGEST)
      append("signature.keyLocator: KeyLocatorDigest: " + keyLocator.getKeyData().toHex());
    else if (keyLocator.getType() == KeyLocatorType.KEYNAME)
      append("signature.keyLocator: KeyName: " + keyLocator.getKeyName().toUri());
    else
      append("signature.keyLocator: <unrecognized ndn_KeyLocatorType>");
  }

  return output;
};

//
// Deprecated: For the browser, define these in the global scope.  Applications should access as member of EncodingUtils.
//

var encodeToHexInterest = function(interest) { return EncodingUtils.encodeToHexInterest(interest); }
var decodeHexInterest = function(input) { return EncodingUtils.decodeHexInterest(input); }
var decodeSubjectPublicKeyInfo = function(input) { return EncodingUtils.decodeSubjectPublicKeyInfo(input); }

/**
 * @deprecated Use interest.wireEncode().
 */
function encodeToBinaryInterest(interest) { return interest.wireEncode().buf(); }
/**
 * Copyright (C) 2015-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * @author: From ndn-group-encrypt src/algo/aes https://github.com/named-data/ndn-group-encrypt
 *
 * 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.
 */

// (This is ported from ndn::gep::algo::Aes, and named AesAlgorithm because
// "Aes" is very short and not all the Common Client Libraries have namespaces.)

/** @ignore */
var Crypto = require('../../crypto.js'); /** @ignore */
var Blob = require('../../util/blob.js').Blob; /** @ignore */
var DecryptKey = require('../decrypt-key.js').DecryptKey; /** @ignore */
var EncryptKey = require('../encrypt-key.js').EncryptKey; /** @ignore */
var EncryptAlgorithmType = require('./encrypt-params.js').EncryptAlgorithmType; /** @ignore */
var UseSubtleCrypto = require('../../use-subtle-crypto-node.js').UseSubtleCrypto; /** @ignore */
var SyncPromise = require('../../util/sync-promise.js').SyncPromise;

/**
 * The AesAlgorithm class provides static methods to manipulate keys, encrypt
 * and decrypt using the AES symmetric key cipher.
 * @note This class is an experimental feature. The API may change.
 * @constructor
 */
var AesAlgorithm = function AesAlgorithm()
{
};

exports.AesAlgorithm = AesAlgorithm;

/**
 * Generate a new random decrypt key for AES based on the given params.
 * @param {AesKeyParams} params The key params with the key size (in bits).
 * @return {DecryptKey} The new decrypt key.
 */
AesAlgorithm.generateKey = function(params)
{
  // Convert the key bit size to bytes.
  var key = Crypto.randomBytes(params.getKeySize() / 8);

  var decryptKey = new DecryptKey(new Blob(key, false));
  return decryptKey;
};

/**
 * Derive a new encrypt key from the given decrypt key value.
 * @param {Blob} keyBits The key value of the decrypt key.
 * @return {EncryptKey} The new encrypt key.
 */
AesAlgorithm.deriveEncryptKey = function(keyBits)
{
  return new EncryptKey(keyBits);
};

/**
 * Decrypt the encryptedData using the keyBits according the encrypt params.
 * @param {Blob} keyBits The key value.
 * @param {Blob} encryptedData The data to decrypt.
 * @param {EncryptParams} params This decrypts according to
 * params.getAlgorithmType() and other params as needed such as
 * params.getInitialVector().
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which returns the decrypted Blob.
 */
AesAlgorithm.decryptPromise = function(keyBits, encryptedData, params, useSync)
{
  if (UseSubtleCrypto() && !useSync &&
      // Crypto.subtle doesn't implement ECB.
      params.getAlgorithmType() != EncryptAlgorithmType.AesEcb) {
    if (params.getAlgorithmType() == EncryptAlgorithmType.AesCbc) {
      return crypto.subtle.importKey
        ("raw", keyBits.buf(), { name: "AES-CBC" }, false,
         ["encrypt", "decrypt"])
      .then(function(key) {
        return crypto.subtle.decrypt
          ({ name: "AES-CBC", iv: params.getInitialVector().buf() },
           key, encryptedData.buf());
      })
      .then(function(result) {
        return Promise.resolve(new Blob(new Uint8Array(result), false));
      });
    }
    else
      return Promise.reject(new Error("unsupported encryption mode"));
  }
  else {
    if (params.getAlgorithmType() == EncryptAlgorithmType.AesEcb) {
      try {
        // ECB ignores the initial vector.
        var cipher = Crypto.createDecipheriv("aes-128-ecb", keyBits.buf(), "");
        return SyncPromise.resolve(new Blob
          (Buffer.concat([cipher.update(encryptedData.buf()), cipher.final()]),
           false));
      } catch (err) {
        return SyncPromise.reject(err);
      }
    }
    else if (params.getAlgorithmType() == EncryptAlgorithmType.AesCbc) {
      try {
        var cipher = Crypto.createDecipheriv
          ("aes-128-cbc", keyBits.buf(), params.getInitialVector().buf());
        return SyncPromise.resolve(new Blob
          (Buffer.concat([cipher.update(encryptedData.buf()), cipher.final()]),
           false));
      } catch (err) {
        return SyncPromise.reject(err);
      }
    }
    else
      return SyncPromise.reject(new Error("unsupported encryption mode"));
  }
};

/**
 * Decrypt the encryptedData using the keyBits according the encrypt params.
 * @param {Blob} keyBits The key value.
 * @param {Blob} encryptedData The data to decrypt.
 * @param {EncryptParams} params This decrypts according to
 * params.getAlgorithmType() and other params as needed such as
 * params.getInitialVector().
 * @return {Blob} The decrypted data.
 * @throws Error If decryptPromise doesn't return a SyncPromise which is
 * already fulfilled.
 */
AesAlgorithm.decrypt = function(keyBits, encryptedData, params)
{
  return SyncPromise.getValue(this.decryptPromise
    (keyBits, encryptedData, params, true));
};

/**
 * Encrypt the plainData using the keyBits according the encrypt params.
 * @param {Blob} keyBits The key value.
 * @param {Blob} plainData The data to encrypt.
 * @param {EncryptParams} params This encrypts according to
 * params.getAlgorithmType() and other params as needed such as
 * params.getInitialVector().
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which returns the encrypted Blob.
 */
AesAlgorithm.encryptPromise = function(keyBits, plainData, params, useSync)
{
  if (params.getAlgorithmType() == EncryptAlgorithmType.AesCbc) {
    if (params.getInitialVector().size() != AesAlgorithm.BLOCK_SIZE)
      return SyncPromise.reject(new Error("incorrect initial vector size"));
  }

  if (UseSubtleCrypto() && !useSync &&
      // Crypto.subtle doesn't implement ECB.
      params.getAlgorithmType() != EncryptAlgorithmType.AesEcb) {
    if (params.getAlgorithmType() == EncryptAlgorithmType.AesCbc) {
      return crypto.subtle.importKey
        ("raw", keyBits.buf(), { name: "AES-CBC" }, false,
         ["encrypt", "decrypt"])
      .then(function(key) {
        return crypto.subtle.encrypt
          ({ name: "AES-CBC", iv: params.getInitialVector().buf() },
           key, plainData.buf());
      })
      .then(function(result) {
        return Promise.resolve(new Blob(new Uint8Array(result), false));
      });
    }
    else
      return Promise.reject(new Error("unsupported encryption mode"));
  }
  else {
    if (params.getAlgorithmType() == EncryptAlgorithmType.AesEcb) {
      // ECB ignores the initial vector.
      var cipher = Crypto.createCipheriv("aes-128-ecb", keyBits.buf(), "");
      return SyncPromise.resolve(new Blob
        (Buffer.concat([cipher.update(plainData.buf()), cipher.final()]),
         false));
    }
    else if (params.getAlgorithmType() == EncryptAlgorithmType.AesCbc) {
      var cipher = Crypto.createCipheriv
        ("aes-128-cbc", keyBits.buf(), params.getInitialVector().buf());
      return SyncPromise.resolve(new Blob
        (Buffer.concat([cipher.update(plainData.buf()), cipher.final()]),
         false));
    }
    else
      return SyncPromise.reject(new Error("unsupported encryption mode"));
  }
};

/**
 * Encrypt the plainData using the keyBits according the encrypt params.
 * @param {Blob} keyBits The key value.
 * @param {Blob} plainData The data to encrypt.
 * @param {EncryptParams} params This encrypts according to
 * params.getAlgorithmType() and other params as needed such as
 * params.getInitialVector().
 * @return {Blob} The encrypted data.
 * @throws Error If encryptPromise doesn't return a SyncPromise which is
 * already fulfilled.
 */
AesAlgorithm.encrypt = function(keyBits, plainData, params)
{
  return SyncPromise.getValue(this.encryptPromise
    (keyBits, plainData, params, true));
};

AesAlgorithm.BLOCK_SIZE = 16;
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * @author: From ndn-group-encrypt src/encrypt-params https://github.com/named-data/ndn-group-encrypt
 *
 * 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.
 */

/** @ignore */
var Crypto = require('../../crypto.js'); /** @ignore */
var Blob = require('../../util/blob.js').Blob;

var EncryptAlgorithmType = function EncryptAlgorithmType()
{
}

exports.EncryptAlgorithmType = EncryptAlgorithmType;

// These correspond to the TLV codes.
EncryptAlgorithmType.AesEcb = 0;
EncryptAlgorithmType.AesCbc = 1;
EncryptAlgorithmType.RsaPkcs = 2;
EncryptAlgorithmType.RsaOaep = 3;

/**
 * An EncryptParams holds an algorithm type and other parameters used to
 * encrypt and decrypt. Create an EncryptParams with the given parameters.
 * @param {number} algorithmType The algorithm type from EncryptAlgorithmType,
 * or null if not specified.
 * @param {number} initialVectorLength (optional) The initial vector length, or
 * 0 if the initial vector is not specified. If ommitted, the initial vector is
 * not specified.
 * @note This class is an experimental feature. The API may change.
 * @constructor
 */
var EncryptParams = function EncryptParams(algorithmType, initialVectorLength)
{
  this.algorithmType_ = algorithmType;

  if (initialVectorLength != null && initialVectorLength > 0) {
    var initialVector = Crypto.randomBytes(initialVectorLength);
    this.initialVector_ = new Blob(initialVector, false);
  }
  else
    this.initialVector_ = new Blob();
};

exports.EncryptParams = EncryptParams;

/**
 * Get the algorithmType.
 * @return {number} The algorithm type from EncryptAlgorithmType, or null if not
 * specified.
 */
EncryptParams.prototype.getAlgorithmType = function()
{
  return this.algorithmType_;
};

/**
 * Get the initial vector.
 * @return {Blob} The initial vector. If not specified, isNull() is true.
 */
EncryptParams.prototype.getInitialVector = function()
{
  return this.initialVector_;
};

/**
 * Set the algorithm type.
 * @param {number} algorithmType The algorithm type from EncryptAlgorithmType.
 * If not specified, set to null.
 * @return {EncryptParams} This EncryptParams so that you can chain calls to
 * update values.
 */
EncryptParams.prototype.setAlgorithmType = function(algorithmType)
{
  this.algorithmType_ = algorithmType;
  return this;
};

/**
 * Set the initial vector.
 * @param {Blob} initialVector The initial vector. If not specified, set to the
 * default Blob() where isNull() is true.
 * @return {EncryptParams} This EncryptParams so that you can chain calls to
 * update values.
 */
EncryptParams.prototype.setInitialVector = function(initialVector)
{
  this.initialVector_ =
      typeof initialVector === 'object' && initialVector instanceof Blob ?
    initialVector : new Blob(initialVector);
  return this;
};
/**
 * Copyright (C) 2015-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * @author: From ndn-group-encrypt src/encryptor https://github.com/named-data/ndn-group-encrypt
 *
 * 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.
 */

/** @ignore */
var Crypto = require('../../crypto.js'); /** @ignore */
var Name = require('../../name.js').Name; /** @ignore */
var KeyLocator = require('../../key-locator.js').KeyLocator; /** @ignore */
var KeyLocatorType = require('../../key-locator.js').KeyLocatorType; /** @ignore */
var TlvWireFormat = require('../../encoding/tlv-wire-format.js').TlvWireFormat; /** @ignore */
var Blob = require('../../util/blob.js').Blob; /** @ignore */
var AesAlgorithm = require('./aes-algorithm.js').AesAlgorithm; /** @ignore */
var RsaAlgorithm = require('./rsa-algorithm.js').RsaAlgorithm; /** @ignore */
var EncryptParams = require('./encrypt-params.js').EncryptParams; /** @ignore */
var EncryptAlgorithmType = require('./encrypt-params.js').EncryptAlgorithmType; /** @ignore */
var EncryptedContent = require('../encrypted-content.js').EncryptedContent; /** @ignore */
var SyncPromise = require('../../util/sync-promise.js').SyncPromise;

/**
 * Encryptor has static constants and utility methods for encryption, such as
 * encryptData.
 * @constructor
 */
var Encryptor = function Encryptor(value)
{
};

exports.Encryptor = Encryptor;

Encryptor.NAME_COMPONENT_FOR = new Name.Component("FOR");
Encryptor.NAME_COMPONENT_READ = new Name.Component("READ");
Encryptor.NAME_COMPONENT_SAMPLE = new Name.Component("SAMPLE");
Encryptor.NAME_COMPONENT_ACCESS = new Name.Component("ACCESS");
Encryptor.NAME_COMPONENT_E_KEY = new Name.Component("E-KEY");
Encryptor.NAME_COMPONENT_D_KEY = new Name.Component("D-KEY");
Encryptor.NAME_COMPONENT_C_KEY = new Name.Component("C-KEY");

/**
 * Prepare an encrypted data packet by encrypting the payload using the key
 * according to the params. In addition, this prepares the encoded
 * EncryptedContent with the encryption result using keyName and params. The
 * encoding is set as the content of the data packet. If params defines an
 * asymmetric encryption algorithm and the payload is larger than the maximum
 * plaintext size, this encrypts the payload with a symmetric key that is
 * asymmetrically encrypted and provided as a nonce in the content of the data
 * packet. The packet's /<dataName>/ is updated to be <dataName>/FOR/<keyName>.
 * @param {Data} data The data packet which is updated.
 * @param {Blob} payload The payload to encrypt.
 * @param {Name} keyName The key name for the EncryptedContent.
 * @param {Blob} key The encryption key value.
 * @param {EncryptParams} params The parameters for encryption.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which fulfills when the data packet
 * is updated.
 */
Encryptor.encryptDataPromise = function
  (data, payload, keyName, key, params, useSync)
{
  data.getName().append(Encryptor.NAME_COMPONENT_FOR).append(keyName);

  var algorithmType = params.getAlgorithmType();

  if (algorithmType == EncryptAlgorithmType.AesCbc ||
      algorithmType == EncryptAlgorithmType.AesEcb) {
    return Encryptor.encryptSymmetricPromise_
      (payload, key, keyName, params, useSync)
    .then(function(content) {
      data.setContent(content.wireEncode(TlvWireFormat.get()));
      return SyncPromise.resolve();
    });
  }
  else if (algorithmType == EncryptAlgorithmType.RsaPkcs ||
           algorithmType == EncryptAlgorithmType.RsaOaep) {
    // Node.js doesn't have a direct way to get the maximum plain text size, so
    // try to encrypt the payload first and catch the error if it is too big.
    return Encryptor.encryptAsymmetricPromise_
      (payload, key, keyName, params, useSync)
    .then(function(content) {
      data.setContent(content.wireEncode(TlvWireFormat.get()));
      return SyncPromise.resolve();
    }, function(err) {
      if (err.message.indexOf("data too large for key size") < 0)
        // Not the expected error.
        throw err;

      // The payload is larger than the maximum plaintext size.
      // 128-bit nonce.
      var nonceKeyBuffer = Crypto.randomBytes(16);
      var nonceKey = new Blob(nonceKeyBuffer, false);

      var nonceKeyName = new Name(keyName);
      nonceKeyName.append("nonce");

      var symmetricParams = new EncryptParams
        (EncryptAlgorithmType.AesCbc, AesAlgorithm.BLOCK_SIZE);

      var nonceContent;
      return Encryptor.encryptSymmetricPromise_
        (payload, nonceKey, nonceKeyName, symmetricParams, useSync)
      .then(function(localNonceContent) {
        nonceContent = localNonceContent;
        return Encryptor.encryptAsymmetricPromise_
          (nonceKey, key, keyName, params, useSync);
      })
      .then(function(payloadContent) {
        var nonceContentEncoding = nonceContent.wireEncode();
        var payloadContentEncoding = payloadContent.wireEncode();
        var content = new Buffer
          (nonceContentEncoding.size() + payloadContentEncoding.size());
        payloadContentEncoding.buf().copy(content, 0);
        nonceContentEncoding.buf().copy(content, payloadContentEncoding.size());

        data.setContent(new Blob(content, false));
        return SyncPromise.resolve();
      });
    });
  }
  else
    return SyncPromise.reject(new Error("Unsupported encryption method"));
};

/**
 * Prepare an encrypted data packet by encrypting the payload using the key
 * according to the params. In addition, this prepares the encoded
 * EncryptedContent with the encryption result using keyName and params. The
 * encoding is set as the content of the data packet. If params defines an
 * asymmetric encryption algorithm and the payload is larger than the maximum
 * plaintext size, this encrypts the payload with a symmetric key that is
 * asymmetrically encrypted and provided as a nonce in the content of the data
 * packet.
 * @param {Data} data The data packet which is updated.
 * @param {Blob} payload The payload to encrypt.
 * @param {Name} keyName The key name for the EncryptedContent.
 * @param {Blob} key The encryption key value.
 * @param {EncryptParams} params The parameters for encryption.
 * @throws Error If encryptPromise doesn't return a SyncPromise which is
 * already fulfilled.
 */
Encryptor.encryptData = function(data, payload, keyName, key, params)
{
  return SyncPromise.getValue(Encryptor.encryptDataPromise
    (data, payload, keyName, key, params, true));
};

/**
 * Encrypt the payload using the symmetric key according to params, and return
 * an EncryptedContent.
 * @param {Blob} payload The data to encrypt.
 * @param {Blob} key The key value.
 * @param {Name} keyName The key name for the EncryptedContent key locator.
 * @param {EncryptParams} params The parameters for encryption.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which returns a new EncryptedContent.
 */
Encryptor.encryptSymmetricPromise_ = function
  (payload, key, keyName, params, useSync)
{
  var algorithmType = params.getAlgorithmType();
  var initialVector = params.getInitialVector();
  var keyLocator = new KeyLocator();
  keyLocator.setType(KeyLocatorType.KEYNAME);
  keyLocator.setKeyName(keyName);

  if (algorithmType == EncryptAlgorithmType.AesCbc ||
      algorithmType == EncryptAlgorithmType.AesEcb) {
    if (algorithmType == EncryptAlgorithmType.AesCbc) {
      if (initialVector.size() != AesAlgorithm.BLOCK_SIZE)
        return SyncPromise.reject(new Error("incorrect initial vector size"));
    }

    return AesAlgorithm.encryptPromise(key, payload, params, useSync)
    .then(function(encryptedPayload) {
      var result = new EncryptedContent();
      result.setAlgorithmType(algorithmType);
      result.setKeyLocator(keyLocator);
      result.setPayload(encryptedPayload);
      result.setInitialVector(initialVector);
      return SyncPromise.resolve(result);
    });
  }
  else
    return SyncPromise.reject(new Error("Unsupported encryption method"));
};

/**
 * Encrypt the payload using the asymmetric key according to params, and
 * return an EncryptedContent.
 * @param {Blob} payload The data to encrypt. The size should be within range of
 * the key.
 * @param {Blob} key The key value.
 * @param {Name} keyName The key name for the EncryptedContent key locator.
 * @param {EncryptParams} params The parameters for encryption.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which returns a new EncryptedContent.
 */
Encryptor.encryptAsymmetricPromise_ = function
  (payload, key, keyName, params, useSync)
{
  var algorithmType = params.getAlgorithmType();
  var keyLocator = new KeyLocator();
  keyLocator.setType(KeyLocatorType.KEYNAME);
  keyLocator.setKeyName(keyName);

  if (algorithmType == EncryptAlgorithmType.RsaPkcs ||
      algorithmType == EncryptAlgorithmType.RsaOaep) {
    return RsaAlgorithm.encryptPromise(key, payload, params, useSync)
    .then(function(encryptedPayload) {
      var result = new EncryptedContent();
      result.setAlgorithmType(algorithmType);
      result.setKeyLocator(keyLocator);
      result.setPayload(encryptedPayload);
      return SyncPromise.resolve(result);
    });
  }
  else
    return SyncPromise.reject(new Error("Unsupported encryption method"));
};
/**
 * Copyright (C) 2015-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * @author: From ndn-group-encrypt src/algo/rsa https://github.com/named-data/ndn-group-encrypt
 *
 * 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.
 */

// (This is ported from ndn::gep::algo::Rsa, and named RsaAlgorithm because
// "Rsa" is very short and not all the Common Client Libraries have namespaces.)

/** @ignore */
var constants = require('constants'); /** @ignore */
var Crypto = require('../../crypto.js'); /** @ignore */
var Blob = require('../../util/blob.js').Blob; /** @ignore */
var DecryptKey = require('../decrypt-key.js').DecryptKey; /** @ignore */
var EncryptKey = require('../encrypt-key.js').EncryptKey; /** @ignore */
var EncryptAlgorithmType = require('./encrypt-params.js').EncryptAlgorithmType; /** @ignore */
var DerNode = require('../../encoding/der/der-node.js').DerNode; /** @ignore */
var OID = require('../../encoding/oid.js').OID; /** @ignore */
var PrivateKeyStorage = require('../../security/identity/private-key-storage.js').PrivateKeyStorage; /** @ignore */
var UseSubtleCrypto = require('../../use-subtle-crypto-node.js').UseSubtleCrypto; /** @ignore */
var SyncPromise = require('../../util/sync-promise.js').SyncPromise; /** @ignore */
var rsaKeygen = null;
try {
  // This should be installed with: sudo npm install rsa-keygen
  rsaKeygen = require('rsa-keygen');
}
catch (e) {}

/**
 * The RsaAlgorithm class provides static methods to manipulate keys, encrypt
 * and decrypt using RSA.
 * @note This class is an experimental feature. The API may change.
 * @constructor
 */
var RsaAlgorithm = function RsaAlgorithm()
{
};

exports.RsaAlgorithm = RsaAlgorithm;

/**
 * Generate a new random decrypt key for RSA based on the given params.
 * @param {RsaKeyParams} params The key params with the key size (in bits).
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which returns the new DecryptKey
 * (containing a PKCS8-encoded private key).
 */
RsaAlgorithm.generateKeyPromise = function(params, useSync)
{
  if (UseSubtleCrypto() && !useSync) {
    return crypto.subtle.generateKey
      ({ name: "RSASSA-PKCS1-v1_5", modulusLength: params.getKeySize(),
         publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
         hash: {name: "SHA-256"} },
       true, ["sign", "verify"])
    .then(function(key) {
      // Export the private key to DER.
      return crypto.subtle.exportKey("pkcs8", key.privateKey);
    })
    .then(function(pkcs8Der) {
      return Promise.resolve(new DecryptKey
        (new Blob(new Uint8Array(pkcs8Der), false)));
    });
  }
  else {
    if (!rsaKeygen)
      return SyncPromise.reject(new Error
        ("Need to install rsa-keygen: sudo npm install rsa-keygen"));

    try {
      var keyPair = rsaKeygen.generate(params.getKeySize());
      // Get the PKCS1 private key DER from the PEM string and encode as PKCS8.
      var privateKeyBase64 = keyPair.private_key.toString().replace
        ("-----BEGIN RSA PRIVATE KEY-----", "").replace
        ("-----END RSA PRIVATE KEY-----", "");
      var pkcs1PrivateKeyDer = new Buffer(privateKeyBase64, 'base64');
      var privateKey = PrivateKeyStorage.encodePkcs8PrivateKey
        (pkcs1PrivateKeyDer, new OID(PrivateKeyStorage.RSA_ENCRYPTION_OID),
         new DerNode.DerNull()).buf();

      return SyncPromise.resolve(new DecryptKey(privateKey));
    } catch (err) {
      return SyncPromise.reject(err);
    }
  }
};

/**
 * Generate a new random decrypt key for RSA based on the given params.
 * @param {RsaKeyParams} params The key params with the key size (in bits).
 * @return {DecryptKey} The new decrypt key (containing a PKCS8-encoded private
 * key).
 * @throws Error If generateKeyPromise doesn't return a SyncPromise which is
 * already fulfilled.
 */
RsaAlgorithm.generateKey = function(params)
{
  return SyncPromise.getValue(this.generateKeyPromise(params, true));
};

/**
 * Derive a new encrypt key from the given decrypt key value.
 * @param {Blob} keyBits The key value of the decrypt key (PKCS8-encoded private
 * key).
 * @return {EncryptKey} The new encrypt key (DER-encoded public key).
 */
RsaAlgorithm.deriveEncryptKey = function(keyBits)
{
  var rsaPrivateKeyDer = RsaAlgorithm.getRsaPrivateKeyDer(keyBits);

  // Decode the PKCS #1 RSAPrivateKey.
  var parsedNode = DerNode.parse(rsaPrivateKeyDer.buf(), 0);
  var rsaPrivateKeyChildren = parsedNode.getChildren();
  var modulus = rsaPrivateKeyChildren[1];
  var publicExponent = rsaPrivateKeyChildren[2];

  // Encode the PKCS #1 RSAPublicKey.
  var rsaPublicKey = new DerNode.DerSequence();
  rsaPublicKey.addChild(modulus);
  rsaPublicKey.addChild(publicExponent);
  var rsaPublicKeyDer = rsaPublicKey.encode();

  // Encode the SubjectPublicKeyInfo.
  var algorithmIdentifier = new DerNode.DerSequence();
  algorithmIdentifier.addChild(new DerNode.DerOid(new OID
    (PrivateKeyStorage.RSA_ENCRYPTION_OID)));
  algorithmIdentifier.addChild(new DerNode.DerNull());
  var publicKey = new DerNode.DerSequence();
  publicKey.addChild(algorithmIdentifier);
  publicKey.addChild(new DerNode.DerBitString(rsaPublicKeyDer.buf(), 0));

  return new EncryptKey(publicKey.encode());
};

/**
 * Decrypt the encryptedData using the keyBits according the encrypt params.
 * @param {Blob} keyBits The key value (PKCS8-encoded private key).
 * @param {Blob} encryptedData The data to decrypt.
 * @param {EncryptParams} params This decrypts according to
 * params.getAlgorithmType().
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which returns the decrypted Blob.
 */
RsaAlgorithm.decryptPromise = function(keyBits, encryptedData, params, useSync)
{
  if (UseSubtleCrypto() && !useSync &&
      // Crypto.subtle doesn't implement PKCS1 padding.
      params.getAlgorithmType() != EncryptAlgorithmType.RsaPkcs) {
    if (params.getAlgorithmType() == EncryptAlgorithmType.RsaOaep) {
      return crypto.subtle.importKey
        ("pkcs8", keyBits.buf(), { name: "RSA-OAEP", hash: {name: "SHA-1"} },
         false, ["decrypt"])
      .then(function(privateKey) {
        return crypto.subtle.decrypt
          ({ name: "RSA-OAEP" }, privateKey, encryptedData.buf());
      })
      .then(function(result) {
        return Promise.resolve(new Blob(new Uint8Array(result), false));
      });
    }
    else
      return Promise.reject(new Error("unsupported padding scheme"));
  }
  else {
    // keyBits is PKCS #8 but we need the inner RSAPrivateKey.
    var rsaPrivateKeyDer = RsaAlgorithm.getRsaPrivateKeyDer(keyBits);

    // Encode the key DER as a PEM private key as needed by Crypto.
    var keyBase64 = rsaPrivateKeyDer.buf().toString('base64');
    var keyPem = "-----BEGIN RSA PRIVATE KEY-----\n";
    for (var i = 0; i < keyBase64.length; i += 64)
      keyPem += (keyBase64.substr(i, 64) + "\n");
    keyPem += "-----END RSA PRIVATE KEY-----";

    var padding;
    if (params.getAlgorithmType() == EncryptAlgorithmType.RsaPkcs)
      padding = constants.RSA_PKCS1_PADDING;
    else if (params.getAlgorithmType() == EncryptAlgorithmType.RsaOaep)
      padding = constants.RSA_PKCS1_OAEP_PADDING;
    else
      return SyncPromise.reject(new Error("unsupported padding scheme"));

    try {
      // In Node.js, privateDecrypt requires version v0.12.
      return SyncPromise.resolve(new Blob
        (Crypto.privateDecrypt({ key: keyPem, padding: padding }, encryptedData.buf()),
         false));
    } catch (err) {
      return SyncPromise.reject(err);
    }
  }
};

/**
 * Decrypt the encryptedData using the keyBits according the encrypt params.
 * @param {Blob} keyBits The key value (PKCS8-encoded private key).
 * @param {Blob} encryptedData The data to decrypt.
 * @param {EncryptParams} params This decrypts according to
 * params.getAlgorithmType().
 * @return {Blob} The decrypted data.
 * @throws Error If decryptPromise doesn't return a SyncPromise which is
 * already fulfilled.
 */
RsaAlgorithm.decrypt = function(keyBits, encryptedData, params)
{
  return SyncPromise.getValue(this.decryptPromise
    (keyBits, encryptedData, params, true));
};

/**
 * Encrypt the plainData using the keyBits according the encrypt params.
 * @param {Blob} keyBits The key value (DER-encoded public key).
 * @param {Blob} plainData The data to encrypt.
 * @param {EncryptParams} params This encrypts according to
 * params.getAlgorithmType().
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise which returns the encrypted Blob.
 */
RsaAlgorithm.encryptPromise = function(keyBits, plainData, params, useSync)
{
  if (UseSubtleCrypto() && !useSync &&
      // Crypto.subtle doesn't implement PKCS1 padding.
      params.getAlgorithmType() != EncryptAlgorithmType.RsaPkcs) {
    if (params.getAlgorithmType() == EncryptAlgorithmType.RsaOaep) {
      return crypto.subtle.importKey
        ("spki", keyBits.buf(), { name: "RSA-OAEP", hash: {name: "SHA-1"} },
         false, ["encrypt"])
      .then(function(publicKey) {
        return crypto.subtle.encrypt
          ({ name: "RSA-OAEP" }, publicKey, plainData.buf());
      })
      .then(function(result) {
        return Promise.resolve(new Blob(new Uint8Array(result), false));
      });
    }
    else
      return Promise.reject(new Error("unsupported padding scheme"));
  }
  else {
    // Encode the key DER as a PEM public key as needed by Crypto.
    var keyBase64 = keyBits.buf().toString('base64');
    var keyPem = "-----BEGIN PUBLIC KEY-----\n";
    for (var i = 0; i < keyBase64.length; i += 64)
      keyPem += (keyBase64.substr(i, 64) + "\n");
    keyPem += "-----END PUBLIC KEY-----";

    var padding;
    if (params.getAlgorithmType() == EncryptAlgorithmType.RsaPkcs)
      padding = constants.RSA_PKCS1_PADDING;
    else if (params.getAlgorithmType() == EncryptAlgorithmType.RsaOaep)
      padding = constants.RSA_PKCS1_OAEP_PADDING;
    else
      return SyncPromise.reject(new Error("unsupported padding scheme"));

    try {
      // In Node.js, publicEncrypt requires version v0.12.
      return SyncPromise.resolve(new Blob
        (Crypto.publicEncrypt({ key: keyPem, padding: padding }, plainData.buf()),
         false));
    } catch (err) {
      return SyncPromise.reject(err);
    }
  }
};

/**
 * Encrypt the plainData using the keyBits according the encrypt params.
 * @param {Blob} keyBits The key value (DER-encoded public key).
 * @param {Blob} plainData The data to encrypt.
 * @param {EncryptParams} params This encrypts according to
 * params.getAlgorithmType().
 * @return {Blob} The encrypted data.
 * @throws Error If encryptPromise doesn't return a SyncPromise which is
 * already fulfilled.
 */
RsaAlgorithm.encrypt = function(keyBits, plainData, params)
{
  return SyncPromise.getValue(this.encryptPromise
    (keyBits, plainData, params, true));
};

/**
 * Decode the PKCS #8 private key, check that the algorithm is RSA, and return
 * the inner RSAPrivateKey DER.
 * @param {Blob} The DER-encoded PKCS #8 private key.
 * @param {Blob} The DER-encoded RSAPrivateKey.
 */
RsaAlgorithm.getRsaPrivateKeyDer = function(pkcs8PrivateKeyDer)
{
  var parsedNode = DerNode.parse(pkcs8PrivateKeyDer.buf(), 0);
  var pkcs8Children = parsedNode.getChildren();
  var algorithmIdChildren = DerNode.getSequence(pkcs8Children, 1).getChildren();
  var oidString = algorithmIdChildren[0].toVal();

  if (oidString != PrivateKeyStorage.RSA_ENCRYPTION_OID)
    throw new Error("The PKCS #8 private key is not RSA_ENCRYPTION");

  return pkcs8Children[2].getPayload();
};
/**
 * Copyright (C) 2015-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * @author: From ndn-group-encrypt src/consumer-db https://github.com/named-data/ndn-group-encrypt
 *
 * 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.
 */

/** @ignore */
var SyncPromise = require('../util/sync-promise.js').SyncPromise;

/**
 * ConsumerDb is a base class the storage of decryption keys for the consumer. A
 * subclass must implement the methods. For example, see Sqlite3ConsumerDb (for
 * Nodejs) or IndexedDbConsumerDb (for the browser).
 * @note This class is an experimental feature. The API may change.
 * @constructor
 */
var ConsumerDb = function ConsumerDb()
{
};

exports.ConsumerDb = ConsumerDb;

/**
 * Create a new ConsumerDb.Error to report an error using ConsumerDb
 * methods, wrapping the given error object.
 * Call with: throw new ConsumerDb.Error(new Error("message")).
 * @constructor
 * @param {Error} error The exception created with new Error.
 */
ConsumerDb.Error = function ConsumerDbError(error)
{
  if (error) {
    error.__proto__ = ConsumerDb.Error.prototype;
    return error;
  }
}

ConsumerDb.Error.prototype = new Error();
ConsumerDb.Error.prototype.name = "ConsumerDbError";

/**
 * Get the key with keyName from the database.
 * @param {Name} keyName The key name.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that returns a Blob with the encoded
 * key (or an isNull Blob if cannot find the key with keyName), or that is
 * rejected with ConsumerDb.Error for a database error.
 */
ConsumerDb.prototype.getKeyPromise = function(keyName, useSync)
{
  return SyncPromise.reject(new Error
    ("ConsumerDb.getKeyPromise is not implemented"));
};

/**
 * Add the key with keyName and keyBlob to the database.
 * @param {Name} keyName The key name.
 * @param {Blob} keyBlob The encoded key.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that fulfills when the key is added,
 * or that is rejected with ConsumerDb.Error if a key with the same keyName
 * already exists, or other database error.
 */
ConsumerDb.prototype.addKeyPromise = function(keyName, keyBlob, useSync)
{
  return SyncPromise.reject(new Error
    ("ConsumerDb.addKeyPromise is not implemented"));
};

/**
 * Delete the key with keyName from the database. If there is no key with
 * keyName, do nothing.
 * @param {Name} keyName The key name.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that fulfills when the key is deleted
 * (or there is no such key), or that is rejected with ConsumerDb.Error for a
 * database error.
 */
ConsumerDb.prototype.deleteKeyPromise = function(keyName, useSync)
{
  return SyncPromise.reject(new Error
    ("ConsumerDb.addKeyPromise is not implemented"));
};
/**
 * Copyright (C) 2015-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * @author: From ndn-group-encrypt src/consumer https://github.com/named-data/ndn-group-encrypt
 *
 * 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.
 */

/** @ignore */
var Blob = require('../util/blob.js').Blob; /** @ignore */
var Name = require('../name.js').Name; /** @ignore */
var Interest = require('../interest.js').Interest; /** @ignore */
var NetworkNack = require('../network-nack.js').NetworkNack; /** @ignore */
var Link = require('../link.js').Link; /** @ignore */
var EncryptedContent = require('./encrypted-content.js').EncryptedContent; /** @ignore */
var EncryptError = require('./encrypt-error.js').EncryptError; /** @ignore */
var EncryptParams = require('./algo/encrypt-params.js').EncryptParams; /** @ignore */
var EncryptAlgorithmType = require('./algo/encrypt-params.js').EncryptAlgorithmType; /** @ignore */
var RsaAlgorithm = require('./algo/rsa-algorithm.js').RsaAlgorithm; /** @ignore */
var AesAlgorithm = require('./algo/aes-algorithm.js').AesAlgorithm; /** @ignore */
var Encryptor = require('./algo/encryptor.js').Encryptor; /** @ignore */
var SyncPromise = require('../util/sync-promise.js').SyncPromise; /** @ignore */
var NdnCommon = require('../util/ndn-common.js').NdnCommon;

/**
 * A Consumer manages fetched group keys used to decrypt a data packet in the
 * group-based encryption protocol.
 * Create a Consumer to use the given ConsumerDb, Face and other values.
 * @param {Face} face The face used for data packet and key fetching.
 * @param {KeyChain} keyChain The keyChain used to verify data packets.
 * @param {Name} groupName The reading group name that the consumer belongs to.
 * This makes a copy of the Name.
 * @param {Name} consumerName The identity of the consumer. This makes a copy of
 * the Name.
 * @param {ConsumerDb} database The ConsumerDb database for storing decryption
 * keys.
 * @param {Link} cKeyLink (optional) The Link object to use in Interests for
 * C-KEY retrieval. This makes a copy of the Link object. If the Link object's
 * getDelegations().size() is zero, don't use it. If omitted, don't use a Link
 * object.
 * @param {Link} dKeyLink (optional) The Link object to use in Interests for
 * D-KEY retrieval. This makes a copy of the Link object. If the Link object's
 * getDelegations().size() is zero, don't use it. If omitted, don't use a Link
 * object.
 * @note This class is an experimental feature. The API may change.
 * @constructor
 */
var Consumer = function Consumer
  (face, keyChain, groupName, consumerName, database, cKeyLink, dKeyLink)
{
  this.database_ = database;
  this.keyChain_ = keyChain;
  this.face_ = face;
  this.groupName_ = new Name(groupName);
  this.consumerName_ = new Name(consumerName);
  this.cKeyLink_ =
    (cKeyLink == undefined ? Consumer.NO_LINK : new Link(cKeyLink));
  this.dKeyLink_ =
    (dKeyLink == undefined ? Consumer.NO_LINK : new Link(dKeyLink));

  // The map key is the C-KEY name URI string. The value is the encoded key Blob.
  // (Use a string because we can't use the Name object as the key in JavaScript.)
  this.cKeyMap_ = {};
  // The map key is the D-KEY name URI string. The value is the encoded key Blob.
  this.dKeyMap_ = {};
};

exports.Consumer = Consumer;

/**
 * Express an Interest to fetch the content packet with contentName, and
 * decrypt it, fetching keys as needed.
 * @param {Name} contentName The name of the content packet.
 * @param {function} onConsumeComplete When the content packet is fetched and
 * decrypted, this calls onConsumeComplete(contentData, result) where
 * contentData is the fetched Data packet and result is the decrypted plain
 * text Blob.
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onError This calls onError(errorCode, message) for an error,
 * where errorCode is an error code from EncryptError.ErrorCode.
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param link {Link} (optional) The Link object to use in Interests for data
 * retrieval. This makes a copy of the Link object. If the Link object's
 * getDelegations().size() is zero, don't use it. If omitted, don't use a Link
 * object.
 */
Consumer.prototype.consume = function
  (contentName, onConsumeComplete, onError, link)
{
  if (link == undefined)
    link = Consumer.NO_LINK;

  var interest = new Interest(contentName);
  var thisConsumer = this;
  // Copy the Link object since the passed link may become invalid.
  this.sendInterest_
    (interest, 1, new Link(link),
     function(validData) {
       // Decrypt the content.
       thisConsumer.decryptContent_(validData, function(plainText) {
         try {
           onConsumeComplete(validData, plainText);
         } catch (ex) {
           console.log("Error in onConsumeComplete: " + NdnCommon.getErrorWithStackTrace(ex));
         }
       }, onError);
     },
     onError);
};

/**
 * Set the group name.
 * @param {Name} groupName The reading group name that the consumer belongs to.
 * This makes a copy of the Name.
 */
Consumer.prototype.setGroup = function(groupName)
{
  this.groupName_ = new Name(groupName);
};

/**
 * Add a new decryption key with keyName and keyBlob to the database.
 * @param {Name} keyName The key name.
 * @param {Blob} keyBlob The encoded key.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that fulfills when the key is added,
 * or that is rejected with Error if the consumer name is not a prefix of the
 * key name, or ConsumerDb.Error if a key with the same keyName already exists,
 * or other database error.
 */
Consumer.prototype.addDecryptionKeyPromise = function(keyName, keyBlob, useSync)
{
  if (!(this.consumerName_.match(keyName)))
    return SyncPromise.reject(new Error
      ("addDecryptionKey: The consumer name must be a prefix of the key name"));

  return this.database_.addKeyPromise(keyName, keyBlob, useSync);
};

/**
 * Add a new decryption key with keyName and keyBlob to the database.
 * @param {Name} keyName The key name.
 * @param {Blob} keyBlob The encoded key.
 * @param {function} onComplete (optional) This calls onComplete() when the key
 * is added. (Some database libraries only use a callback, so onComplete is
 * required to use these.)
 * @param {function} onError (optional) If defined, then onComplete must be
 * defined and if there is an exception, then this calls onError(exception)
 * where exception is Error if the consumer name is not a prefix of the key
 * name, or ConsumerDb.Error if a key with the same keyName already exists,
 * or other database error. If onComplete is defined but onError is undefined,
 * then this will log any thrown exception. (Some database libraries only use a
 * callback, so onError is required to be notified of an exception.)
 */
Consumer.prototype.addDecryptionKey = function
  (keyName, keyBlob, onComplete, onError)
{
  return SyncPromise.complete(onComplete, onError,
    this.addDecryptionKeyPromise(keyName, keyBlob, !onComplete));
};

/**
 * Consume.Error is used internally from promised-based methods to reject with
 * an error object that has the errorCode and message returned through the
 * onError callback.
 * @param {number} errorCode An error code from EncryptError.ErrorCode.
 * @param {string} message The error message.
 */
Consumer.Error = function ConsumerError(errorCode, message)
{
  this.errorCode = errorCode;
  this.message = message;
};

/**
 * If exception is a ConsumerError, then call onError with the errorCode and
 * message, otherwise call onError with ErrorCode.General.
 */
Consumer.Error.callOnError = function(onError, exception, messagePrefix)
{
  if (!messagePrefix)
    messagePrefix = "";

  if (exception instanceof Consumer.Error) {
    try {
      onError(exception.errorCode, exception.message);
    } catch (ex) {
      console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
    }
  }
  else {
    try {
      onError(EncryptError.ErrorCode.General, messagePrefix + exception);
    } catch (ex) {
      console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
    }
  }
}

/**
 * Decrypt encryptedContent using keyBits.
 * @param {Blob|EncryptedContent} encryptedContent The EncryptedContent to
 * decrypt, or a Blob which is first decoded as an EncryptedContent.
 * @param {Blob} keyBits The key value.
 * @return {Promise|SyncPromise} A promise that returns the decrypted Blob, or
 * that is rejected with Consumer.Error or other error.
 */
Consumer.decryptPromise_ = function(encryptedContent, keyBits)
{
  return SyncPromise.resolve()
  .then(function() {
    if (typeof encryptedContent == 'object' && encryptedContent instanceof Blob) {
      // Decode as EncryptedContent.
      var encryptedBlob = encryptedContent;
      encryptedContent = new EncryptedContent();
      encryptedContent.wireDecode(encryptedBlob);
    }

    var payload = encryptedContent.getPayload();

    if (encryptedContent.getAlgorithmType() == EncryptAlgorithmType.AesCbc) {
      // Prepare the parameters.
      var decryptParams = new EncryptParams(EncryptAlgorithmType.AesCbc);
      decryptParams.setInitialVector(encryptedContent.getInitialVector());

      // Decrypt the content.
      return AesAlgorithm.decryptPromise(keyBits, payload, decryptParams);
    }
    else if (encryptedContent.getAlgorithmType() == EncryptAlgorithmType.RsaOaep) {
      // Prepare the parameters.
      var decryptParams = new EncryptParams(EncryptAlgorithmType.RsaOaep);

      // Decrypt the content.
      return RsaAlgorithm.decryptPromise(keyBits, payload, decryptParams);
    }
    else
      return SyncPromise.reject(new Consumer.Error
        (EncryptError.ErrorCode.UnsupportedEncryptionScheme,
          "" + encryptedContent.getAlgorithmType()));
  });
};

/**
 * Decrypt encryptedContent using keyBits.
 * @param {Blob|EncryptedContent} encryptedContent The EncryptedContent to
 * decrypt, or a Blob which is first decoded as an EncryptedContent.
 * @param {Blob} keyBits The key value.
 * @param {function} onPlainText When the data packet is decrypted, this calls
 * onPlainText(decryptedBlob) with the decrypted Blob.
 * @param {function} onError This calls onError(errorCode, message) for an error,
 * where errorCode is an error code from EncryptError.ErrorCode.
 */
Consumer.decrypt_ = function(encryptedContent, keyBits, onPlainText, onError)
{
  Consumer.decryptPromise_(encryptedContent, keyBits)
  .then(function(decryptedBlob) {
    onPlainText(decryptedBlob);
  }, function(ex) {
    Consumer.Error.callOnError(onError, ex);
  });
};

/**
 * Decrypt the data packet.
 * @param {Data} data The data packet. This does not verify the packet.
 * @param {function} onPlainText When the data packet is decrypted, this calls
 * onPlainText(decryptedBlob) with the decrypted Blob.
 * @param {function} onError This calls onError(errorCode, message) for an error,
 * where errorCode is an error code from EncryptError.ErrorCode.
 */
Consumer.prototype.decryptContent_ = function(data, onPlainText, onError)
{
  // Get the encrypted content.
  var dataEncryptedContent = new EncryptedContent();
  try {
    dataEncryptedContent.wireDecode(data.getContent());
  } catch (ex) {
    Consumer.Error.callOnError(onError, ex, "Error decoding EncryptedContent: ");
    return;
  }
  var cKeyName = dataEncryptedContent.getKeyLocator().getKeyName();

  // Check if the content key is already in the store.
  var cKey = this.cKeyMap_[cKeyName.toUri()];
  if (cKey)
    this.decrypt_(dataEncryptedContent, cKey, onPlainText, onError);
  else {
    // Retrieve the C-KEY Data from the network.
    var interestName = new Name(cKeyName);
    interestName.append(Encryptor.NAME_COMPONENT_FOR).append(this.groupName_);
    var interest = new Interest(interestName);
    var thisConsumer = this;
    this.sendInterest_
      (interest, 1, this.cKeyLink_,
       function(validCKeyData) {
         thisConsumer.decryptCKey_(validCKeyData, function(cKeyBits) {
           thisConsumer.cKeyMap_[cKeyName.toUri()] = cKeyBits;
           Consumer.decrypt_
             (dataEncryptedContent, cKeyBits, onPlainText, onError);
         }, onError);
       },
       onError);
  }
};

/**
 * Decrypt cKeyData.
 * @param {Data} cKeyData The C-KEY data packet.
 * @param {function} onPlainText When the data packet is decrypted, this calls
 * onPlainText(decryptedBlob) with the decrypted Blob.
 * @param {function} onError This calls onError(errorCode, message) for an error,
 * where errorCode is an error code from EncryptError.ErrorCode.
 */
Consumer.prototype.decryptCKey_ = function(cKeyData, onPlainText, onError)
{
  // Get the encrypted content.
  var cKeyContent = cKeyData.getContent();
  var cKeyEncryptedContent = new EncryptedContent();
  try {
    cKeyEncryptedContent.wireDecode(cKeyContent);
  } catch (ex) {
    Consumer.Error.callOnError(onError, ex, "Error decoding EncryptedContent: ");
    return;
  }
  var eKeyName = cKeyEncryptedContent.getKeyLocator().getKeyName();
  var dKeyName = eKeyName.getPrefix(-3);
  dKeyName.append(Encryptor.NAME_COMPONENT_D_KEY).append(eKeyName.getSubName(-2));

  // Check if the decryption key is already in the store.
  var dKey = this.dKeyMap_[dKeyName.toUri()];
  if (dKey)
    this.decrypt_(cKeyEncryptedContent, dKey, onPlainText, onError);
  else {
    // Get the D-Key Data.
    var interestName = new Name(dKeyName);
    interestName.append(Encryptor.NAME_COMPONENT_FOR).append(this.consumerName_);
    var interest = new Interest(interestName);
    var thisConsumer = this;
    this.sendInterest_
      (interest, 1, this.dKeyLink_,
       function(validDKeyData) {
         thisConsumer.decryptDKeyPromise_(validDKeyData)
         .then(function(dKeyBits) {
           thisConsumer.dKeyMap_[dKeyName.toUri()] = dKeyBits;
           Consumer.decrypt_
             (cKeyEncryptedContent, dKeyBits, onPlainText, onError);
         }, function(ex) {
           Consumer.Error.callOnError(onError, ex, "decryptDKey error: ");
         });
       },
       onError);
  }
};

/**
 * Decrypt dKeyData.
 * @param {Data} dKeyData The D-KEY data packet.
 * @return {Promise|SyncPromise} A promise that returns the decrypted Blob, or
 * that is rejected with Consumer.Error or other error.
 */
Consumer.prototype.decryptDKeyPromise_ = function(dKeyData)
{
  var dataContent;
  var encryptedNonce;
  var encryptedPayloadBlob;
  var thisConsumer = this;

  return SyncPromise.resolve()
  .then(function() {
    // Get the encrypted content.
    dataContent = dKeyData.getContent();

    // Process the nonce.
    // dataContent is a sequence of the two EncryptedContent.
    encryptedNonce = new EncryptedContent();
    encryptedNonce.wireDecode(dataContent);
    var consumerKeyName = encryptedNonce.getKeyLocator().getKeyName();

    // Get consumer decryption key.
    return thisConsumer.getDecryptionKeyPromise_(consumerKeyName);
  })
  .then(function(consumerKeyBlob) {
    if (consumerKeyBlob.size() == 0)
      return SyncPromise.reject(new Consumer.Error
        (EncryptError.ErrorCode.NoDecryptKey,
         "The desired consumer decryption key in not in the database"));

    // Process the D-KEY.
    // Use the size of encryptedNonce to find the start of encryptedPayload.
    var encryptedPayloadBuffer = dataContent.buf().slice
      (encryptedNonce.wireEncode().size());
    encryptedPayloadBlob = new Blob(encryptedPayloadBuffer, false);
    if (encryptedPayloadBlob.size() == 0)
      return SyncPromise.reject(new Consumer.Error
        (EncryptError.ErrorCode.InvalidEncryptedFormat,
         "The data packet does not satisfy the D-KEY packet format"));

    // Decrypt the D-KEY.
    return Consumer.decryptPromise_(encryptedNonce, consumerKeyBlob);
  })
  .then(function(nonceKeyBits) {
    return Consumer.decryptPromise_(encryptedPayloadBlob, nonceKeyBits);
  });
};

/**
 * Express the interest, call verifyData for the fetched Data packet and call
 * onVerified if verify succeeds. If verify fails, call
 * onError(EncryptError.ErrorCode.Validation, "verifyData failed"). If the
 * interest times out, re-express nRetrials times. If the interest times out
 * nRetrials times, or for a network Nack, call
 * onError(EncryptError.ErrorCode.DataRetrievalFailure, interest.getName().toUri()).
 * @param {Interest} interest The Interest to express.
 * @param {number} nRetrials The number of retrials left after a timeout.
 * @param {Link} link The Link object to use in the Interest. This does not make
 * a copy of the Link object. If the Link object's getDelegations().size() is
 * zero, don't use it.
 * @param {function} onVerified When the fetched Data packet validation
 * succeeds, this calls onVerified(data).
 * @param {function} onError This calls onError(errorCode, message) for an error,
 * where errorCode is an error code from EncryptError.ErrorCode.
 */
Consumer.prototype.sendInterest_ = function
  (interest, nRetrials, link, onVerified, onError)
{
  // Prepare the callback functions.
  var thisConsumer = this;
  var onData = function(contentInterest, contentData) {
    try {
      thisConsumer.keyChain_.verifyData
        (contentData, onVerified,
         function(d, reason) {
           try {
             onError
               (EncryptError.ErrorCode.Validation, "verifyData failed. Reason: " +
                reason);
           } catch (ex) {
             console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
           }
         });
    } catch (ex) {
      Consumer.Error.callOnError(onError, ex, "verifyData error: ");
    }
  };

  function onNetworkNack(interest, networkNack) {
    // We have run out of options. Report a retrieval failure.
    try {
      onError(EncryptError.ErrorCode.DataRetrievalFailure,
              interest.getName().toUri());
    } catch (ex) {
      console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
    }
  }

  var onTimeout = function(interest) {
    if (nRetrials > 0)
      thisConsumer.sendInterest_(interest, nRetrials - 1, link, onVerified, onError);
    else
      onNetworkNack(interest, new NetworkNack());
  };

  var request;
  if (link.getDelegations().size() === 0)
    // We can use the supplied interest without copying.
    request = interest;
  else {
    // Copy the supplied interest and add the Link.
    request = new Interest(interest);
    // This will use a cached encoding if available.
    request.setLinkWireEncoding(link.wireEncode());
  }

  try {
    this.face_.expressInterest(request, onData, onTimeout, onNetworkNack);
  } catch (ex) {
    Consumer.Error.callOnError(onError, ex, "expressInterest error: ");
  }
};

/**
 * Get the encoded blob of the decryption key with decryptionKeyName from the
 * database.
 * @param {Name} decryptionKeyName The key name.
 * @return {Promise|SyncPromise} A promise that returns a Blob with the encoded
 * key (or an isNull Blob if cannot find the key with decryptionKeyName), or
 * that is rejected with ConsumerDb.Error for a database error.
 */
Consumer.prototype.getDecryptionKeyPromise_ = function(decryptionKeyName)
{
  return this.database_.getKeyPromise(decryptionKeyName);
};

Consumer.NO_LINK = new Link();
/**
 * Copyright (C) 2015-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * @author: From ndn-group-encrypt src/decrypt-key https://github.com/named-data/ndn-group-encrypt
 *
 * 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.
 */

/** @ignore */
var Blob = require('../util/blob.js').Blob;

/**
 * A DecryptKey supplies the key for decrypt.
 * Create a DecryptKey with the given key value.
 * @param {Blob|DecryptKey} value If value is another DecryptKey then copy it.
 * Otherwise, value is the key value.
 * @note This class is an experimental feature. The API may change.
 * @constructor
 */
var DecryptKey = function DecryptKey(value)
{
  if (typeof value === 'object' && value instanceof DecryptKey) {
    // Make a deep copy.
    this.keyBits_ = value.keyBits_;
  }
  else {
    var keyBits = value;
    this.keyBits_ = typeof keyBits === 'object' && keyBits instanceof Blob ?
      keyBits : new Blob(keyBits);
  }
};

exports.DecryptKey = DecryptKey;

/**
 * Get the key value.
 * @return {Blob} The key value.
 */
DecryptKey.prototype.getKeyBits = function() { return this.keyBits_; };
/**
 * Copyright (C) 2015-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * @author: From ndn-group-encrypt src/error-code https://github.com/named-data/ndn-group-encrypt
 *
 * 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.
 */

/**
 * EncryptError holds the ErrorCode enum for errors from the encrypt library.
 */
var EncryptError = function EncryptError()
{
};

exports.EncryptError = EncryptError;

EncryptError.ErrorCode = {
  Timeout:                     1,
  Validation:                  2,
  UnsupportedEncryptionScheme: 32,
  InvalidEncryptedFormat:      33,
  NoDecryptKey:                34,
  EncryptionFailure:           35,
  DataRetrievalFailure:        36,
  General:                     100
};
/**
 * Copyright (C) 2015-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * @author: From ndn-group-encrypt src/encrypt-key https://github.com/named-data/ndn-group-encrypt
 *
 * 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.
 */

/** @ignore */
var Blob = require('../util/blob.js').Blob;

/**
 * An EncryptKey supplies the key for encrypt.
 * Create an EncryptKey with the given key value.
 * @param {Blob|EncryptKey} value If value is another EncryptKey then copy it.
 * Otherwise, value is the key value.
 * @note This class is an experimental feature. The API may change.
 * @constructor
 */
var EncryptKey = function EncryptKey(value)
{
  if (typeof value === 'object' && value instanceof EncryptKey) {
    // Make a deep copy.
    this.keyBits_ = value.keyBits_;
  }
  else {
    var keyBits = value;
    this.keyBits_ = typeof keyBits === 'object' && keyBits instanceof Blob ?
      keyBits : new Blob(keyBits);
  }
};

exports.EncryptKey = EncryptKey;

/**
 * Get the key value.
 * @return {Blob} The key value.
 */
EncryptKey.prototype.getKeyBits = function() { return this.keyBits_; };
/**
 * Copyright (C) 2015-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * @author: From ndn-group-encrypt src/encrypted-content https://github.com/named-data/ndn-group-encrypt
 *
 * 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.
 */

/** @ignore */
var KeyLocator = require('../key-locator.js').KeyLocator; /** @ignore */
var WireFormat = require('../encoding/wire-format.js').WireFormat; /** @ignore */
var Blob = require('../util/blob.js').Blob;

/**
 * An EncryptedContent holds an encryption type, a payload and other fields
 * representing encrypted content.
 * @param {EncryptedContent} (optional) If value is another EncryptedContent
 * then copy it. If value is omitted then create an EncryptedContent with
 * unspecified values.
 * @note This class is an experimental feature. The API may change.
 * @constructor
 */
var EncryptedContent = function EncryptedContent(value)
{
  if (typeof value === 'object' && value instanceof EncryptedContent) {
    // Make a deep copy.
    this.algorithmType_ = value.algorithmType_;
    this.keyLocator_ = new KeyLocator(value.keyLocator_);
    this.initialVector_ = value.initialVector_;
    this.payload_ = value.payload_;
  }
  else {
    this.algorithmType_ = null;
    this.keyLocator_ = new KeyLocator();
    this.initialVector_ = new Blob();
    this.payload_ = new Blob();
  }
};

exports.EncryptedContent = EncryptedContent;

/**
 * Get the algorithm type from EncryptAlgorithmType.
 * @return {number} The algorithm type from EncryptAlgorithmType, or null if
 * not specified.
 */
EncryptedContent.prototype.getAlgorithmType = function()
{
  return this.algorithmType_;
};

/**
 * Get the key locator.
 * @return {KeyLocator} The key locator. If not specified, getType() is null.
 */
EncryptedContent.prototype.getKeyLocator = function()
{
  return this.keyLocator_;
};

/**
 * Get the initial vector.
 * @return {Blob} The initial vector. If not specified, isNull() is true.
 */
EncryptedContent.prototype.getInitialVector = function()
{
  return this.initialVector_;
};

/**
 * Get the payload.
 * @return {Blob} The payload. If not specified, isNull() is true.
 */
EncryptedContent.prototype.getPayload = function()
{
  return this.payload_;
};

/**
 * Set the algorithm type.
 * @param {number} algorithmType The algorithm type from EncryptAlgorithmType.
 * If not specified, set to null.
 * @return {EncryptedContent} This EncryptedContent so that you can chain calls
 * to update values.
 */
EncryptedContent.prototype.setAlgorithmType = function(algorithmType)
{
  this.algorithmType_ = algorithmType;
  return this;
};

/**
 * Set the key locator.
 * @param {KeyLocator} keyLocator The key locator. This makes a copy of the
 * object. If not specified, set to the default KeyLocator().
 * @return {EncryptedContent} This EncryptedContent so that you can chain calls
 * to update values.
 */
EncryptedContent.prototype.setKeyLocator = function(keyLocator)
{
  this.keyLocator_ = typeof keyLocator === 'object' &&
                       keyLocator instanceof KeyLocator ?
    new KeyLocator(keyLocator) : new KeyLocator();
  return this;
};

/**
 * Set the initial vector.
 * @param {Blob} initialVector The initial vector. If not specified, set to the
 * default Blob() where isNull() is true.
 * @return {EncryptedContent} This EncryptedContent so that you can chain calls
 * to update values.
 */
EncryptedContent.prototype.setInitialVector = function(initialVector)
{
  this.initialVector_ =
      typeof initialVector === 'object' && initialVector instanceof Blob ?
    initialVector : new Blob(initialVector);
  return this;
};

/**
 * Set the encrypted payload.
 * @param {Blob} payload The payload. If not specified, set to the default Blob()
 * where isNull() is true.
 * @return {EncryptedContent} This EncryptedContent so that you can chain calls
 * to update values.
 */
EncryptedContent.prototype.setPayload = function(payload)
{
  this.payload_ = typeof payload === 'object' && payload instanceof Blob ?
    payload : new Blob(payload);
  return this;
};

/**
 * Encode this EncryptedContent for a particular wire format.
 * @param {WireFormat} wireFormat (optional) A WireFormat object  used to encode
 * this object. If omitted, use WireFormat.getDefaultWireFormat().
 * @return {Blob} The encoded buffer in a Blob object.
 */
EncryptedContent.prototype.wireEncode = function(wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
  return wireFormat.encodeEncryptedContent(this);
};

/**
 * Decode the input using a particular wire format and update this
 * EncryptedContent.
 * @param {Blob|Buffer} input The buffer with the bytes to decode.
 * @param {WireFormat} wireFormat (optional) A WireFormat object used to decode
 * this object. If omitted, use WireFormat.getDefaultWireFormat().
 */
EncryptedContent.prototype.wireDecode = function(input, wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());
  if (typeof input === 'object' && input instanceof Blob)
    // Input is a blob, so get its buf() and set copy false.
    wireFormat.decodeEncryptedContent(this, input.buf(), false);
  else
    wireFormat.decodeEncryptedContent(this, input, true);
};
/**
 * Copyright (C) 2015-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * @author: From ndn-group-encrypt src/group-manager-db https://github.com/named-data/ndn-group-encrypt
 *
 * 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.
 */

/** @ignore */
var SyncPromise = require('../util/sync-promise.js').SyncPromise;

/**
 * GroupManagerDb is a base class for the storage of data used by the
 * GroupManager. It contains two tables to store Schedules and Members.
 * This is an abstract base class. A subclass must implement the methods.
 * For example, see Sqlite3GroupManagerDb (for Nodejs) or IndexedDbGroupManagerDb
 * (for the browser).
 * @note This class is an experimental feature. The API may change.
 * @constructor
 */
var GroupManagerDb = function GroupManagerDb()
{
};

exports.GroupManagerDb = GroupManagerDb;

/**
 * Create a new GroupManagerDb.Error to report an error using GroupManagerDb
 * methods, wrapping the given error object.
 * Call with: throw new GroupManagerDb.Error(new Error("message")).
 * @constructor
 * @param {Error} error The exception created with new Error.
 */
GroupManagerDb.Error = function GroupManagerDbError(error)
{
  if (error) {
    error.__proto__ = GroupManagerDb.Error.prototype;
    return error;
  }
}

GroupManagerDb.Error.prototype = new Error();
GroupManagerDb.Error.prototype.name = "GroupManagerDbError";

////////////////////////////////////////////////////// Schedule management.

/**
 * Check if there is a schedule with the given name.
 * @param {string} name The name of the schedule.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that returns true if there is a
 * schedule (else false), or that is rejected with GroupManagerDb.Error for a
 * database error.
 */
GroupManagerDb.prototype.hasSchedulePromise = function(name, useSync)
{
  return SyncPromise.reject(new Error
    ("GroupManagerDb.hasSchedulePromise is not implemented"));
};

/**
 * List all the names of the schedules.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that returns a new array of string
 * with the names of all schedules, or that is rejected with
 * GroupManagerDb.Error for a database error.
 */
GroupManagerDb.prototype.listAllScheduleNamesPromise = function(useSync)
{
  return SyncPromise.reject(new Error
    ("GroupManagerDb.listAllScheduleNamesPromise is not implemented"));
};

/**
 * Get a schedule with the given name.
 * @param {string} name The name of the schedule.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that returns a new Schedule object,
 * or that is rejected with GroupManagerDb.Error if the schedule does not exist
 * or other database error.
 */
GroupManagerDb.prototype.getSchedulePromise = function(name, useSync)
{
  return SyncPromise.reject(new Error
    ("GroupManagerDb.getSchedulePromise is not implemented"));
};

/**
 * For each member using the given schedule, get the name and public key DER
 * of the member's key.
 * @param {string} name The name of the schedule.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that returns a new array of object
 * (where "keyName" is the Name of the public key and "publicKey" is the Blob of
 * the public key DER), or that is rejected with GroupManagerDb.Error for a
 * database error. Note that the member's identity name is keyName.getPrefix(-1).
 * If the schedule name is not found, the list is empty.
 */
GroupManagerDb.prototype.getScheduleMembersPromise = function
  (name, useSync)
{
  return SyncPromise.reject(new Error
    ("GroupManagerDb.getScheduleMembersPromise is not implemented"));
};

/**
 * Add a schedule with the given name.
 * @param {string} name The name of the schedule. The name cannot be empty.
 * @param {Schedule} schedule The Schedule to add.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that fulfills when the schedule is
 * added, or that is rejected with GroupManagerDb.Error if a schedule with the
 * same name already exists, if the name is empty, or other database error.
 */
GroupManagerDb.prototype.addSchedulePromise = function(name, schedule, useSync)
{
  return SyncPromise.reject(new Error
    ("GroupManagerDb.addSchedulePromise is not implemented"));
};

/**
 * Delete the schedule with the given name. Also delete members which use this
 * schedule. If there is no schedule with the name, then do nothing.
 * @param {string} name The name of the schedule.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that fulfills when the schedule is
 * deleted (or there is no such schedule), or that is rejected with
 * GroupManagerDb.Error for a database error.
 */
GroupManagerDb.prototype.deleteSchedulePromise = function(name, useSync)
{
  return SyncPromise.reject(new Error
    ("GroupManagerDb.deleteSchedulePromise is not implemented"));
};

/**
 * Rename a schedule with oldName to newName.
 * @param {string} oldName The name of the schedule to be renamed.
 * @param {string} newName The new name of the schedule. The name cannot be empty.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that fulfills when the schedule is
 * renamed, or that is rejected with GroupManagerDb.Error if a schedule with
 * newName already exists, if the schedule with oldName does not exist, if
 * newName is empty, or other database error.
 */
GroupManagerDb.prototype.renameSchedulePromise = function
  (oldName, newName, useSync)
{
  return SyncPromise.reject(new Error
    ("GroupManagerDb.renameSchedulePromise is not implemented"));
};

/**
 * Update the schedule with name and replace the old object with the given
 * schedule. Otherwise, if no schedule with name exists, a new schedule
 * with name and the given schedule will be added to database.
 * @param {string} name The name of the schedule. The name cannot be empty.
 * @param {Schedule} schedule The Schedule to update or add.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that fulfills when the schedule is
 * updated, or that is rejected with GroupManagerDb.Error if the name is empty,
 * or other database error.
 */
GroupManagerDb.prototype.updateSchedulePromise = function
  (name, schedule, useSync)
{
  return SyncPromise.reject(new Error
    ("GroupManagerDb.updateSchedulePromise is not implemented"));
};

////////////////////////////////////////////////////// Member management.

/**
 * Check if there is a member with the given identity name.
 * @param {Name} identity The member's identity name.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that returns true if there is a
 * member (else false), or that is rejected with GroupManagerDb.Error for a
 * database error.
 */
GroupManagerDb.prototype.hasMemberPromise = function(identity, useSync)
{
  return SyncPromise.reject(new Error
    ("GroupManagerDb.hasMemberPromise is not implemented"));
};

/**
 * List all the members.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that returns a new array of Name with
 * the names of all members, or that is rejected with GroupManagerDb.Error for a
 * database error.
 */
GroupManagerDb.prototype.listAllMembersPromise = function(useSync)
{
  return SyncPromise.reject(new Error
    ("GroupManagerDb.listAllMembersPromise is not implemented"));
};

/**
 * Get the name of the schedule for the given member's identity name.
 * @param {Name} identity The member's identity name.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that returns the string schedule name,
 * or that is rejected with GroupManagerDb.Error if there's no member with the
 * given identity name in the database, or other database error.
 */
GroupManagerDb.prototype.getMemberSchedulePromise = function(identity, useSync)
{
  return SyncPromise.reject(new Error
    ("GroupManagerDb.getMemberSchedulePromise is not implemented"));
};

/**
 * Add a new member with the given key named keyName into a schedule named
 * scheduleName. The member's identity name is keyName.getPrefix(-1).
 * @param {string} scheduleName The schedule name.
 * @param {Name} keyName The name of the key.
 * @param {Blob} key A Blob of the public key DER.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that fulfills when the member is
 * added, or that is rejected with GroupManagerDb.Error if there's no schedule
 * named scheduleName, if the member's identity name already exists, or other
 * database error.
 */
GroupManagerDb.prototype.addMemberPromise = function
  (scheduleName, keyName, key, useSync)
{
  return SyncPromise.reject(new Error
    ("GroupManagerDb.addMemberPromise is not implemented"));
};

/**
 * Change the name of the schedule for the given member's identity name.
 * @param {Name} identity The member's identity name.
 * @param {string} scheduleName The new schedule name.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that fulfills when the member is
 * updated, or that is rejected with GroupManagerDb.Error if there's no member
 * with the given identity name in the database, or there's no schedule named
 * scheduleName, or other database error.
 */
GroupManagerDb.prototype.updateMemberSchedulePromise = function
  (identity, scheduleName, useSync)
{
  return SyncPromise.reject(new Error
    ("GroupManagerDb.updateMemberSchedulePromise is not implemented"));
};

/**
 * Delete a member with the given identity name. If there is no member with
 * the identity name, then do nothing.
 * @param {Name} identity The member's identity name.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that fulfills when the member is
 * deleted (or there is no such member), or that is rejected with
 * GroupManagerDb.Error for a database error.
 */
GroupManagerDb.prototype.deleteMemberPromise = function(identity, useSync)
{
  return SyncPromise.reject(new Error
    ("GroupManagerDb.deleteMemberPromise is not implemented"));
};
/**
 * Copyright (C) 2015-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * @author: From ndn-group-encrypt src/group-manager https://github.com/named-data/ndn-group-encrypt
 *
 * 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.
 */

/** @ignore */
var Name = require('../name.js').Name; /** @ignore */
var Data = require('../data.js').Data; /** @ignore */
var SyncPromise = require('../util/sync-promise.js').SyncPromise; /** @ignore */
var IdentityCertificate = require('../security/certificate/identity-certificate.js').IdentityCertificate; /** @ignore */
var SecurityException = require('../security/security-exception.js').SecurityException; /** @ignore */
var RsaKeyParams = require('../security/key-params.js').RsaKeyParams; /** @ignore */
var EncryptParams = require('./algo/encrypt-params.js').EncryptParams; /** @ignore */
var EncryptAlgorithmType = require('./algo/encrypt-params.js').EncryptAlgorithmType; /** @ignore */
var Encryptor = require('./algo/encryptor.js').Encryptor; /** @ignore */
var RsaAlgorithm = require('./algo/rsa-algorithm.js').RsaAlgorithm; /** @ignore */
var Interval = require('./interval.js').Interval; /** @ignore */
var Schedule = require('./schedule.js').Schedule;

/**
 * A GroupManager manages keys and schedules for group members in a particular
 * namespace.
 * Create a group manager with the given values. The group manager namespace
 * is <prefix>/read/<dataType> .
 * @param {Name} prefix The prefix for the group manager namespace.
 * @param {Name} dataType The data type for the group manager namespace.
 * @param {GroupManagerDb} database The GroupManagerDb for storing the group
 * management information (including user public keys and schedules).
 * @param {number} keySize The group key will be an RSA key with keySize bits.
 * @param {number} freshnessHours The number of hours of the freshness period of
 *   data packets carrying the keys.
 * @param {KeyChain} keyChain The KeyChain to use for signing data packets. This
 * signs with the default identity.
 * @note This class is an experimental feature. The API may change.
 * @constructor
 */
var GroupManager = function GroupManager
  (prefix, dataType, database, keySize, freshnessHours, keyChain)
{
  this.namespace_ = new Name(prefix).append(Encryptor.NAME_COMPONENT_READ)
    .append(dataType);
  this.database_ = database;
  this.keySize_ = keySize;
  this.freshnessHours_ = freshnessHours;

  this.keyChain_ = keyChain;
};

exports.GroupManager = GroupManager;

/**
 * Create a group key for the interval into which timeSlot falls. This creates
 * a group key if it doesn't exist, and encrypts the key using the public key of
 * each eligible member.
 * @param {number} timeSlot The time slot to cover as milliseconds since
 * Jan 1, 1970 UTC.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that returns a List of Data packets
 * (where the first is the E-KEY data packet with the group's public key and the
 * rest are the D-KEY data packets with the group's private key encrypted with
 * the public key of each eligible member), or that is rejected with
 * GroupManagerDb.Error for a database error or SecurityException for an error
 * using the security KeyChain.
 */
GroupManager.prototype.getGroupKeyPromise = function(timeSlot, useSync)
{
  var memberKeys = [];
  var result = [];
  var thisManager = this;
  var privateKeyBlob;
  var publicKeyBlob;
  var startTimeStamp;
  var endTimeStamp;

  // Get the time interval.
  return this.calculateIntervalPromise_(timeSlot, memberKeys, useSync)
  .then(function(finalInterval) {
    if (finalInterval.isValid() == false)
      return SyncPromise.resolve(result);

    startTimeStamp = Schedule.toIsoString(finalInterval.getStartTime());
    endTimeStamp = Schedule.toIsoString(finalInterval.getEndTime());

    // Generate the private and public keys.
    return thisManager.generateKeyPairPromise_(useSync)
    .then(function(keyPair) {
      privateKeyBlob = keyPair.privateKeyBlob;
      publicKeyBlob = keyPair.publicKeyBlob;

      // Add the first element to the result.
      // The E-KEY (public key) data packet name convention is:
      // /<data_type>/E-KEY/[start-ts]/[end-ts]
      return thisManager.createEKeyDataPromise_
        (startTimeStamp, endTimeStamp, publicKeyBlob, useSync);
    })
    .then(function(data) {
      result.push(data);

      // Encrypt the private key with the public key from each member's certificate.

      // Process the memberKeys entry at i, and recursively call to process the
      // next entry. Return a promise which is resolved when all are processed.
      // (We have to make a recursive function to use Promises.)
      function processMemberKey(i) {
        if (i >= memberKeys.length)
          // Finished.
          return SyncPromise.resolve();

        var keyName = memberKeys[i].keyName;
        var certificateKey = memberKeys[i].publicKey;

        return thisManager.createDKeyDataPromise_
          (startTimeStamp, endTimeStamp, keyName, privateKeyBlob, certificateKey,
           useSync)
        .then(function(data) {
          result.push(data);

          return processMemberKey(i + 1);
        });
      }

      return processMemberKey(0);
    })
    .then(function() {
      return SyncPromise.resolve(result);
    });
  });
};

/**
 * Add a schedule with the given scheduleName.
 * @param {string} scheduleName The name of the schedule. The name cannot be
 * empty.
 * @param {Schedule} schedule The Schedule to add.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that fulfills when the schedule is
 * added, or that is rejected with GroupManagerDb.Error if a schedule with the
 * same name already exists, if the name is empty, or other database error.
 */
GroupManager.prototype.addSchedulePromise = function
  (scheduleName, schedule, useSync)
{
  return this.database_.addSchedulePromise(scheduleName, schedule, useSync);
};

/**
 * Delete the schedule with the given scheduleName. Also delete members which
 * use this schedule. If there is no schedule with the name, then do nothing.
 * @param {string} scheduleName The name of the schedule.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that fulfills when the schedule is
 * deleted (or there is no such schedule), or that is rejected with
 * GroupManagerDb.Error for a database error.
 */
GroupManager.prototype.deleteSchedulePromise = function(scheduleName, useSync)
{
  return this.database_.deleteSchedulePromise(scheduleName, useSync);
};

/**
 * Update the schedule with scheduleName and replace the old object with the
 * given schedule. Otherwise, if no schedule with name exists, a new schedule
 * with name and the given schedule will be added to database.
 * @param {string} scheduleName The name of the schedule. The name cannot be
 * empty.
 * @param {Schedule} schedule The Schedule to update or add.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that fulfills when the schedule is
 * updated, or that is rejected with GroupManagerDb.Error if the name is empty,
 * or other database error.
 */
GroupManager.prototype.updateSchedulePromise = function
  (name, scheduleName, useSync)
{
  return this.database_.updateSchedulePromise(scheduleName, schedule, useSync);
};

/**
 * Add a new member with the given memberCertificate into a schedule named
 * scheduleName. If cert is an IdentityCertificate made from memberCertificate,
 * then the member's identity name is cert.getPublicKeyName().getPrefix(-1).
 * @param {string} scheduleName The schedule name.
 * @param {Data} memberCertificate The member's certificate.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that fulfills when the member is
 * added, or that is rejected with GroupManagerDb.Error if there's no schedule
 * named scheduleName, if the member's identity name already exists, or other
 * database error. Or a promise that is rejected with DerDecodingException for
 * an error decoding memberCertificate as a certificate.
 */
GroupManager.prototype.addMemberPromise = function
  (scheduleName, memberCertificate, useSync)
{
  var cert = new IdentityCertificate(memberCertificate);
  return this.database_.addMemberPromise
    (scheduleName, cert.getPublicKeyName(), cert.getPublicKeyInfo().getKeyDer(),
     useSync);
};

/**
 * Remove a member with the given identity name. If there is no member with
 * the identity name, then do nothing.
 * @param {Name} identity The member's identity name.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that fulfills when the member is
 * removed (or there is no such member), or that is rejected with
 * GroupManagerDb.Error for a database error.
 */
GroupManager.prototype.removeMemberPromise = function(identity, useSync)
{
  return this.database_.deleteMemberPromise(identity, useSync);
};

/**
 * Change the name of the schedule for the given member's identity name.
 * @param {Name} identity The member's identity name.
 * @param {string} scheduleName The new schedule name.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that fulfills when the member is
 * updated, or that is rejected with GroupManagerDb.Error if there's no member
 * with the given identity name in the database, or there's no schedule named
 * scheduleName.
 */
GroupManager.prototype.updateMemberSchedulePromise = function
  (identity, scheduleName, useSync)
{
  return this.database_.updateMemberSchedulePromise
    (identity, scheduleName, useSync);
};

/**
 * Calculate an Interval that covers the timeSlot.
 * @param {number} timeSlot The time slot to cover as milliseconds since
 * Jan 1, 1970 UTC.
 * @param {Array<object>} memberKeys First clear memberKeys then fill it with
 * the info of members who are allowed to access the interval. memberKeys is an
 * array of object where "keyName" is the Name of the public key and "publicKey"
 * is the Blob of the public key DER. The memberKeys entries are sorted by
 * the entry keyName.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that returns a new nterval covering
 * the time slot, or that is rejected with GroupManagerDb.Error for a database
 * error.
 */
GroupManager.prototype.calculateIntervalPromise_ = function
  (timeSlot, memberKeys, useSync)
{
  // Prepare.
  var positiveResult = new Interval();
  var negativeResult = new Interval();
  // Clear memberKeys.
  memberKeys.splice(0, memberKeys.length);
  var thisManager = this;

  // Get the all intervals from the schedules.
  return this.database_.listAllScheduleNamesPromise(useSync)
  .then(function(scheduleNames) {
    // Process the scheduleNames entry at i, and recursively call to process the
    // next entry. Return a promise which is resolved when all are processed.
    // (We have to make a recursive function to use Promises.)
    function processSchedule(i) {
      if (i >= scheduleNames.length)
        // Finished.
        return SyncPromise.resolve();

      var scheduleName = scheduleNames[i];

      return thisManager.database_.getSchedulePromise(scheduleName, useSync)
      .then(function(schedule) {
        var result = schedule.getCoveringInterval(timeSlot);
        var tempInterval = result.interval;

        if (result.isPositive) {
          if (!positiveResult.isValid())
            positiveResult = tempInterval;
          positiveResult.intersectWith(tempInterval);

          return thisManager.database_.getScheduleMembersPromise
            (scheduleName, useSync)
          .then(function(map) {
            // Add each entry in map to memberKeys.
            for (var iMap = 0; iMap < map.length; ++iMap)
              GroupManager.memberKeysAdd_(memberKeys, map[iMap]);

            return processSchedule(i + 1);
          });
        }
        else {
          if (!negativeResult.isValid())
            negativeResult = tempInterval;
          negativeResult.intersectWith(tempInterval);

          return processSchedule(i + 1);
        }
      });
    }

    return processSchedule(0);
  })
  .then(function() {
    if (!positiveResult.isValid())
      // Return an invalid interval when there is no member which has an
      // interval covering the time slot.
      return SyncPromise.resolve(new Interval(false));

    // Get the final interval result.
    var finalInterval;
    if (negativeResult.isValid())
      finalInterval = positiveResult.intersectWith(negativeResult);
    else
      finalInterval = positiveResult;

    return SyncPromise.resolve(finalInterval);
  });
};

/**
 * Add entry to memberKeys, sorted by entry.keyName. If there is already an
 * entry with keyName, then don't add.
 */
GroupManager.memberKeysAdd_ = function(memberKeys, entry)
{
  // Find the index of the first node where the keyName is not less than
  // entry.keyName.
  var i = 0;
  while (i < memberKeys.length) {
    var comparison = memberKeys[i].keyName.compare(entry.keyName);
    if (comparison == 0)
      // A duplicate, so don't add.
      return;

    if (comparison > 0)
      break;
    i += 1;
  }

  memberKeys.splice(i, 0, entry);
};

/**
 * Generate an RSA key pair according to keySize_.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that returns an object where
 * "privateKeyBlob" is the encoding Blob of the private key and "publicKeyBlob"
 * is the encoding Blob of the public key.
 */
GroupManager.prototype.generateKeyPairPromise_ = function(useSync)
{
  var params = new RsaKeyParams(this.keySize_);

  return RsaAlgorithm.generateKeyPromise(params)
  .then(function(privateKey) {
    var privateKeyBlob = privateKey.getKeyBits();
    var publicKey = RsaAlgorithm.deriveEncryptKey(privateKeyBlob);
    var publicKeyBlob = publicKey.getKeyBits();

    return SyncPromise.resolve
      ({ privateKeyBlob: privateKeyBlob, publicKeyBlob: publicKeyBlob });
  });
};

/**
 * Create an E-KEY Data packet for the given public key.
 * @param {string} startTimeStamp The start time stamp string to put in the name.
 * @param {string} endTimeStamp The end time stamp string to put in the name.
 * @param {Blob} publicKeyBlob A Blob of the public key DER.
 * @return The Data packet.
 * @throws SecurityException for an error using the security KeyChain.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that returns the Data packet, or that
 * is rejected with SecurityException for an error using the security KeyChain.
 */
GroupManager.prototype.createEKeyDataPromise_ = function
  (startTimeStamp, endTimeStamp, publicKeyBlob, useSync)
{
  var name = new Name(this.namespace_);
  name.append(Encryptor.NAME_COMPONENT_E_KEY).append(startTimeStamp)
    .append(endTimeStamp);

  var data = new Data(name);
  data.getMetaInfo().setFreshnessPeriod
    (this.freshnessHours_ * GroupManager.MILLISECONDS_IN_HOUR);
  data.setContent(publicKeyBlob);

  return this.keyChain_.signPromise(data);
};

/**
 * Create a D-KEY Data packet with an EncryptedContent for the given private
 * key, encrypted with the certificate key.
 * @param {string} startTimeStamp The start time stamp string to put in the name.
 * @param {string} endTimeStamp The end time stamp string to put in the name.
 * @param {Name} keyName The key name to put in the data packet name and the
 * EncryptedContent key locator.
 * @param {Blob} privateKeyBlob A Blob of the encoded private key.
 * @param {Blob} certificateKey The certificate key encoding, used to encrypt
 * the private key.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that returns the Data packet, or that
 * is rejected with SecurityException for an error using the security KeyChain.
 */
GroupManager.prototype.createDKeyDataPromise_ = function
  (startTimeStamp, endTimeStamp, keyName, privateKeyBlob, certificateKey,
   useSync)
{
  var name = new Name(this.namespace_);
  name.append(Encryptor.NAME_COMPONENT_D_KEY);
  name.append(startTimeStamp).append(endTimeStamp);
  var data = new Data(name);
  data.getMetaInfo().setFreshnessPeriod
    (this.freshnessHours_ * GroupManager.MILLISECONDS_IN_HOUR);
  var encryptParams = new EncryptParams(EncryptAlgorithmType.RsaOaep);
  var thisManager = this;

  return Encryptor.encryptDataPromise
    (data, privateKeyBlob, keyName, certificateKey, encryptParams, useSync)
  .catch(function(ex) {
    // Consolidate errors such as InvalidKeyException.
    return SyncPromise.reject(SecurityException(new Error
      ("createDKeyData: Error in encryptData: " + ex)));
  })
  .then(function() {
    return thisManager.keyChain_.signPromise(data);
  });
};

GroupManager.MILLISECONDS_IN_HOUR = 3600 * 1000;
/**
 * Copyright (C) 2015-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * @author: From ndn-group-encrypt src/interval https://github.com/named-data/ndn-group-encrypt
 *
 * 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.
 */

/**
 * An Interval defines a time duration which contains a start timestamp and an
 * end timestamp. Create an Interval with one of these forms:
 * Interval(isValid).
 * Interval(startTime, endTime).
 * Interval(interval).
 * @param {boolean} isValid True to create a valid empty interval, false to
 * create an invalid interval.
 * @param {number} startTime The start time as milliseconds since Jan 1, 1970 UTC.
 * The start time must be less than the end time. To create an empty interval
 * (start time equals end time), use the constructor Interval(true).
 * @param {number} endTime The end time as milliseconds since Jan 1, 1970 UTC.
 * @param {Interval} interval The other interval with values to copy.
 * @note This class is an experimental feature. The API may change.
 * @constructor
 */
var Interval = function Interval(value, endTime)
{
  if (typeof value === 'object' && value instanceof Interval) {
    // Make a copy.
    this.startTime_ = value.startTime_;
    this.endTime_ = value.endTime_;
    this.isValid_ = value.isValid_;
  }
  else if (typeof value === 'number') {
    var startTime = value;

    if (!(startTime < endTime))
      throw new Error("Interval start time must be less than the end time");

    this.startTime_ = startTime;
    this.endTime_ = endTime;
    this.isValid_ = true;
  }
  else {
    var isValid = (value ? true : false);

    this.startTime_ = -Number.MAX_VALUE;
    this.endTime_ = -Number.MAX_VALUE;
    this.isValid_ = isValid;
  }
};

exports.Interval = Interval;

/**
 * Set this interval to have the same values as the other interval.
 * @param {Interval} other The other Interval with values to copy.
 */
Interval.prototype.set = function(other)
{
  this.startTime_ = other.startTime_;
  this.endTime_ = other.endTime_;
  this.isValid_ = other.isValid_;
};

/**
 * Check if the time point is in this interval.
 * @param {number} timePoint The time point to check as milliseconds since
 * Jan 1, 1970 UTC.
 * @return {boolean} True if timePoint is in this interval.
 * @throws Error if this Interval is invalid.
 */
Interval.prototype.covers = function(timePoint)
{
  if (!this.isValid_)
    throw new Error("Interval.covers: This Interval is invalid");

  if (this.isEmpty())
    return false;
  else
    return this.startTime_ <= timePoint && timePoint < this.endTime_;
};

/**
 * Set this Interval to the intersection of this and the other interval.
 * This and the other interval should be valid but either can be empty.
 * @param {Interval} interval The other Interval to intersect with.
 * @return {Interval} This Interval.
 * @throws Error if this Interval or the other interval is invalid.
 */
Interval.prototype.intersectWith = function(interval)
{
  if (!this.isValid_)
    throw new Error("Interval.intersectWith: This Interval is invalid");
  if (!interval.isValid_)
    throw new Error("Interval.intersectWith: The other Interval is invalid");

  if (this.isEmpty() || interval.isEmpty()) {
    // If either is empty, the result is empty.
    this.startTime_ = this.endTime_;
    return this;
  }

  if (this.startTime_ >= interval.endTime_ || this.endTime_ <= interval.startTime_) {
    // The two intervals don't have an intersection, so the result is empty.
    this.startTime_ = this.endTime_;
    return this;
  }

  // Get the start time.
  if (this.startTime_ <= interval.startTime_)
    this.startTime_ = interval.startTime_;

  // Get the end time.
  if (this.endTime_ > interval.endTime_)
    this.endTime_ = interval.endTime_;

  return this;
};

/**
 * Set this Interval to the union of this and the other interval.
 * This and the other interval should be valid but either can be empty.
 * This and the other interval should have an intersection. (Contiguous
 * intervals are not allowed.)
 * @param {Interval} interval The other Interval to union with.
 * @return {Interval} This Interval.
 * @throws Error if this Interval or the other interval is invalid, or if the
 * two intervals do not have an intersection.
 */
Interval.prototype.unionWith = function(interval)
{
  if (!this.isValid_)
    throw new Error("Interval.intersectWith: This Interval is invalid");
  if (!interval.isValid_)
    throw new Error("Interval.intersectWith: The other Interval is invalid");

  if (this.isEmpty()) {
    // This interval is empty, so use the other.
    this.startTime_ = interval.startTime_;
    this.endTime_ = interval.endTime_;
    return this;
  }

  if (interval.isEmpty())
    // The other interval is empty, so keep using this one.
    return this;

  if (this.startTime_ >= interval.endTime_ || this.endTime_ <= interval.startTime_)
    throw new Error
      ("Interval.unionWith: The two intervals do not have an intersection");

  // Get the start time.
  if (this.startTime_ > interval.startTime_)
    this.startTime_ = interval.startTime_;

  // Get the end time.
  if (this.endTime_ < interval.endTime_)
    this.endTime_ = interval.endTime_;

  return this;
};

/**
 * Get the start time.
 * @return {number} The start time as milliseconds since Jan 1, 1970 UTC.
 * @throws Error if this Interval is invalid.
 */
Interval.prototype.getStartTime = function()
{
  if (!this.isValid_)
    throw new Error("Interval.getStartTime: This Interval is invalid");
  return this.startTime_;
};

/**
 * Get the end time.
 * @return {number} The end time as milliseconds since Jan 1, 1970 UTC.
 * @throws Error if this Interval is invalid.
 */
Interval.prototype.getEndTime = function()
{
  if (!this.isValid_)
    throw new Error("Interval.getEndTime: This Interval is invalid");
  return this.endTime_;
};

/**
 * Check if this Interval is valid.
 * @return {boolean} True if this interval is valid, false if invalid.
 */
Interval.prototype.isValid = function() { return this.isValid_; };

/**
 * Check if this Interval is empty.
 * @return {boolean} True if this Interval is empty (start time equals end time),
 * false if not.
 * @throws Error if this Interval is invalid.
 */
Interval.prototype.isEmpty = function()
{
  if (!this.isValid_)
    throw new Error("Interval.isEmpty: This Interval is invalid");
  return this.startTime_ == this.endTime_;
};
/**
 * Copyright (C) 2015-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * @author: From ndn-group-encrypt src/producer-db https://github.com/named-data/ndn-group-encrypt
 *
 * 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.
 */

/** @ignore */
var SyncPromise = require('../util/sync-promise.js').SyncPromise;

/**
 * ProducerDb is a base class for the storage of keys for the producer. It contains
 * one table that maps time slots (to the nearest hour) to the content key
 * created for that time slot. A subclass must implement the methods. For
 * example, see Sqlite3ProducerDb (for Nodejs) or IndexedDbProducerDb (for the
 * browser).
 * @note This class is an experimental feature. The API may change.
 * @constructor
 */
var ProducerDb = function ProducerDb()
{
};

exports.ProducerDb = ProducerDb;

/**
 * Create a new ProducerDb.Error to report an error using ProducerDb
 * methods, wrapping the given error object.
 * Call with: throw new ProducerDb.Error(new Error("message")).
 * @constructor
 * @param {Error} error The exception created with new Error.
 */
ProducerDb.Error = function ProducerDbError(error)
{
  if (error) {
    error.__proto__ = ProducerDb.Error.prototype;
    return error;
  }
}

ProducerDb.Error.prototype = new Error();
ProducerDb.Error.prototype.name = "ProducerDbError";

/**
 * Check if a content key exists for the hour covering timeSlot.
 * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that returns true if there is a
 * content key for timeSlot (else false), or that is rejected with
 * ProducerDb.Error for a database error.
 */
ProducerDb.prototype.hasContentKeyPromise = function(timeSlot, useSync)
{
  return SyncPromise.reject(new Error
    ("ProducerDb.hasContentKeyPromise is not implemented"));
};

/**
 * Get the content key for the hour covering timeSlot.
 * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that returns a Blob with the encoded
 * key, or that is rejected with ProducerDb.Error if there is no key covering
 * timeSlot, or other database error
 */
ProducerDb.prototype.getContentKeyPromise = function(timeSlot, useSync)
{
  return SyncPromise.reject(new Error
    ("ProducerDb.getContentKeyPromise is not implemented"));
};

/**
 * Add key as the content key for the hour covering timeSlot.
 * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
 * @param {Blob} key The encoded key.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that fulfills when the key is added,
 * or that is rejected with ProducerDb.Error if a key for the same hour already
 * exists in the database, or other database error.
 */
ProducerDb.prototype.addContentKeyPromise = function
  (timeSlot, key, useSync)
{
  return SyncPromise.reject(new Error
    ("ProducerDb.addContentKeyPromise is not implemented"));
};

/**
 * Delete the content key for the hour covering timeSlot. If there is no key for
 * the time slot, do nothing.
 * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
 * @param {boolean} useSync (optional) If true then return a SyncPromise which
 * is already fulfilled. If omitted or false, this may return a SyncPromise or
 * an async Promise.
 * @return {Promise|SyncPromise} A promise that fulfills when the key is deleted
 * (or there is no such key), or that is rejected with ProducerDb.Error for a
 * database error.
 */
ProducerDb.prototype.deleteContentKeyPromise = function(timeSlot, useSync)
{
  return SyncPromise.reject(new Error
    ("ProducerDb.deleteContentKeyPromise is not implemented"));
};

/**
 * Get the hour-based time slot.
 * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
 * @return {number} The hour-based time slot as hours since Jan 1, 1970 UTC.
 */
ProducerDb.getFixedTimeSlot = function(timeSlot)
{
  return Math.floor(Math.round(timeSlot) / 3600000.0);
};
/**
 * Copyright (C) 2015-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * @author: From ndn-group-encrypt src/producer https://github.com/named-data/ndn-group-encrypt
 *
 * 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.
 */

/** @ignore */
var Name = require('../name.js').Name; /** @ignore */
var Interest = require('../interest.js').Interest; /** @ignore */
var Data = require('../data.js').Data; /** @ignore */
var Link = require('../link.js').Link; /** @ignore */
var NetworkNack = require('../network-nack.js').NetworkNack; /** @ignore */
var Exclude = require('../exclude.js').Exclude; /** @ignore */
var Encryptor = require('./algo/encryptor.js').Encryptor; /** @ignore */
var EncryptParams = require('./algo/encrypt-params.js').EncryptParams; /** @ignore */
var EncryptAlgorithmType = require('./algo/encrypt-params.js').EncryptAlgorithmType; /** @ignore */
var AesKeyParams = require('../security/key-params.js').AesKeyParams; /** @ignore */
var AesAlgorithm = require('./algo/aes-algorithm.js').AesAlgorithm; /** @ignore */
var Schedule = require('./schedule.js').Schedule; /** @ignore */
var EncryptError = require('./encrypt-error.js').EncryptError; /** @ignore */
var NdnCommon = require('../util/ndn-common.js').NdnCommon; /** @ignore */
var SyncPromise = require('../util/sync-promise.js').SyncPromise;

/**
 * A Producer manages content keys used to encrypt a data packet in the
 * group-based encryption protocol.
 * Create a Producer to use the given ProducerDb, Face and other values.
 *
 * A producer can produce data with a naming convention:
 *   /<prefix>/SAMPLE/<dataType>/[timestamp]
 *
 * The produced data packet is encrypted with a content key,
 * which is stored in the ProducerDb database.
 *
 * A producer also needs to produce data containing a content key
 * encrypted with E-KEYs. A producer can retrieve E-KEYs through the face,
 * and will re-try for at most repeatAttemps times when E-KEY retrieval fails.
 *
 * @param {Name} prefix The producer name prefix. This makes a copy of the Name.
 * @param {Name} dataType The dataType portion of the producer name. This makes
 * a copy of the Name.
 * @param {Face} face The face used to retrieve keys.
 * @param {KeyChain} keyChain The keyChain used to sign data packets.
 * @param {ProducerDb} database The ProducerDb database for storing keys.
 * @param {number} repeatAttempts (optional) The maximum retry for retrieving
 * keys. If omitted, use a default value of 3.
 * @param {Link} keyRetrievalLink (optional) The Link object to use in Interests
 * for key retrieval. This makes a copy of the Link object. If the Link object's
 * getDelegations().size() is zero, don't use it. If omitted, don't use a Link
 * object.
 * @note This class is an experimental feature. The API may change.
 * @constructor
 */
var Producer = function Producer
  (prefix, dataType, face, keyChain, database, repeatAttempts, keyRetrievalLink)
{
  this.face_ = face;
  this.keyChain_ = keyChain;
  this.database_ = database;
  this.maxRepeatAttempts_ = (repeatAttempts == undefined ? 3 : repeatAttempts);
  this.keyRetrievalLink_ =
    (keyRetrievalLink == undefined ? Producer.NO_LINK : new Link(keyRetrievalLink));

  // The map key is the key name URI string. The value is an object with fields
  // "keyName" and "keyInfo" where "keyName" is the same Name used for the key
  // name URI string, and "keyInfo" is the Producer.KeyInfo_.
  // (Use a string because we can't use the Name object as the key in JavaScript.)
  // (Also put the original Name in the value because we need to iterate over
  // eKeyInfo_ and we don't want to rebuild the Name from the name URI string.)
  this.eKeyInfo_ = {};
  // The map key is the time stamp. The value is a Producer.KeyRequest_.
  this.keyRequests_ = {};

  var fixedPrefix = new Name(prefix);
  var fixedDataType = new Name(dataType);

  // Fill ekeyInfo_ with all permutations of dataType, including the 'E-KEY'
  // component of the name. This will be used in createContentKey to send
  // interests without reconstructing names every time.
  fixedPrefix.append(Encryptor.NAME_COMPONENT_READ);
  while (fixedDataType.size() > 0) {
    var nodeName = new Name(fixedPrefix);
    nodeName.append(fixedDataType);
    nodeName.append(Encryptor.NAME_COMPONENT_E_KEY);

    this.eKeyInfo_[nodeName.toUri()] =
      { keyName: nodeName, keyInfo: new Producer.KeyInfo_() };
    fixedDataType = fixedDataType.getPrefix(-1);
  }
  fixedPrefix.append(dataType);
  this.namespace_ = new Name(prefix);
  this.namespace_.append(Encryptor.NAME_COMPONENT_SAMPLE);
  this.namespace_.append(dataType);
};

exports.Producer = Producer;

/**
 * Create the content key corresponding to the timeSlot. This first checks if
 * the content key exists. For an existing content key, this returns the
 * content key name directly. If the key does not exist, this creates one and
 * encrypts it using the corresponding E-KEYs. The encrypted content keys are
 * passed to the onEncryptedKeys callback.
 * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
 * @param {function} onEncryptedKeys If this creates a content key, then this
 * calls onEncryptedKeys(keys) where keys is a list of encrypted content key
 * Data packets. If onEncryptedKeys is null, this does not use it.
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onContentKeyName This calls onContentKeyName(contentKeyName)
 * with the content key name for the time slot. If onContentKeyName is null,
 * this does not use it. (A callback is needed because of async database
 * operations.)
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onError (optional) This calls onError(errorCode, message)
 * for an error, where errorCode is from EncryptError.ErrorCode and message is a
 * string. If omitted, use a default callback which does nothing.
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 */
Producer.prototype.createContentKey = function
  (timeSlot, onEncryptedKeys, onContentKeyName, onError)
{
  if (!onError)
    onError = Producer.defaultOnError;

  var hourSlot = Producer.getRoundedTimeSlot_(timeSlot);

  // Create the content key name.
  var contentKeyName = new Name(this.namespace_);
  contentKeyName.append(Encryptor.NAME_COMPONENT_C_KEY);
  contentKeyName.append(Schedule.toIsoString(hourSlot));

  var contentKeyBits;
  var thisProducer = this;

  // Check if we have created the content key before.
  this.database_.hasContentKeyPromise(timeSlot)
  .then(function(exists) {
    if (exists) {
      if (onContentKeyName != null)
        onContentKeyName(contentKeyName);
      return;
    }

    // We haven't created the content key. Create one and add it into the database.
    var aesParams = new AesKeyParams(128);
    contentKeyBits = AesAlgorithm.generateKey(aesParams).getKeyBits();
    thisProducer.database_.addContentKeyPromise(timeSlot, contentKeyBits)
    .then(function() {
      // Now we need to retrieve the E-KEYs for content key encryption.
      var timeCount = Math.round(timeSlot);
      thisProducer.keyRequests_[timeCount] =
        new Producer.KeyRequest_(thisProducer.getEKeyInfoSize_());
      var keyRequest = thisProducer.keyRequests_[timeCount];

      // Check if the current E-KEYs can cover the content key.
      var timeRange = new Exclude();
      Producer.excludeAfter
        (timeRange, new Name.Component(Schedule.toIsoString(timeSlot)));
      for (var keyNameUri in thisProducer.eKeyInfo_) {
         // For each current E-KEY.
        var entry = thisProducer.eKeyInfo_[keyNameUri];
        var keyInfo = entry.keyInfo;
        if (timeSlot < keyInfo.beginTimeSlot || timeSlot >= keyInfo.endTimeSlot) {
          // The current E-KEY cannot cover the content key, so retrieve one.
          keyRequest.repeatAttempts[keyNameUri] = 0;
          thisProducer.sendKeyInterest_
            (new Interest(entry.keyName).setExclude(timeRange).setChildSelector(1),
             timeSlot, onEncryptedKeys, onError);
        }
        else {
          // The current E-KEY can cover the content key.
          // Encrypt the content key directly.
          var eKeyName = new Name(entry.keyName);
          eKeyName.append(Schedule.toIsoString(keyInfo.beginTimeSlot));
          eKeyName.append(Schedule.toIsoString(keyInfo.endTimeSlot));
          thisProducer.encryptContentKeyPromise_
            (keyInfo.keyBits, eKeyName, timeSlot, onEncryptedKeys, onError);
        }
      }

      if (onContentKeyName != null)
        onContentKeyName(contentKeyName);
    });
  });
};

/**
 * Encrypt the given content with the content key that covers timeSlot, and
 * update the data packet with the encrypted content and an appropriate data
 * name.
 * @param {Data} data An empty Data object which is updated.
 * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
 * @param {Blob} content The content to encrypt.
 * @param {function} onComplete This calls onComplete() when the data packet has
 * been updated.
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onError (optional) This calls onError(errorCode, message)
 * for an error, where errorCode is from EncryptError.ErrorCode and message is a
 * string. If omitted, use a default callback which does nothing.
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 */
Producer.prototype.produce = function
  (data, timeSlot, content, onComplete, onError)
{
  if (!onError)
    onError = Producer.defaultOnError;

  var thisProducer = this;

  // Get a content key.
  this.createContentKey(timeSlot, null, function(contentKeyName) {
    thisProducer.database_.getContentKeyPromise(timeSlot)
    .then(function(contentKey) {
      // Produce data.
      var dataName = new Name(thisProducer.namespace_);
      dataName.append(Schedule.toIsoString(timeSlot));

      data.setName(dataName);
      var params = new EncryptParams(EncryptAlgorithmType.AesCbc, 16);
      return Encryptor.encryptData
        (data, content, contentKeyName, contentKey, params);
    })
    .then(function() {
      return thisProducer.keyChain_.signPromise(data);
    })
    .then(function() {
      try {
        onComplete();
      } catch (ex) {
        console.log("Error in onComplete: " + NdnCommon.getErrorWithStackTrace(ex));
      }
    }, function(error) {
      try {
        onError(EncryptError.ErrorCode.General, "" + error);
      } catch (ex) {
        console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
      }
    });
  }, onError);
};

/**
 * The default onError callback which does nothing.
 */
Producer.defaultOnError = function(errorCode, message)
{
  // Do nothing.
};

Producer.KeyInfo_ = function ProducerKeyInfo()
{
  this.beginTimeSlot = 0.0;
  this.endTimeSlot = 0.0;
  this.keyBits = null; // Blob
};

Producer.KeyRequest_ = function ProducerKeyRequest(interests)
{
  this.interestCount = interests; // number
  // The map key is the name URI string. The value is an int count.
  // (Use a string because we can't use the Name object as the key in JavaScript.)
  this.repeatAttempts = {};
  this.encryptedKeys = []; // of Data
};

/**
 * Round timeSlot to the nearest whole hour, so that we can store content keys
 * uniformly (by start of the hour).
 * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
 * @return {number} The start of the hour as milliseconds since Jan 1, 1970 UTC.
 */
Producer.getRoundedTimeSlot_ = function(timeSlot)
{
  return Math.round(Math.floor(Math.round(timeSlot) / 3600000.0) * 3600000.0);
}

/**
 * Send an interest with the given name through the face with callbacks to
 * handleCoveringKey_, handleTimeout_ and handleNetworkNack_.
 * @param {Interest} interest The interest to send.
 * @param {number} timeSlot The time slot, passed to handleCoveringKey_,
 * handleTimeout_ and handleNetworkNack_.
 * @param {function} onEncryptedKeys The OnEncryptedKeys callback, passed to
 * handleCoveringKey_, handleTimeout_ and handleNetworkNack_.
 * @param {function} onError This calls onError(errorCode, message) for an error.
 */
Producer.prototype.sendKeyInterest_ = function
  (interest, timeSlot, onEncryptedKeys, onError)
{
  var thisProducer = this;

  function onKey(interest, data) {
    thisProducer.handleCoveringKey_
      (interest, data, timeSlot, onEncryptedKeys, onError);
  }

  function onTimeout(interest) {
    thisProducer.handleTimeout_(interest, timeSlot, onEncryptedKeys, onError);
  }

  function onNetworkNack(interest, networkNack) {
    thisProducer.handleNetworkNack_
      (interest, networkNack, timeSlot, onEncryptedKeys, onError);
  }

  var request;
  if (this.keyRetrievalLink_.getDelegations().size() === 0)
    // We can use the supplied interest without copying.
    request = interest;
  else {
    // Copy the supplied interest and add the Link.
    request = new Interest(interest);
    // This will use a cached encoding if available.
    request.setLinkWireEncoding(this.keyRetrievalLink_.wireEncode());
  }

  this.face_.expressInterest(request, onKey, onTimeout, onNetworkNack);
};

/**
 * This is called from an expressInterest timeout to update the state of
 * keyRequest. Re-express the interest if the number of retrials is less than
 * the max limit.
 * @param {Interest} interest The timed-out interest.
 * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
 * @param {function} onEncryptedKeys When there are no more interests to process,
 * this calls onEncryptedKeys(keys) where keys is a list of encrypted content
 * key Data packets. If onEncryptedKeys is null, this does not use it.
 * @param {function} onError This calls onError(errorCode, message) for an error.
 */
Producer.prototype.handleTimeout_ = function
  (interest, timeSlot, onEncryptedKeys, onError)
{
  var timeCount = Math.round(timeSlot);
  var keyRequest = this.keyRequests_[timeCount];

  var interestName = interest.getName();
  var interestNameUri = interestName.toUri();

  if (keyRequest.repeatAttempts[interestNameUri] < this.maxRepeatAttempts_) {
    // Increase the retrial count.
    ++keyRequest.repeatAttempts[interestNameUri];
    this.sendKeyInterest_(interest, timeSlot, onEncryptedKeys, onError);
  }
  else
    // Treat an eventual timeout as a network Nack.
    this.handleNetworkNack_
      (interest, new NetworkNack(), timeSlot, onEncryptedKeys, onError);
};

/**
 * This is called from an expressInterest OnNetworkNack to handle a network
 * Nack for the E-KEY requested through the Interest. Decrease the outstanding
 * E-KEY interest count for the C-KEY corresponding to the timeSlot.
 * @param {Interest} interest The interest given to expressInterest.
 * @param {NetworkNack} networkNack The returned NetworkNack (unused).
 * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
 * @param {function} onEncryptedKeys When there are no more interests to process,
 * this calls onEncryptedKeys(keys) where keys is a list of encrypted content
 * key Data packets. If onEncryptedKeys is null, this does not use it.
 */
Producer.prototype.handleNetworkNack_ = function
  (interest, networkNack, timeSlot, onEncryptedKeys, onError)
{
  // We have run out of options....
  var timeCount = Math.round(timeSlot);
  this.updateKeyRequest_
    (this.keyRequests_[timeCount], timeCount, onEncryptedKeys);
};

/**
 * Decrease the count of outstanding E-KEY interests for the C-KEY for
 * timeCount. If the count decreases to 0, invoke onEncryptedKeys.
 * @param {Producer.KeyRequest_} keyRequest The KeyRequest with the
 * interestCount to update.
 * @param {number} timeCount The time count for indexing keyRequests_.
 * @param {function} onEncryptedKeys When there are no more interests to
 * process, this calls onEncryptedKeys(keys) where keys is a list of encrypted
 * content key Data packets. If onEncryptedKeys is null, this does not use it.
 */
Producer.prototype.updateKeyRequest_ = function
  (keyRequest, timeCount, onEncryptedKeys)
{
  --keyRequest.interestCount;
  if (keyRequest.interestCount == 0 && onEncryptedKeys != null) {
    try {
      onEncryptedKeys(keyRequest.encryptedKeys);
    } catch (ex) {
      console.log("Error in onEncryptedKeys: " + NdnCommon.getErrorWithStackTrace(ex));
    }
    delete this.keyRequests_[timeCount];
  }
};

/**
 * This is called from an expressInterest OnData to check that the encryption
 * key contained in data fits the timeSlot. This sends a refined interest if
 * required.
 * @param {Interest} interest The interest given to expressInterest.
 * @param {Data} data The fetched Data packet.
 * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
 * @param {function} onEncryptedKeys When there are no more interests to process,
 * this calls onEncryptedKeys(keys) where keys is a list of encrypted content
 * key Data packets. If onEncryptedKeys is null, this does not use it.
 * @param {function} onError This calls onError(errorCode, message) for an error.
 */
Producer.prototype.handleCoveringKey_ = function
  (interest, data, timeSlot, onEncryptedKeys, onError)
{
  var timeCount = Math.round(timeSlot);
  var keyRequest = this.keyRequests_[timeCount];

  var interestName = interest.getName();
  var interestNameUrl = interestName.toUri();
  var keyName = data.getName();

  var begin = Schedule.fromIsoString
    (keyName.get(Producer.START_TIME_STAMP_INDEX).getValue().toString());
  var end = Schedule.fromIsoString
    (keyName.get(Producer.END_TIME_STAMP_INDEX).getValue().toString());

  if (timeSlot >= end) {
    // If the received E-KEY covers some earlier period, try to retrieve an
    // E-KEY covering a later one.
    var timeRange = new Exclude(interest.getExclude());
    Producer.excludeBefore(timeRange, keyName.get(Producer.START_TIME_STAMP_INDEX));
    keyRequest.repeatAttempts[interestNameUrl] = 0;
    this.sendKeyInterest_
      (new Interest(interestName).setExclude(timeRange).setChildSelector(1),
       timeSlot, onEncryptedKeys, onError);
  }
  else {
    // If the received E-KEY covers the content key, encrypt the content.
    var encryptionKey = data.getContent();
    var thisProducer = this;
    this.encryptContentKeyPromise_
      (encryptionKey, keyName, timeSlot, onEncryptedKeys, onError)
    .then(function(success) {
      if (success) {
        var keyInfo = thisProducer.eKeyInfo_[interestNameUrl].keyInfo;
        keyInfo.beginTimeSlot = begin;
        keyInfo.endTimeSlot = end;
        keyInfo.keyBits = encryptionKey;
      }
    });
  }
};

/**
 * Get the content key from the database_ and encrypt it for the timeSlot
 * using encryptionKey.
 * @param {Blob} encryptionKey The encryption key value.
 * @param {Name} eKeyName The key name for the EncryptedContent.
 * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
 * @param {function} onEncryptedKeys When there are no more interests to process,
 * this calls onEncryptedKeys(keys) where keys is a list of encrypted content
 * key Data packets. If onEncryptedKeys is null, this does not use it.
 * @param {function} onError This calls onError(errorCode, message) for an error.
 * @return {Promise} A promise that returns true if encryption succeeds,
 * otherwise false.
 */
Producer.prototype.encryptContentKeyPromise_ = function
  (encryptionKey, eKeyName, timeSlot, onEncryptedKeys, onError)
{
  var timeCount = Math.round(timeSlot);
  var keyRequest = this.keyRequests_[timeCount];

  var keyName = new Name(this.namespace_);
  keyName.append(Encryptor.NAME_COMPONENT_C_KEY);
  keyName.append(Schedule.toIsoString(Producer.getRoundedTimeSlot_(timeSlot)));

  var cKeyData;
  var thisProducer = this;

  return this.database_.getContentKeyPromise(timeSlot)
  .then(function(contentKey) {
    cKeyData = new Data();
    cKeyData.setName(keyName);
    var params = new EncryptParams(EncryptAlgorithmType.RsaOaep);
    return Encryptor.encryptDataPromise
      (cKeyData, contentKey, eKeyName, encryptionKey, params);
  })
  .then(function() {
    return SyncPromise.resolve(true);
  }, function(error) {
    try {
      onError(EncryptError.ErrorCode.EncryptionFailure,
              "encryptData failed: " + error);
    } catch (ex) {
      console.log("Error in onError: " + NdnCommon.getErrorWithStackTrace(ex));
    }
    return SyncPromise.resolve(false);
  })
  .then(function(success) {
    if (success) {
      return thisProducer.keyChain_.signPromise(cKeyData)
      .then(function() {
        keyRequest.encryptedKeys.push(cKeyData);
        thisProducer.updateKeyRequest_(keyRequest, timeCount, onEncryptedKeys);
        return SyncPromise.resolve(true);
      });
    }
    else
      return SyncPromise.resolve(false);
  });
};

Producer.prototype.getEKeyInfoSize_ = function()
{
  // Note: This is really a method to find the key count in any object, but we
  // don't want to claim that it is a tested and general utility method.
  var size = 0;
  for (key in this.eKeyInfo_) {
    if (this.eKeyInfo_.hasOwnProperty(key))
      ++size;
  }

  return size;
};

// TODO: Move this to be the main representation inside the Exclude object.
/**
 * Create a new ExcludeEntry.
 * @param {Name.Component} component
 * @param {boolean} anyFollowsComponent
 */
Producer.ExcludeEntry = function ExcludeEntry(component, anyFollowsComponent)
{
  this.component_ = component;
  this.anyFollowsComponent_ = anyFollowsComponent;
};

/**
 * Create a list of ExcludeEntry from the Exclude object.
 * @param {Exclude} exclude The Exclude object to read.
 * @return {Array<ExcludeEntry>} A new array of ExcludeEntry.
 */
Producer.getExcludeEntries = function(exclude)
{
  var entries = [];

  for (var i = 0; i < exclude.size(); ++i) {
    if (exclude.get(i) == Exclude.ANY) {
      if (entries.length == 0)
        // Add a "beginning ANY".
        entries.push(new Producer.ExcludeEntry(new Name.Component(), true));
      else
        // Set anyFollowsComponent of the final component.
        entries[entries.length - 1].anyFollowsComponent_ = true;
    }
    else
      entries.push(new Producer.ExcludeEntry(exclude.get(i), false));
  }

  return entries;
};

/**
 * Set the Exclude object from the array of ExcludeEntry.
 * @param {Exclude} exclude The Exclude object to update.
 * @param {Array<ExcludeEntry>} entries The array of ExcludeEntry.
 */
Producer.setExcludeEntries = function(exclude, entries)
{
  exclude.clear();

  for (var i = 0; i < entries.length; ++i) {
    var entry = entries[i];

    if (i == 0 && entry.component_.getValue().size() == 0 &&
        entry.anyFollowsComponent_)
      // This is a "beginning ANY".
      exclude.appendAny();
    else {
      exclude.appendComponent(entry.component_);
      if (entry.anyFollowsComponent_)
        exclude.appendAny();
    }
  }
};

/**
 * Get the latest entry in the array whose component_ is less than or equal to
 * component.
 * @param {Array<ExcludeEntry>} entries The array of ExcludeEntry.
 * @param {Name.Component} component The component to compare.
 * @return {number} The index of the found entry, or -1 if not found.
 */
Producer.findEntryBeforeOrAt = function(entries, component)
{
  var i = entries.length - 1;
  while (i >= 0) {
    if (entries[i].component_.compare(component) <= 0)
      break;
    --i;
  }

  return i;
};

/**
 * Exclude all components in the range beginning at "from".
 * @param {Exclude} exclude The Exclude object to update.
 * @param {Name.Component} from The first component in the exclude range.
 */
Producer.excludeAfter = function(exclude, from)
{
  var entries = Producer.getExcludeEntries(exclude);

  var iNewFrom;
  var iFoundFrom = Producer.findEntryBeforeOrAt(entries, from);
  if (iFoundFrom < 0) {
    // There is no entry before "from" so insert at the beginning.
    entries.splice(0, 0, new Producer.ExcludeEntry(from, true));
    iNewFrom = 0;
  }
  else {
    var foundFrom = entries[iFoundFrom];

    if (!foundFrom.anyFollowsComponent_) {
      if (foundFrom.component_.equals(from)) {
        // There is already an entry with "from", so just set the "ANY" flag.
        foundFrom.anyFollowsComponent_ = true;
        iNewFrom = iFoundFrom;
      }
      else {
        // Insert following the entry before "from".
        entries.splice(iFoundFrom + 1, 0, new Producer.ExcludeEntry(from, true));
        iNewFrom = iFoundFrom + 1;
      }
    }
    else
      // The entry before "from" already has an "ANY" flag, so do nothing.
      iNewFrom = iFoundFrom;
  }

  // Remove intermediate entries since they are inside the range.
  var iRemoveBegin = iNewFrom + 1;
  var nRemoveNeeded = entries.length - iRemoveBegin;
  entries.splice(iRemoveBegin, nRemoveNeeded);

  Producer.setExcludeEntries(exclude, entries);
};

/**
 * Exclude all components in the range ending at "to".
 * @param {Exclude} exclude The Exclude object to update.
 * @param {Name.Component} to The last component in the exclude range.
 */
Producer.excludeBefore = function(exclude, to)
{
  Producer.excludeRange(exclude, new Name.Component(), to);
};

/**
 * Exclude all components in the range beginning at "from" and ending at "to".
 * @param {Exclude} exclude The Exclude object to update.
 * @param {Name.Component} from The first component in the exclude range.
 * @param {Name.Component} to The last component in the exclude range.
 */
Producer.excludeRange = function(exclude, from, to)
{
  if (from.compare(to) >= 0) {
    if (from.compare(to) == 0)
      throw new Error
        ("excludeRange: from == to. To exclude a single component, sue excludeOne.");
    else
      throw new Error
        ("excludeRange: from must be less than to. Invalid range: [" +
         from.toEscapedString() + ", " + to.toEscapedString() + "]");
  }

  var entries = Producer.getExcludeEntries(exclude);

  var iNewFrom;
  var iFoundFrom = Producer.findEntryBeforeOrAt(entries, from);
  if (iFoundFrom < 0) {
    // There is no entry before "from" so insert at the beginning.
    entries.splice(0, 0, new Producer.ExcludeEntry(from, true));
    iNewFrom = 0;
  }
  else {
    var foundFrom = entries[iFoundFrom];

    if (!foundFrom.anyFollowsComponent_) {
      if (foundFrom.component_.equals(from)) {
        // There is already an entry with "from", so just set the "ANY" flag.
        foundFrom.anyFollowsComponent_ = true;
        iNewFrom = iFoundFrom;
      }
      else {
        // Insert following the entry before "from".
        entries.splice(iFoundFrom + 1, 0, new Producer.ExcludeEntry(from, true));
        iNewFrom = iFoundFrom + 1;
      }
    }
    else
      // The entry before "from" already has an "ANY" flag, so do nothing.
      iNewFrom = iFoundFrom;
  }

  // We have at least one "from" before "to", so we know this will find an entry.
  var iFoundTo = Producer.findEntryBeforeOrAt(entries, to);
  var foundTo = entries[iFoundTo];
  if (iFoundTo == iNewFrom)
    // Insert the "to" immediately after the "from".
    entries.splice(iNewFrom + 1, 0, new Producer.ExcludeEntry(to, false));
  else {
    var iRemoveEnd;
    if (!foundTo.anyFollowsComponent_) {
      if (foundTo.component_.equals(to))
        // The "to" entry already exists. Remove up to it.
        iRemoveEnd = iFoundTo;
      else {
        // Insert following the previous entry, which will be removed.
        entries.splice(iFoundTo + 1, 0, new Producer.ExcludeEntry(to, false));
        iRemoveEnd = iFoundTo + 1;
      }
    }
    else
      // "to" follows a component which is already followed by "ANY", meaning
      // the new range now encompasses it, so remove the component.
      iRemoveEnd = iFoundTo + 1;

    // Remove intermediate entries since they are inside the range.
    var iRemoveBegin = iNewFrom + 1;
    var nRemoveNeeded = iRemoveEnd - iRemoveBegin;
    entries.splice(iRemoveBegin, nRemoveNeeded);
  }

  Producer.setExcludeEntries(exclude, entries);
};

Producer.START_TIME_STAMP_INDEX = -2;
Producer.END_TIME_STAMP_INDEX = -1;
Producer.NO_LINK = new Link();
/**
 * Copyright (C) 2015-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * @author: From ndn-group-encrypt src/repetitive-interval https://github.com/named-data/ndn-group-encrypt
 *
 * 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.
 */

/** @ignore */
var Interval = require('./interval.js').Interval;

/**
 * A RepetitiveInterval is an advanced interval which can repeat and can be used
 * to find a simple Interval that a time point falls in. Create a
 * RepetitiveInterval with one of these forms:
 * RepetitiveInterval() A RepetitiveInterval with one day duration, non-repeating..
 * RepetitiveInterval(startDate, endDate, intervalStartHour, intervalEndHour, nRepeats, repeatUnit).
 * RepetitiveInterval(repetitiveInterval).
 * @param {number} startDate The start date as milliseconds since Jan 1, 1970 UTC.
 * startDate must be earlier than or same as endDate. Or if repeatUnit is
 * RepetitiveInterval.RepeatUnit.NONE, then it must equal endDate.
 * @param {number} endDate The end date as milliseconds since Jan 1, 1970 UTC.
 * @param {number} intervalStartHour The start hour in the day, from 0 to 23.
 * intervalStartHour must be less than intervalEndHour.
 * @param {number} intervalEndHour The end hour in the day from 1 to 24.
 * @param {number} nRepeats (optional) Repeat the interval nRepeats repetitions,
 * every unit, until endDate. If ommitted, use 0.
 * @param {number} repeatUnit (optional) The unit of the repetition, from
 * RepetitiveInterval.RepeatUnit. If ommitted, use NONE. If this is NONE or
 * ommitted, then startDate must equal endDate.
 * @note This class is an experimental feature. The API may change.
 * @constructor
 */
var RepetitiveInterval = function RepetitiveInterval
  (startDate, endDate, intervalStartHour, intervalEndHour, nRepeats, repeatUnit)
{
  if (typeof startDate === 'object' && startDate instanceof RepetitiveInterval) {
    // Make a copy.
    repetitiveInterval = startDate;

    this.startDate_ = repetitiveInterval.startDate_;
    this.endDate_ = repetitiveInterval.endDate_;
    this.intervalStartHour_ = repetitiveInterval.intervalStartHour_;
    this.intervalEndHour_ = repetitiveInterval.intervalEndHour_;
    this.nRepeats_ = repetitiveInterval.nRepeats_;
    this.repeatUnit_ = repetitiveInterval.repeatUnit_;
  }
  else if (typeof startDate === 'number') {
    if (nRepeats == undefined)
      nRepeats = 0;
    if (repeatUnit == undefined)
      repeatUnit = RepetitiveInterval.RepeatUnit.NONE;

    this.startDate_ = RepetitiveInterval.toDateOnlyMilliseconds_(startDate);
    this.endDate_ = RepetitiveInterval.toDateOnlyMilliseconds_(endDate);
    this.intervalStartHour_ = Math.round(intervalStartHour);
    this.intervalEndHour_ = Math.round(intervalEndHour);
    this.nRepeats_ = Math.round(nRepeats);
    this.repeatUnit_ = repeatUnit;

    // Validate.
    if (!(this.intervalStartHour_ < this.intervalEndHour_))
      throw new Error("ReptitiveInterval: startHour must be less than endHour");
    if (!(this.startDate_ <= this.endDate_))
      throw new Error
        ("ReptitiveInterval: startDate must be earlier than or same as endDate");
    if (!(this.intervalStartHour_ >= 0))
      throw new Error("ReptitiveInterval: intervalStartHour must be non-negative");
    if (!(this.intervalEndHour_ >= 1 && this.intervalEndHour_ <= 24))
      throw new Error("ReptitiveInterval: intervalEndHour must be from 1 to 24");
    if (this.repeatUnit_ == RepetitiveInterval.RepeatUnit.NONE) {
      if (!(this.startDate_ == this.endDate_))
        throw new Error
          ("ReptitiveInterval: With RepeatUnit.NONE, startDate must equal endDate");
    }
  }
  else {
    // The default constructor.
    this.startDate_ = -Number.MAX_VALUE;
    this.endDate_ = -Number.MAX_VALUE;
    this.intervalStartHour_ = 0;
    this.intervalEndHour_ = 24;
    this.nRepeats_ = 0;
    this.repeatUnit_ = RepetitiveInterval.RepeatUnit.NONE;
  }
};

exports.RepetitiveInterval = RepetitiveInterval;

RepetitiveInterval.RepeatUnit = {
  NONE:  0,
  DAY:   1,
  MONTH: 2,
  YEAR:  3
};

/**
 * Get an interval that covers the time point. If there is no interval
 * covering the time point, this returns false for isPositive and returns a
 * negative interval.
 * @param {number} timePoint The time point as milliseconds since Jan 1, 1970 UTC.
 * @return {object} An associative array with fields
 * (isPositive, interval) where
 * isPositive is true if the returned interval is
 * positive or false if negative, and interval is the Interval covering the time
 * point or a negative interval if not found.
 */
RepetitiveInterval.prototype.getInterval = function(timePoint)
{
  var isPositive;
  var startTime;
  var endTime;

  if (!this.hasIntervalOnDate_(timePoint)) {
    // There is no interval on the date of timePoint.
    startTime = RepetitiveInterval.toDateOnlyMilliseconds_(timePoint);
    endTime = RepetitiveInterval.toDateOnlyMilliseconds_(timePoint) +
      24 * RepetitiveInterval.MILLISECONDS_IN_HOUR;
    isPositive = false;
  }
  else {
    // There is an interval on the date of timePoint.
    startTime = RepetitiveInterval.toDateOnlyMilliseconds_(timePoint) +
      this.intervalStartHour_ * RepetitiveInterval.MILLISECONDS_IN_HOUR;
    endTime = RepetitiveInterval.toDateOnlyMilliseconds_(timePoint) +
      this.intervalEndHour_ * RepetitiveInterval.MILLISECONDS_IN_HOUR;

    // check if in the time duration
    if (timePoint < startTime) {
      endTime = startTime;
      startTime = RepetitiveInterval.toDateOnlyMilliseconds_(timePoint);
      isPositive = false;
    }
    else if (timePoint > endTime) {
      startTime = endTime;
      endTime = RepetitiveInterval.toDateOnlyMilliseconds_(timePoint) +
        RepetitiveInterval.MILLISECONDS_IN_DAY;
      isPositive = false;
    }
    else
      isPositive = true;
  }

  return { isPositive: isPositive, interval: new Interval(startTime, endTime) };
};

/**
 * Compare this to the other RepetitiveInterval.
 * @param {RepetitiveInterval} other The other RepetitiveInterval to compare to.
 * @return {number} -1 if this is less than the other, 1 if greater and 0 if equal.
 */
RepetitiveInterval.prototype.compare = function(other)
{
  if (this.startDate_ < other.startDate_)
    return -1;
  if (this.startDate_ > other.startDate_)
    return 1;

  if (this.endDate_ < other.endDate_)
    return -1;
  if (this.endDate_ > other.endDate_)
    return 1;

  if (this.intervalStartHour_ < other.intervalStartHour_)
    return -1;
  if (this.intervalStartHour_ > other.intervalStartHour_)
    return 1;

  if (this.intervalEndHour_ < other.intervalEndHour_)
    return -1;
  if (this.intervalEndHour_ > other.intervalEndHour_)
    return 1;

  if (this.nRepeats_ < other.nRepeats_)
    return -1;
  if (this.nRepeats_ > other.nRepeats_)
    return 1;

  if (this.repeatUnit_ < other.repeatUnit_)
    return -1;
  if (this.repeatUnit_ > other.repeatUnit_)
    return 1;

  return 0;
};

/**
 * Get the start date.
 * @return {number} The start date as milliseconds since Jan 1, 1970 UTC.
 */
RepetitiveInterval.prototype.getStartDate = function()
{
  return this.startDate_;
};

/**
 * Get the end date.
 * @return {number} The end date as milliseconds since Jan 1, 1970 UTC.
 */
RepetitiveInterval.prototype.getEndDate = function()
{
  return this.endDate_;
};

/**
 * Get the interval start hour.
 * @return {number} The interval start hour.
 */
RepetitiveInterval.prototype.getIntervalStartHour = function()
{
  return this.intervalStartHour_;
}

/**
 * Get the interval end hour.
 * @return {number} The interval end hour.
 */
RepetitiveInterval.prototype.getIntervalEndHour = function()
{
  return this.intervalEndHour_;
};

/**
 * Get the number of repeats.
 * @return {number} The number of repeats.
 */
RepetitiveInterval.prototype.getNRepeats = function()
{
  return this.nRepeats_;
};

/**
 * Get the repeat unit.
 * @return {number} The repeat unit, from RepetitiveInterval.RepeatUnit.
 */
RepetitiveInterval.prototype.getRepeatUnit = function()
{
  return this.repeatUnit_;
};

/**
 * Check if the date of the time point is in any interval.
 * @param {number} timePoint The time point as milliseconds since Jan 1, 1970 UTC.
 * @return {boolean} True if the date of the time point is in any interval.
 */
RepetitiveInterval.prototype.hasIntervalOnDate_ = function(timePoint)
{
  var timePointDateMilliseconds = RepetitiveInterval.toDateOnlyMilliseconds_(timePoint);

  if (timePointDateMilliseconds < this.startDate_ ||
      timePointDateMilliseconds > this.endDate_)
    return false;

  if (this.repeatUnit_ == RepetitiveInterval.RepeatUnit.NONE)
    return true;
  else if (this.repeatUnit_ == RepetitiveInterval.RepeatUnit.DAY) {
    var durationDays = (timePointDateMilliseconds - this.startDate_) /
                        RepetitiveInterval.MILLISECONDS_IN_DAY;
    if (durationDays % this.nRepeats_ == 0)
      return true;
  }
  else {
    var timePointDate = new Date(timePointDateMilliseconds);
    var startDate = new Date(this.startDate_);

    if (this.repeatUnit_ == RepetitiveInterval.RepeatUnit.MONTH &&
             timePointDate.getUTCDate() == startDate.getUTCDate()) {
      var yearDifference =
        timePointDate.getUTCFullYear() - startDate.getUTCFullYear();
      var monthDifference = 12 * yearDifference +
        timePointDate.getUTCMonth() - startDate.getUTCMonth();
      if (monthDifference % this.nRepeats_ == 0)
        return true;
    }
    else if (this.repeatUnit_ == RepetitiveInterval.RepeatUnit.YEAR &&
             timePointDate.getUTCDate() == startDate.getUTCDate() &&
             timePointDate.getUTCMonth() == startDate.getUTCMonth()) {
      var difference = timePointDate.getUTCFullYear() - startDate.getUTCFullYear();
      if (difference % this.nRepeats_ == 0)
        return true;
    }
  }

  return false;
};

/**
 * Return a time point on the beginning of the date (without hours, minutes, etc.)
 * @param {number} timePoint The time point as milliseconds since Jan 1, 1970 UTC.
 * @return {number} A time point as milliseconds since Jan 1, 1970 UTC.
 */
RepetitiveInterval.toDateOnlyMilliseconds_ = function(timePoint)
{
  var result = Math.round(timePoint);
  result -= result % RepetitiveInterval.MILLISECONDS_IN_DAY;
  return result;
};

RepetitiveInterval.MILLISECONDS_IN_HOUR = 3600 * 1000;
RepetitiveInterval.MILLISECONDS_IN_DAY = 24 * 3600 * 1000;
/**
 * Copyright (C) 2015-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * @author: From ndn-group-encrypt src/schedule https://github.com/named-data/ndn-group-encrypt
 *
 * 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.
 */

/** @ignore */
var Interval = require('./interval.js').Interval; /** @ignore */
var RepetitiveInterval = require('./repetitive-interval.js').RepetitiveInterval; /** @ignore */
var Tlv = require('../encoding/tlv/tlv.js').Tlv; /** @ignore */
var TlvEncoder = require('../encoding/tlv/tlv-encoder.js').TlvEncoder; /** @ignore */
var TlvDecoder = require('../encoding/tlv/tlv-decoder.js').TlvDecoder; /** @ignore */
var Blob = require('../util/blob.js').Blob;

/**
 * Schedule is used to manage the times when a member can access data using two
 * sets of RepetitiveInterval as follows. whiteIntervalList is an ordered
 * set for the times a member is allowed to access to data, and
 * blackIntervalList is for the times a member is not allowed.
 * Create a Schedule with one of these forms:
 * Schedule() A Schedule with empty whiteIntervalList and blackIntervalList.
 * Schedule(schedule). A copy of the given schedule.
 * @note This class is an experimental feature. The API may change.
 * @constructor
 */
var Schedule = function Schedule(value)
{
  if (typeof value === 'object' && value instanceof Schedule) {
    // Make a copy.
    var schedule = value;

    // RepetitiveInterval is immutable, so we don't need to make a deep copy.
    this.whiteIntervalList_ = schedule.whiteIntervalList_.slice(0);
    this.blackIntervalList_ = schedule.blackIntervalList_.slice(0);
  }
  else {
    // The default constructor.
    this.whiteIntervalList_ = [];
    this.blackIntervalList_ = [];
  }
};

exports.Schedule = Schedule;

/**
 * Add the repetitiveInterval to the whiteIntervalList.
 * @param {RepetitiveInterval} repetitiveInterval The RepetitiveInterval to add.
 * If the list already contains the same RepetitiveInterval, this does nothing.
 * @return {Schedule} This Schedule so you can chain calls to add.
 */
Schedule.prototype.addWhiteInterval = function(repetitiveInterval)
{
  // RepetitiveInterval is immutable, so we don't need to make a copy.
  Schedule.sortedSetAdd_(this.whiteIntervalList_, repetitiveInterval);
  return this;
};

/**
 * Add the repetitiveInterval to the blackIntervalList.
 * @param {RepetitiveInterval} repetitiveInterval The RepetitiveInterval to add.
 * If the list already contains the same RepetitiveInterval, this does nothing.
 * @return {Schedule} This Schedule so you can chain calls to add.
 */
Schedule.prototype.addBlackInterval = function(repetitiveInterval)
{
  // RepetitiveInterval is immutable, so we don't need to make a copy.
  Schedule.sortedSetAdd_(this.blackIntervalList_, repetitiveInterval);
  return this;
};

/**
 * Get the interval that covers the time stamp. This iterates over the two
 * repetitive interval sets and find the shortest interval that allows a group
 * member to access the data. If there is no interval covering the time stamp,
 * this returns false for isPositive and a negative interval.
 * @param {number} timeStamp The time stamp as milliseconds since Jan 1, 1970 UTC.
 * @return {object} An associative array with fields
 * (isPositive, interval) where
 * isPositive is true if the returned interval is positive or false if negative,
 * and interval is the Interval covering the time stamp, or a negative interval
 * if not found.
 */
Schedule.prototype.getCoveringInterval = function(timeStamp)
{
  var blackPositiveResult = new Interval(true);
  var whitePositiveResult = new Interval(true);

  var blackNegativeResult = new Interval();
  var whiteNegativeResult = new Interval();

  // Get the black result.
  Schedule.calculateIntervalResult_
    (this.blackIntervalList_, timeStamp, blackPositiveResult, blackNegativeResult);

  // If the black positive result is not empty, then isPositive must be false.
  if (!blackPositiveResult.isEmpty())
    return { isPositive: false, interval: blackPositiveResult };

  // Get the whiteResult.
  Schedule.calculateIntervalResult_
    (this.whiteIntervalList_, timeStamp, whitePositiveResult, whiteNegativeResult);

  if (whitePositiveResult.isEmpty() && !whiteNegativeResult.isValid()) {
    // There is no white interval covering the time stamp.
    // Return false and a 24-hour interval.
    var timeStampDateOnly =
      RepetitiveInterval.toDateOnlyMilliseconds_(timeStamp);
    return { isPositive: false,
             interval:  new Interval
               (timeStampDateOnly,
                timeStampDateOnly + RepetitiveInterval.MILLISECONDS_IN_DAY) };
  }

  if (!whitePositiveResult.isEmpty()) {
    // There is white interval covering the time stamp.
    // Return true and calculate the intersection.
    if (blackNegativeResult.isValid())
      return { isPositive: true,
               interval: whitePositiveResult.intersectWith(blackNegativeResult) };
    else
      return  { isPositive: true, interval: whitePositiveResult };
  }
  else
    // There is no white interval covering the time stamp.
    // Return false.
    return { isPositive: false, interval: whiteNegativeResult };
};

/**
 * Encode this Schedule.
 * @return {Blob} The encoded buffer.
 */
Schedule.prototype.wireEncode = function()
{
  // For now, don't use WireFormat and hardcode to use TLV since the encoding
  // doesn't go out over the wire, only into the local SQL database.
  var encoder = new TlvEncoder(256);
  var saveLength = encoder.getLength();

  // Encode backwards.
  // Encode the blackIntervalList.
  var saveLengthForList = encoder.getLength();
  for (var i = this.blackIntervalList_.length - 1; i >= 0; i--)
    Schedule.encodeRepetitiveInterval_(this.blackIntervalList_[i], encoder);
  encoder.writeTypeAndLength
    (Tlv.Encrypt_BlackIntervalList, encoder.getLength() - saveLengthForList);

  // Encode the whiteIntervalList.
  saveLengthForList = encoder.getLength();
  for (var i = this.whiteIntervalList_.length - 1; i >= 0; i--)
    Schedule.encodeRepetitiveInterval_(this.whiteIntervalList_[i], encoder);
  encoder.writeTypeAndLength
    (Tlv.Encrypt_WhiteIntervalList, encoder.getLength() - saveLengthForList);

  encoder.writeTypeAndLength
    (Tlv.Encrypt_Schedule, encoder.getLength() - saveLength);

  return new Blob(encoder.getOutput(), false);
};

/**
 * Decode the input and update this Schedule object.
 * @param {Blob|Buffer} input The input buffer to decode. For Buffer, this reads
 * from position() to limit(), but does not change the position.
 * @throws DecodingException For invalid encoding.
 */
Schedule.prototype.wireDecode = function(input)
{
  // If input is a blob, get its buf().
  var decodeBuffer = typeof input === 'object' && input instanceof Blob ?
    input.buf() : input;

  // For now, don't use WireFormat and hardcode to use TLV since the encoding
  // doesn't go out over the wire, only into the local SQL database.
  var decoder = new TlvDecoder(decodeBuffer);

  var endOffset = decoder.readNestedTlvsStart(Tlv.Encrypt_Schedule);

  // Decode the whiteIntervalList.
  this.whiteIntervalList_ = [];
  var listEndOffset = decoder.readNestedTlvsStart(Tlv.Encrypt_WhiteIntervalList);
  while (decoder.getOffset() < listEndOffset)
    Schedule.sortedSetAdd_
      (this.whiteIntervalList_, Schedule.decodeRepetitiveInterval_(decoder));
  decoder.finishNestedTlvs(listEndOffset);

  // Decode the blackIntervalList.
  this.blackIntervalList_ = [];
  listEndOffset = decoder.readNestedTlvsStart(Tlv.Encrypt_BlackIntervalList);
  while (decoder.getOffset() < listEndOffset)
    Schedule.sortedSetAdd_
      (this.blackIntervalList_, Schedule.decodeRepetitiveInterval_(decoder));
  decoder.finishNestedTlvs(listEndOffset);

  decoder.finishNestedTlvs(endOffset);
};

/**
 * Insert element into the list, sorted using element.compare(). If it is a
 * duplicate of an existing list element, don't add it.
 */
Schedule.sortedSetAdd_ = function(list, element)
{
  // Find the index of the first element where it is not less than element.
  var i = 0;
  while (i < list.length) {
    var comparison = list[i].compare(element);
    if (comparison == 0)
      // Don't add a duplicate.
      return;
    if (!(comparison < 0))
      break;

    ++i;
  }

  list.splice(i, 0, element);
};

/**
 * Encode the RepetitiveInterval as NDN-TLV to the encoder.
 * @param {RepetitiveInterval} repetitiveInterval The RepetitiveInterval to encode.
 * @param {TlvEncoder} encoder The TlvEncoder to receive the encoding.
 */
Schedule.encodeRepetitiveInterval_ = function(repetitiveInterval, encoder)
{
  var saveLength = encoder.getLength();

  // Encode backwards.
  // The RepeatUnit enum has the same values as the encoding.
  encoder.writeNonNegativeIntegerTlv
    (Tlv.Encrypt_RepeatUnit, repetitiveInterval.getRepeatUnit());
  encoder.writeNonNegativeIntegerTlv
    (Tlv.Encrypt_NRepeats, repetitiveInterval.getNRepeats());
  encoder.writeNonNegativeIntegerTlv
    (Tlv.Encrypt_IntervalEndHour, repetitiveInterval.getIntervalEndHour());
  encoder.writeNonNegativeIntegerTlv
    (Tlv.Encrypt_IntervalStartHour, repetitiveInterval.getIntervalStartHour());
  // Use Blob to convert the string to UTF8 encoding.
  encoder.writeBlobTlv(Tlv.Encrypt_EndDate,
    new Blob(Schedule.toIsoString(repetitiveInterval.getEndDate())).buf());
  encoder.writeBlobTlv(Tlv.Encrypt_StartDate,
    new Blob(Schedule.toIsoString(repetitiveInterval.getStartDate())).buf());

  encoder.writeTypeAndLength
    (Tlv.Encrypt_RepetitiveInterval, encoder.getLength() - saveLength);
};

/**
 * Decode the input as an NDN-TLV RepetitiveInterval.
 * @param {TlvDecoder} decoder The decoder with the input to decode.
 * @return {RepetitiveInterval} A new RepetitiveInterval with the decoded result.
 */
Schedule.decodeRepetitiveInterval_ = function(decoder)
{
  var endOffset = decoder.readNestedTlvsStart(Tlv.Encrypt_RepetitiveInterval);

  // Use Blob to convert UTF8 to a string.
  var startDate = Schedule.fromIsoString
    (new Blob(decoder.readBlobTlv(Tlv.Encrypt_StartDate), true).toString());
  var endDate = Schedule.fromIsoString
    (new Blob(decoder.readBlobTlv(Tlv.Encrypt_EndDate), true).toString());
  var startHour = decoder.readNonNegativeIntegerTlv(Tlv.Encrypt_IntervalStartHour);
  var endHour = decoder.readNonNegativeIntegerTlv(Tlv.Encrypt_IntervalEndHour);
  var nRepeats = decoder.readNonNegativeIntegerTlv(Tlv.Encrypt_NRepeats);

  // The RepeatUnit enum has the same values as the encoding.
  var repeatUnit = decoder.readNonNegativeIntegerTlv(Tlv.Encrypt_RepeatUnit);

  decoder.finishNestedTlvs(endOffset);
  return new RepetitiveInterval
    (startDate, endDate, startHour, endHour, nRepeats, repeatUnit);
};

/**
 * A helper function to calculate black interval results or white interval
 * results.
 * @param {Array} list The set of RepetitiveInterval, which can be the white
 * list or the black list.
 * @param {number} timeStamp The time stamp as milliseconds since Jan 1, 1970 UTC.
 * @param {Interval} positiveResult The positive result which is updated.
 * @param {Interval} negativeResult The negative result which is updated.
 */
Schedule.calculateIntervalResult_ = function
  (list, timeStamp, positiveResult, negativeResult)
{
  for (var i = 0; i < list.length; ++i) {
    var element = list[i];

    var result = element.getInterval(timeStamp);
    var tempInterval = result.interval;
    if (result.isPositive == true)
      positiveResult.unionWith(tempInterval);
    else {
      if (!negativeResult.isValid())
        negativeResult.set(tempInterval);
      else
        negativeResult.intersectWith(tempInterval);
    }
  }
};

/**
 * Convert a UNIX timestamp to ISO time representation with the "T" in the middle.
 * @param {number} msSince1970 Timestamp as milliseconds since Jan 1, 1970 UTC.
 * @return {string} The string representation.
 */
Schedule.toIsoString = function(msSince1970)
{
  var utcTime = new Date(Math.round(msSince1970));
  return utcTime.getUTCFullYear() +
         Schedule.to2DigitString(utcTime.getUTCMonth() + 1) +
         Schedule.to2DigitString(utcTime.getUTCDate()) +
         "T" +
         Schedule.to2DigitString(utcTime.getUTCHours()) +
         Schedule.to2DigitString(utcTime.getUTCMinutes()) +
         Schedule.to2DigitString(utcTime.getUTCSeconds());
};

/**
 * A private method to zero pad an integer to 2 digits.
 * @param {number} x The number to pad.  Assume it is a non-negative integer.
 * @return {string} The padded string.
 */
Schedule.to2DigitString = function(x)
{
  var result = x.toString();
  return result.length === 1 ? "0" + result : result;
};

/**
 * Convert an ISO time representation with the "T" in the middle to a UNIX
 * timestamp.
 * @param {string} timeString The ISO time representation.
 * @return {number} The timestamp as milliseconds since Jan 1, 1970 UTC.
 */
Schedule.fromIsoString = function(timeString)
{
  if (timeString.length != 15 || timeString.substr(8, 1) != 'T')
    throw new Error("fromIsoString: Format is not the expected yyyymmddThhmmss");

  return Date.UTC
    (parseInt(timeString.substr(0, 4)),
     parseInt(timeString.substr(4, 2) - 1),
     parseInt(timeString.substr(6, 2)),
     parseInt(timeString.substr(9, 2)),
     parseInt(timeString.substr(11, 2)),
     parseInt(timeString.substr(13, 2)));
};
/**
 * Copyright (C) 2015-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

// Don't require modules since this is meant for the browser, not Node.js.

/**
 * IndexedDbConsumerDb extends ConsumerDb to implement the storage of decryption
 * keys for the consumer using the browser's IndexedDB service.
 * Create an IndexedDbConsumerDb to use the given IndexedDB database name.
 * @param {string} databaseName IndexedDB database name.
 * @note This class is an experimental feature. The API may change.
 * @constructor
 */
var IndexedDbConsumerDb = function IndexedDbConsumerDb(databaseName)
{
  ConsumerDb.call(this);

  this.database = new Dexie(databaseName);
  this.database.version(1).stores({
    // "keyName" is the key name URI // string
    //   (Note: In SQLite3, the key name is the TLV encoded bytes, but we can't
    //   index on a byte array in IndexedDb.)
    // "key" is the key bytes // Uint8Array
    decryptionKeys: "keyName"
  });
  this.database.open();
};

IndexedDbConsumerDb.prototype = new ConsumerDb();
IndexedDbConsumerDb.prototype.name = "IndexedDbConsumerDb";

/**
 * Get the key with keyName from the database.
 * @param {Name} keyName The key name.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise that returns a Blob with the encoded key (or an
 * isNull Blob if cannot find the key with keyName), or that is
 * rejected with ConsumerDb.Error for a database error.
 */
IndexedDbConsumerDb.prototype.getKeyPromise = function(keyName, useSync)
{
  if (useSync)
    return Promise.reject(new ConsumerDb.Error(new Error
      ("IndexedDbConsumerDb.getKeyPromise is only supported for async")));

  return this.database.decryptionKeys.get(keyName.toUri())
  .then(function(decryptionKeysEntry) {
    if (decryptionKeysEntry)
      return Promise.resolve(new Blob(decryptionKeysEntry.key));
    else
      return Promise.resolve(new Blob());
  })
  .catch(function(ex) {
    return Promise.reject(new ConsumerDb.Error(new Error
      ("IndexedDbConsumerDb.getKeyPromise: Error: " + ex)));
  });
};

/**
 * Add the key with keyName and keyBlob to the database.
 * @param {Name} keyName The key name.
 * @param {Blob} keyBlob The encoded key.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise that fulfills when the key is added, or that
 * is rejected with ConsumerDb.Error if a key with the same keyName already
 * exists, or other database error.
 */
IndexedDbConsumerDb.prototype.addKeyPromise = function(keyName, keyBlob, useSync)
{
  if (useSync)
    return Promise.reject(new ConsumerDb.Error(new Error
      ("IndexedDbConsumerDb.addKeyPromise is only supported for async")));

  // Add rejects if the primary key already exists.
  return this.database.decryptionKeys.add
    ({ keyName: keyName.toUri(), key: keyBlob.buf() })
  .catch(function(ex) {
    return Promise.reject(new ConsumerDb.Error(new Error
      ("IndexedDbConsumerDb.addKeyPromise: Error: " + ex)));
  });
};

/**
 * Delete the key with keyName from the database. If there is no key with
 * keyName, do nothing.
 * @param {Name} keyName The key name.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise that fulfills when the key is deleted (or there
 * is no such key), or that is rejected with ConsumerDb.Error for a database
 * error.
 */
IndexedDbConsumerDb.prototype.deleteKeyPromise = function(keyName, useSync)
{
  if (useSync)
    return Promise.reject(new ConsumerDb.Error(new Error
      ("IndexedDbConsumerDb.deleteKeyPromise is only supported for async")));

  return this.database.decryptionKeys.delete(keyName.toUri())
  .catch(function(ex) {
    return Promise.reject(new ConsumerDb.Error(new Error
      ("IndexedDbConsumerDb.deleteKeyPromise: Error: " + ex)));
  });
};
/**
 * Copyright (C) 2015-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

// Don't require modules since this is meant for the browser, not Node.js.

/**
 * IndexedDbGroupManagerDb extends GroupManagerDb to implement the storage of
 * data used by the GroupManager using the browser's IndexedDB service.
 * Create an IndexedDbGroupManagerDb to use the given IndexedDB database name.
 * @param {string} databaseName IndexedDB database name.
 * @note This class is an experimental feature. The API may change.
 * @constructor
 */
var IndexedDbGroupManagerDb = function IndexedDbGroupManagerDb(databaseName)
{
  GroupManagerDb.call(this);

  this.database = new Dexie(databaseName);
  this.database.version(1).stores({
    // "scheduleId" is the schedule ID, auto incremented // number
    // "scheduleName" is the schedule name, unique // string
    // "schedule" is the TLV-encoded schedule // Uint8Array
    schedules: "++scheduleId, &scheduleName",

    // "memberNameUri" is the member name URI // string
    //   (Note: In SQLite3, the member name index is the TLV encoded bytes, but
    //   we can't index on a byte array in IndexedDb.)
    //   (Note: The SQLite3 table also has an auto-incremented member ID primary
    //   key, but is not used so we omit it to simplify.)
    // "memberName" is the TLV-encoded member name (same as memberNameUri // Uint8Array
    // "scheduleId" is the schedule ID, linked to the schedules table // number
    //   (Note: The SQLite3 table has a foreign key to the schedules table with
    //   cascade update and delete, but we have to handle it manually.)
    // "keyName" is the TLV-encoded key name // Uint8Array
    // "publicKey" is the encoded key bytes // Uint8Array
    members: "memberNameUri, scheduleId"
  });
  this.database.open();
};

IndexedDbGroupManagerDb.prototype = new GroupManagerDb();
IndexedDbGroupManagerDb.prototype.name = "IndexedDbGroupManagerDb";

////////////////////////////////////////////////////// Schedule management.

/**
 * Check if there is a schedule with the given name.
 * @param {string} name The name of the schedule.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise that returns true if there is a schedule (else
 * false), or that is rejected with GroupManagerDb.Error for a database error.
 */
IndexedDbGroupManagerDb.prototype.hasSchedulePromise = function(name, useSync)
{
  if (useSync)
    return Promise.reject(new GroupManagerDb.Error(new Error
      ("IndexedDbGroupManagerDb.hasSchedulePromise is only supported for async")));

  return this.getScheduleIdPromise_(name)
  .then(function(scheduleId) {
    return Promise.resolve(scheduleId != -1);
  });
};

/**
 * List all the names of the schedules.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise that returns a new array of string with the names
 * of all schedules, or that is rejected with GroupManagerDb.Error for a
 * database error.
 */
IndexedDbGroupManagerDb.prototype.listAllScheduleNamesPromise = function(useSync)
{
  if (useSync)
    return Promise.reject(new GroupManagerDb.Error(new Error
      ("IndexedDbGroupManagerDb.listAllScheduleNamesPromise is only supported for async")));

  var list = [];
  return this.database.schedules.each(function(entry) {
    list.push(entry.scheduleName);
  })
  .then(function() {
    return Promise.resolve(list);
  })
  .catch(function(ex) {
    return Promise.reject(new GroupManagerDb.Error(new Error
      ("IndexedDbGroupManagerDb.listAllScheduleNamesPromise: Error: " + ex)));
  });
};

/**
 * Get a schedule with the given name.
 * @param {string} name The name of the schedule.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise that returns a new Schedule object, or that is
 * rejected with GroupManagerDb.Error if the schedule does not exist or other
 * database error.
 */
IndexedDbGroupManagerDb.prototype.getSchedulePromise = function(name, useSync)
{
  if (useSync)
    return Promise.reject(new GroupManagerDb.Error(new Error
      ("IndexedDbGroupManagerDb.getSchedulePromise is only supported for async")));

  var thisManager = this;
  // Use getScheduleIdPromise_ to handle the search on the non-primary key.
  return this.getScheduleIdPromise_(name)
  .then(function(scheduleId) {
    if (scheduleId != -1) {
      return thisManager.database.schedules.get(scheduleId)
      .then(function(entry) {
        // We expect entry to be found, and don't expect an error decoding.
        var schedule = new Schedule();
        schedule.wireDecode(new Blob(entry.schedule, false));
        return Promise.resolve(schedule);
      })
      .catch(function(ex) {
        return Promise.reject(new GroupManagerDb.Error(new Error
          ("IndexedDbGroupManagerDb.getSchedulePromise: Error: " + ex)));
      });
    }
    else
      return Promise.reject(new GroupManagerDb.Error(new Error
        ("IndexedDbGroupManagerDb.getSchedulePromise: Cannot get the result from the database")));
  });
};

/**
 * For each member using the given schedule, get the name and public key DER
 * of the member's key.
 * @param {string} name The name of the schedule.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise that returns a new array of object (where
 * "keyName" is the Name of the public key and "publicKey" is the Blob of the
 * public key DER), or that is rejected with GroupManagerDb.Error for a database
 * error. Note that the member's identity name is keyName.getPrefix(-1). If the
 * schedule name is not found, the list is empty.
 */
IndexedDbGroupManagerDb.prototype.getScheduleMembersPromise = function
  (name, useSync)
{
  if (useSync)
    return Promise.reject(new GroupManagerDb.Error(new Error
      ("IndexedDbGroupManagerDb.getScheduleMembersPromise is only supported for async")));

  var list = [];
  var thisManager = this;
  // There is only one matching schedule ID, so we can just look it up instead
  // of doing a more complicated join.
  return this.getScheduleIdPromise_(name)
  .then(function(scheduleId) {
    if (scheduleId == -1)
      // Return the empty list.
      return Promise.resolve(list);

    var onEntryError = null;
    return thisManager.database.members.where("scheduleId").equals(scheduleId)
    .each(function(entry) {
      try {
        var keyName = new Name();
        keyName.wireDecode(new Blob(entry.keyName, false), TlvWireFormat.get());

        list.push({ keyName: keyName, publicKey: new Blob(entry.publicKey, false) });
      } catch (ex) {
        // We don't expect this to happen.
        onEntryError = new GroupManagerDb.Error(new Error
          ("IndexedDbGroupManagerDb.getScheduleMembersPromise: Error decoding name: " + ex));
      }
    })
    .then(function() {
      if (onEntryError)
        // We got an error decoding.
        return Promise.reject(onEntryError);
      else
        return Promise.resolve(list);
    }, function(ex) {
      return Promise.reject(new GroupManagerDb.Error(new Error
        ("IndexedDbGroupManagerDb.getScheduleMembersPromise: Error: " + ex)));
    });
  });
};

/**
 * Add a schedule with the given name.
 * @param {string} name The name of the schedule. The name cannot be empty.
 * @param {Schedule} schedule The Schedule to add.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise that fulfills when the schedule is added, or that
 * is rejected with GroupManagerDb.Error if a schedule with the same name
 * already exists, if the name is empty, or other database error.
 */
IndexedDbGroupManagerDb.prototype.addSchedulePromise = function
  (name, schedule, useSync)
{
  if (useSync)
    return Promise.reject(new GroupManagerDb.Error(new Error
      ("IndexedDbGroupManagerDb.addSchedulePromise is only supported for async")));

  if (name.length == 0)
    return Promise.reject(new GroupManagerDb.Error
      ("IndexedDbGroupManagerDb.addSchedulePromise: The schedule name cannot be empty"));

  // Add rejects if the primary key already exists.
  return this.database.schedules.add
    ({ scheduleName: name, schedule: schedule.wireEncode().buf() })
  .catch(function(ex) {
    return Promise.reject(new GroupManagerDb.Error(new Error
      ("IndexedDbGroupManagerDb.addContentKeyPromise: Error: " + ex)));
  });
};

/**
 * Delete the schedule with the given name. Also delete members which use this
 * schedule. If there is no schedule with the name, then do nothing.
 * @param {string} name The name of the schedule.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise that fulfills when the schedule is deleted (or
 * there is no such schedule), or that is rejected with GroupManagerDb.Error for
 * a database error.
 */
IndexedDbGroupManagerDb.prototype.deleteSchedulePromise = function
  (name, useSync)
{
  if (useSync)
    return Promise.reject(new GroupManagerDb.Error(new Error
      ("IndexedDbGroupManagerDb.deleteSchedulePromise is only supported for async")));

  var scheduleId;
  var thisManager = this;
  return this.getScheduleIdPromise_(name)
  .then(function(localScheduleId) {
    scheduleId = localScheduleId;

    // Get the members which use this schedule.
    return thisManager.database.members.where("scheduleId").equals(scheduleId).toArray();
  })
  .then(function(membersEntries) {
    // Delete the members.
    var promises = membersEntries.map(function(entry) {
      return thisManager.database.members.delete(entry.memberNameUri);
    });
    return Promise.all(promises);
  })
  .then(function() {
    // Now delete the schedule.
    return thisManager.database.schedules.delete(scheduleId);
  })
  .catch(function(ex) {
    return Promise.reject(new GroupManagerDb.Error(new Error
      ("IndexedDbGroupManagerDb.deleteSchedulePromise: Error: " + ex)));
  });
};

/**
 * Rename a schedule with oldName to newName.
 * @param {string} oldName The name of the schedule to be renamed.
 * @param {string} newName The new name of the schedule. The name cannot be empty.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise that fulfills when the schedule is renamed, or
 * that is rejected with GroupManagerDb.Error if a schedule with newName already
 * exists, if the schedule with oldName does not exist, if newName is empty, or
 * other database error.
 */
IndexedDbGroupManagerDb.prototype.renameSchedulePromise = function
  (oldName, newName, useSync)
{
  if (useSync)
    return Promise.reject(new GroupManagerDb.Error(new Error
      ("IndexedDbGroupManagerDb.renameSchedulePromise is only supported for async")));

  if (newName.length == 0)
    return Promise.reject(new GroupManagerDb.Error(new Error
      ("IndexedDbGroupManagerDb.renameSchedule: The schedule newName cannot be empty")));

  var thisManager = this;
  return this.getScheduleIdPromise_(oldName)
  .then(function(scheduleId) {
    if (scheduleId == -1)
      return Promise.reject(new GroupManagerDb.Error(new Error
        ("IndexedDbGroupManagerDb.renameSchedule: The schedule oldName does not exist")));

    return thisManager.database.schedules.update
      (scheduleId, { scheduleName: newName })
    .catch(function(ex) {
      return Promise.reject(new GroupManagerDb.Error(new Error
        ("IndexedDbGroupManagerDb.renameSchedulePromise: Error: " + ex)));
    });
  });
};

/**
 * Update the schedule with name and replace the old object with the given
 * schedule. Otherwise, if no schedule with name exists, a new schedule
 * with name and the given schedule will be added to database.
 * @param {string} name The name of the schedule. The name cannot be empty.
 * @param {Schedule} schedule The Schedule to update or add.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise that fulfills when the schedule is updated, or
 * that is rejected with GroupManagerDb.Error if the name is empty, or other
 * database error.
 */
IndexedDbGroupManagerDb.prototype.updateSchedulePromise = function
  (name, schedule, useSync)
{
  if (useSync)
    return Promise.reject(new GroupManagerDb.Error(new Error
      ("IndexedDbGroupManagerDb.updateSchedulePromise is only supported for async")));

  var thisManager = this;
  return this.getScheduleIdPromise_(name)
  .then(function(scheduleId) {
    if (scheduleId == -1)
      return thisManager.addSchedulePromise(name, schedule);

    return thisManager.database.schedules.update
      (scheduleId, { schedule: schedule.wireEncode().buf() })
    .catch(function(ex) {
      return Promise.reject(new GroupManagerDb.Error(new Error
        ("IndexedDbGroupManagerDb.updateSchedulePromise: Error: " + ex)));
    });
  });
};

////////////////////////////////////////////////////// Member management.

/**
 * Check if there is a member with the given identity name.
 * @param {Name} identity The member's identity name.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise that returns true if there is a member (else
 * false), or that is rejected with GroupManagerDb.Error for a database error.
 */
IndexedDbGroupManagerDb.prototype.hasMemberPromise = function(identity, useSync)
{
  if (useSync)
    return Promise.reject(new GroupManagerDb.Error(new Error
      ("IndexedDbGroupManagerDb.hasMemberPromise is only supported for async")));

  return this.database.members.get(identity.toUri())
  .then(function(entry) {
    return Promise.resolve(entry != undefined);
  })
  .catch(function(ex) {
    return Promise.reject(new GroupManagerDb.Error(new Error
      ("IndexedDbGroupManagerDb.hasMemberPromise: Error: " + ex)));
  });
};

/**
 * List all the members.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise that returns a new array of Name with the names
 * of all members, or that is rejected with GroupManagerDb.Error for a
 * database error.
 */
IndexedDbGroupManagerDb.prototype.listAllMembersPromise = function(useSync)
{
  if (useSync)
    return Promise.reject(new GroupManagerDb.Error(new Error
      ("IndexedDbGroupManagerDb.listAllMembersPromise is only supported for async")));

  var list = [];
  var onEntryError = null;
  return this.database.members.each(function(entry) {
    try {
      var identity = new Name();
      identity.wireDecode(new Blob(entry.memberName, false), TlvWireFormat.get());
      list.push(identity);
    } catch (ex) {
      // We don't expect this to happen.
      onEntryError = new GroupManagerDb.Error(new Error
        ("IndexedDbGroupManagerDb.listAllMembersPromise: Error decoding name: " + ex));
    }
  })
  .then(function() {
    if (onEntryError)
      // We got an error decoding.
      return Promise.reject(onEntryError);
    else
      return Promise.resolve(list);
  }, function(ex) {
    return Promise.reject(new GroupManagerDb.Error(new Error
      ("IndexedDbGroupManagerDb.listAllMembersPromise: Error: " + ex)));
  });
};

/**
 * Get the name of the schedule for the given member's identity name.
 * @param {Name} identity The member's identity name.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise that returns the string schedule name, or that is
 * rejected with GroupManagerDb.Error if there's no member with the given
 * identity name in the database, or other database error.
 */
IndexedDbGroupManagerDb.prototype.getMemberSchedulePromise = function
  (identity, useSync)
{
  if (useSync)
    return Promise.reject(new GroupManagerDb.Error(new Error
      ("IndexedDbGroupManagerDb.getMemberSchedulePromise is only supported for async")));

  var thisManager = this;
  return this.database.members.get(identity.toUri())
  .then(function(membersEntry) {
    if (!membersEntry)
      throw new Error("The member identity name does not exist in the database");

    return thisManager.database.schedules.get(membersEntry.scheduleId);
  })
  .then(function(schedulesEntry) {
    if (!schedulesEntry)
      throw new Error
        ("The schedule ID for the member identity name does not exist in the database");

    return Promise.resolve(schedulesEntry.scheduleName);
  })
  .catch(function(ex) {
    return Promise.reject(new GroupManagerDb.Error(new Error
      ("IndexedDbGroupManagerDb.getScheduleIdPromise_: Error: " + ex)));
  });
};

/**
 * Add a new member with the given key named keyName into a schedule named
 * scheduleName. The member's identity name is keyName.getPrefix(-1).
 * @param {string} scheduleName The schedule name.
 * @param {Name} keyName The name of the key.
 * @param {Blob} key A Blob of the public key DER.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise that fulfills when the member is added, or that
 * is rejected with GroupManagerDb.Error if there's no schedule named
 * scheduleName, if the member's identity name already exists, or other database
 * error.
 */
IndexedDbGroupManagerDb.prototype.addMemberPromise = function
  (scheduleName, keyName, key, useSync)
{
  if (useSync)
    return Promise.reject(new GroupManagerDb.Error(new Error
      ("IndexedDbGroupManagerDb.addMemberPromise is only supported for async")));

  var thisManager = this;
  return this.getScheduleIdPromise_(scheduleName)
  .then(function(scheduleId) {
    if (scheduleId == -1)
      return Promise.reject(new GroupManagerDb.Error(new Error
        ("IndexedDbGroupManagerDb.addMemberPromise: The schedule does not exist")));

    // Needs to be changed in the future.
    var memberName = keyName.getPrefix(-1);

    // Add rejects if the primary key already exists.
    return thisManager.database.members.add
      ({ memberNameUri: memberName.toUri(),
         memberName: memberName.wireEncode(TlvWireFormat.get()).buf(),
         scheduleId: scheduleId,
         keyName: keyName.wireEncode(TlvWireFormat.get()).buf(),
         publicKey: key.buf() })
    .catch(function(ex) {
      return Promise.reject(new GroupManagerDb.Error(new Error
        ("IndexedDbGroupManagerDb.addMemberPromise: Error: " + ex)));
    });
  });
};

/**
 * Change the name of the schedule for the given member's identity name.
 * @param {Name} identity The member's identity name.
 * @param {string} scheduleName The new schedule name.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise that fulfills when the member is updated, or that
 * is rejected with GroupManagerDb.Error if there's no member with the given
 * identity name in the database, or there's no schedule named scheduleName, or
 * other database error.
 */
IndexedDbGroupManagerDb.prototype.updateMemberSchedulePromise = function
  (identity, scheduleName, useSync)
{
  if (useSync)
    return Promise.reject(new GroupManagerDb.Error(new Error
      ("IndexedDbGroupManagerDb.updateMemberSchedulePromise is only supported for async")));

  var thisManager = this;
  return this.getScheduleIdPromise_(scheduleName)
  .then(function(scheduleId) {
    if (scheduleId == -1)
      return Promise.reject(new GroupManagerDb.Error(new Error
        ("IndexedDbGroupManagerDb.updateMemberSchedulePromise: The schedule does not exist")));

    return thisManager.database.members.update
      (identity.toUri(), { scheduleId: scheduleId })
    .catch(function(ex) {
      return Promise.reject(new GroupManagerDb.Error(new Error
        ("IndexedDbGroupManagerDb.updateMemberSchedulePromise: Error: " + ex)));
    });
  });
};

/**
 * Delete a member with the given identity name. If there is no member with
 * the identity name, then do nothing.
 * @param {Name} identity The member's identity name.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise that fulfills when the member is deleted (or
 * there is no such member), or that is rejected with GroupManagerDb.Error for a
 * database error.
 */
IndexedDbGroupManagerDb.prototype.deleteMemberPromise = function
  (identity, useSync)
{
  if (useSync)
    return Promise.reject(new GroupManagerDb.Error(new Error
      ("IndexedDbGroupManagerDb.deleteMemberPromise is only supported for async")));

  return this.database.members.delete(identity.toUri())
  .catch(function(ex) {
    return Promise.reject(new GroupManagerDb.Error(new Error
      ("IndexedDbGroupManagerDb.deleteMemberPromise: Error: " + ex)));
  });
};

/**
 * Get the ID for the schedule.
 * @param {string} name The schedule name.
 * @return {Promise} A promise that returns the ID (or -1 if not found), or that
 * is rejected with GroupManagerDb.Error for a database error.
 */
IndexedDbGroupManagerDb.prototype.getScheduleIdPromise_ = function(name)
{
  // The scheduleName is not the primary key, so use 'where' instead of 'get'.
  var id = -1;
  return this.database.schedules.where("scheduleName").equals(name)
  .each(function(entry) {
    id = entry.scheduleId;
  })
  .then(function() {
    return Promise.resolve(id);
  })
  .catch(function(ex) {
    return Promise.reject(new GroupManagerDb.Error(new Error
      ("IndexedDbGroupManagerDb.getScheduleIdPromise_: Error: " + ex)));
  });
};
/**
 * Copyright (C) 2015-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

// Don't require modules since this is meant for the browser, not Node.js.

/**
 * IndexedDbProducerDb extends ProducerDb to implement storage of keys for the
 * producer using the browser's IndexedDB service. It contains one table that
 * maps time slots (to the nearest hour) to the content key created for that
 * time slot.
 * Create an IndexedDbProducerDb to use the given IndexedDB database name.
 * @param {string} databaseName IndexedDB database name.
 * @note This class is an experimental feature. The API may change.
 * @constructor
 */
var IndexedDbProducerDb = function IndexedDbProducerDb(databaseName)
{
  ProducerDb.call(this);

  this.database = new Dexie(databaseName);
  this.database.version(1).stores({
    // "timeSlot" is the hour-based time slot as hours since Jan 1, 1970 UTC. // number
    // "key" is the encoded key // Uint8Array
    contentKeys: "timeSlot"
  });
  this.database.open();
};

IndexedDbProducerDb.prototype = new ProducerDb();
IndexedDbProducerDb.prototype.name = "IndexedDbProducerDb";

/**
 * Check if a content key exists for the hour covering timeSlot.
 * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise that returns true if there is a content key for
 * timeSlot (else false), or that is rejected with ProducerDb.Error for a
 * database error.
 */
IndexedDbProducerDb.prototype.hasContentKeyPromise = function(timeSlot, useSync)
{
  if (useSync)
    return Promise.reject(new ProducerDb.Error(new Error
      ("IndexedDbProducerDb.hasContentKeyPromise is only supported for async")));

  var fixedTimeSlot = ProducerDb.getFixedTimeSlot(timeSlot);

  return this.database.contentKeys.get(fixedTimeSlot)
  .then(function(contentKeysEntry) {
    return Promise.resolve(contentKeysEntry != undefined);
  })
  .catch(function(ex) {
    return Promise.reject(new ProducerDb.Error(new Error
      ("IndexedDbProducerDb.hasContentKeyPromise: Error: " + ex)));
  });
};

/**
 * Get the content key for the hour covering timeSlot.
 * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise that returns a Blob with the encoded key, or that
 * is rejected with ProducerDb.Error if there is no key covering timeSlot, or
 * other database error
 */
IndexedDbProducerDb.prototype.getContentKeyPromise = function(timeSlot, useSync)
{
  if (useSync)
    return Promise.reject(new ProducerDb.Error(new Error
      ("IndexedDbProducerDb.getContentKeyPromise is only supported for async")));

  var fixedTimeSlot = ProducerDb.getFixedTimeSlot(timeSlot);

  return this.database.contentKeys.get(fixedTimeSlot)
  .then(function(contentKeysEntry) {
    if (contentKeysEntry)
      return Promise.resolve(new Blob(contentKeysEntry.key));
    else
      return Promise.reject(new ProducerDb.Error(new Error
        ("IndexedDbProducerDb.getContentKeyPromise: Cannot get the key from the database")));
  }, function(ex) {
    return Promise.reject(new ProducerDb.Error(new Error
      ("IndexedDbProducerDb.getContentKeyPromise: Error: " + ex)));
  });
};

/**
 * Add key as the content key for the hour covering timeSlot.
 * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
 * @param {Blob} key The encoded key.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise that fulfills when the key is added, or that
 * is rejected with ProducerDb.Error if a key for the same hour already exists
 * in the database, or other database error.
 */
IndexedDbProducerDb.prototype.addContentKeyPromise = function
  (timeSlot, key, useSync)
{
  if (useSync)
    return Promise.reject(new ProducerDb.Error(new Error
      ("IndexedDbProducerDb.addContentKeyPromise is only supported for async")));

  var fixedTimeSlot = ProducerDb.getFixedTimeSlot(timeSlot);

  // Add rejects if the primary key already exists.
  return this.database.contentKeys.add
    ({ timeSlot: fixedTimeSlot, key: key.buf() })
  .catch(function(ex) {
    return Promise.reject(new ProducerDb.Error(new Error
      ("IndexedDbProducerDb.addContentKeyPromise: Error: " + ex)));
  });
};

/**
 * Delete the content key for the hour covering timeSlot. If there is no key for
 * the time slot, do nothing.
 * @param {number} timeSlot The time slot as milliseconds since Jan 1, 1970 UTC.
 * @param {boolean} useSync (optional) If true then return a rejected promise
 * since this only supports async code.
 * @return {Promise} A promise that fulfills when the key is deleted (or there
 * is no such key), or that is rejected with ProducerDb.Error for a database
 * error.
 */
IndexedDbProducerDb.prototype.deleteContentKeyPromise = function(timeSlot, useSync)
{
  if (useSync)
    return Promise.reject(new ProducerDb.Error(new Error
      ("IndexedDbProducerDb.deleteContentKeyPromise is only supported for async")));

  var fixedTimeSlot = ProducerDb.getFixedTimeSlot(timeSlot);

  return this.database.contentKeys.delete(fixedTimeSlot)
  .catch(function(ex) {
    return Promise.reject(new ProducerDb.Error(new Error
      ("IndexedDbProducerDb.deleteContentKeyPromise: Error: " + ex)));
  });
};
/**
 * This class represents the digest tree for chrono-sync2013.
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Zhehao Wang, based on Jeff T.'s implementation in ndn-cpp
 *
 * 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.
 */

/** @ignore */
var DigestTree = require('./digest-tree.js').DigestTree; /** @ignore */
var Interest = require('../interest.js').Interest; /** @ignore */
var Data = require('../data.js').Data; /** @ignore */
var Name = require('../name.js').Name; /** @ignore */
var Blob = require('../util/blob.js').Blob; /** @ignore */
var MemoryContentCache = require('../util/memory-content-cache.js').MemoryContentCache; /** @ignore */
var SyncStateProto = require('./sync-state.js').SyncStateProto; /** @ignore */
var NdnCommon = require('../util/ndn-common.js').NdnCommon;

/**
 * ChronoSync2013 implements the NDN ChronoSync protocol as described in the
 * 2013 paper "Let's ChronoSync: Decentralized Dataset State Synchronization in
 * Named Data Networking". http://named-data.net/publications/chronosync .
 * @note The support for ChronoSync is experimental and the API is not finalized.
 * See the API docs for more detail at
 * http://named-data.net/doc/ndn-ccl-api/chrono-sync2013.html .
 *
 * Create a new ChronoSync2013 to communicate using the given face. Initialize
 * the digest log with a digest of "00" and and empty content. Register the
 * applicationBroadcastPrefix to receive interests for sync state messages and
 * express an interest for the initial root digest "00".
 * @param {function} onReceivedSyncState When ChronoSync receives a sync state message,
 * this calls onReceivedSyncState(syncStates, isRecovery) where syncStates is the
 * list of SyncState messages and isRecovery is true if this is the initial
 * list of SyncState messages or from a recovery interest. (For example, if
 * isRecovery is true, a chat application would not want to re-display all
 * the associated chat messages.) The callback should send interests to fetch
 * the application data for the sequence numbers in the sync state.
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onInitialized This calls onInitialized() when the first sync data
 * is received (or the interest times out because there are no other
 * publishers yet).
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {Name} applicationDataPrefix The prefix used by this application instance
 * for application data. For example, "/my/local/prefix/ndnchat4/0K4wChff2v".
 * This is used when sending a sync message for a new sequence number.
 * In the sync message, this uses applicationDataPrefix.toUri().
 * @param {Name} applicationBroadcastPrefix The broadcast name prefix including the
 * application name. For example, "/ndn/broadcast/ChronoChat-0.3/ndnchat1".
 * This makes a copy of the name.
 * @param {int} sessionNo The session number used with the applicationDataPrefix in
 * sync state messages.
 * @param {Face} face The Face for calling registerPrefix and expressInterest. The
 * Face object must remain valid for the life of this ChronoSync2013 object.
 * @param {KeyChain} keyChain To sign a data packet containing a sync state message, this
 * calls keyChain.sign(data, certificateName).
 * @param {Name} certificateName The certificate name of the key to use for signing a
 * data packet containing a sync state message.
 * @param {Milliseconds} syncLifetime The interest lifetime in milliseconds for sending
 * sync interests.
 * @param {function} onRegisterFailed If failed to register the prefix to receive
 * interests for the applicationBroadcastPrefix, this calls
 * onRegisterFailed(applicationBroadcastPrefix).
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @constructor
 */
var ChronoSync2013 = function ChronoSync2013
  (onReceivedSyncState, onInitialized, applicationDataPrefix,
   applicationBroadcastPrefix, sessionNo, face, keyChain, certificateName,
   syncLifetime, onRegisterFailed)
{
  // assigning function pointers
  this.onReceivedSyncState = onReceivedSyncState;
  this.onInitialized = onInitialized;
  this.applicationDataPrefixUri = applicationDataPrefix.toUri();
  this.applicationBroadcastPrefix = applicationBroadcastPrefix;
  this.session = sessionNo;
  this.face = face;
  this.keyChain = keyChain;
  this.certificateName = certificateName;
  this.sync_lifetime = syncLifetime;
  this.usrseq = -1;

  this.digest_tree = new DigestTree();
  this.contentCache = new MemoryContentCache(face);

  this.digest_log = new Array();
  this.digest_log.push(new ChronoSync2013.DigestLogEntry("00",[]));

  this.contentCache.registerPrefix
    (this.applicationBroadcastPrefix, onRegisterFailed,
     this.onInterest.bind(this));
  this.enabled = true;

  var interest = new Interest(this.applicationBroadcastPrefix);
  interest.getName().append("00");

  interest.setInterestLifetimeMilliseconds(1000);

  var Sync;
  try {
    // Using protobuf.min.js in the browser.
    Sync = dcodeIO.ProtoBuf.newBuilder().import(SyncStateProto).build("Sync");
  }
  catch (ex) {
    // Using protobufjs in node.
    Sync = require("protobufjs").newBuilder().import(SyncStateProto).build("Sync");
  }
  this.SyncStateMsg = Sync.SyncStateMsg;
  this.SyncState = Sync.SyncState;

  this.face.expressInterest(interest, this.onData.bind(this), this.initialTimeOut.bind(this));
};

exports.ChronoSync2013 = ChronoSync2013;

ChronoSync2013.prototype.getProducerSequenceNo = function(dataPrefix, sessionNo)
{
  var index = this.digest_tree.find(dataPrefix, sessionNo);
  if (index < 0)
    return -1;
  else
    return this.digest_tree.get(index).getSequenceNo();
};

/**
 * Increment the sequence number, create a sync message with the new sequence number,
 * and publish a data packet where the name is applicationBroadcastPrefix + root
 * digest of current digest tree. Then add the sync message to digest tree and digest
 * log which creates a new root digest. Finally, express an interest for the next sync
 * update with the name applicationBroadcastPrefix + the new root digest.
 * After this, application should publish the content for the new sequence number.
 * Get the new sequence number with getSequenceNo().
 */
ChronoSync2013.prototype.publishNextSequenceNo = function()
{
  this.usrseq ++;
  var content = [new this.SyncState({ name:this.applicationDataPrefixUri,
                                 type:'UPDATE',
                                 seqno:{
                                   seq:this.usrseq,
                                   session:this.session
                                  }
                                })];
  var content_t = new this.SyncStateMsg({ss:content});
  this.broadcastSyncState(this.digest_tree.getRoot(), content_t);

  if (!this.update(content))
    console.log("Warning: ChronoSync: update did not create a new digest log entry");

  var interest = new Interest(this.applicationBroadcastPrefix);
  interest.getName().append(this.digest_tree.getRoot());
  interest.setInterestLifetimeMilliseconds(this.sync_lifetime);

  this.face.expressInterest(interest, this.onData.bind(this), this.syncTimeout.bind(this));
};

/**
 * Get the sequence number of the latest data published by this application instance.
 * @return {int} the sequence number
 */
ChronoSync2013.prototype.getSequenceNo = function()
{
  return this.usrseq;
};

// DigestLogEntry class

ChronoSync2013.DigestLogEntry = function ChronoSync2013DisgestLogEntry(digest, data)
{
  this.digest = digest;
  this.data = data;
};

ChronoSync2013.DigestLogEntry.prototype.getDigest = function()
{
  return this.digest;
};

ChronoSync2013.DigestLogEntry.prototype.getData = function()
{
  return this.data;
};

/**
 * Unregister callbacks so that this does not respond to interests anymore.
 * If you will dispose this ChronoSync2013 object while your application is
 * still running, you should call shutdown() first.  After calling this, you
 * should not call publishNextSequenceNo() again since the behavior will be
 * undefined.
 */
ChronoSync2013.prototype.shutdown = function()
{
  this.enabled = false;
  this.contentCache.unregisterAll();
};

// SyncState class
/**
 * A SyncState holds the values of a sync state message which is passed to the
 * onReceivedSyncState callback which was given to the ChronoSyn2013
 * constructor. Note: this has the same info as the Protobuf class
 * Sync::SyncState, but we make a separate class so that we don't need the
 * Protobuf definition in the ChronoSync API.
 */
ChronoSync2013.SyncState = function ChronoSync2013SyncState(dataPrefixUri, sessionNo, sequenceNo)
{
  this.dataPrefixUri_ = dataPrefixUri;
  this.sessionNo_ = sessionNo;
  this.sequenceNo_ = sequenceNo;
};

/**
 * Get the application data prefix for this sync state message.
 * @return The application data prefix as a Name URI string.
 */
ChronoSync2013.SyncState.prototype.getDataPrefix = function()
{
  return this.dataPrefixUri_;
}

/**
 * Get the session number associated with the application data prefix for
 * this sync state message.
 * @return The session number.
 */
ChronoSync2013.SyncState.prototype.getSessionNo = function()
{
  return this.sessionNo_;
}

/**
 * Get the sequence number for this sync state message.
 * @return The sequence number.
 */
ChronoSync2013.SyncState.prototype.getSequenceNo = function()
{
  return this.sequenceNo_;
}

// Private methods for ChronoSync2013 class,
/**
 * Make a data packet with the syncMessage and with name applicationBroadcastPrefix_ + digest.
 * Sign and send.
 * @param {string} The root digest as a hex string for the data packet name.
 * @param {SyncStateMsg} The syncMessage updates the digest tree state with the given digest.
 */
ChronoSync2013.prototype.broadcastSyncState = function(digest, syncMessage)
{
  var array = new Uint8Array(syncMessage.toArrayBuffer());
  var data = new Data(this.applicationBroadcastPrefix);
  data.getName().append(digest);
  data.setContent(new Blob(array, false));
  var thisChronoSync = this;
  this.keyChain.sign(data, this.certificateName, function() {
    thisChronoSync.contentCache.add(data);
  });
};

/**
 * Update the digest tree with the messages in content. If the digest tree root is not in
 * the digest log, also add a log entry with the content.
 * @param {SyncStates[]} The sync state messages
 * @return {bool} True if added a digest log entry (because the updated digest tree root
 * was not in the log), false if didn't add a log entry.
 */
 // Whatever's received by ondata, is pushed into digest log as its data directly
ChronoSync2013.prototype.update = function(content)
{
  for (var i = 0; i < content.length; i++) {
    if (content[i].type == 0) {
      if (this.digest_tree.update(content[i].name, content[i].seqno.session, content[i].seqno.seq)) {
        if (this.applicationDataPrefixUri == content[i].name)
          this.usrseq = content[i].seqno.seq;
      }
    }
  }

  if (this.logfind(this.digest_tree.getRoot()) == -1) {
    var newlog = new ChronoSync2013.DigestLogEntry(this.digest_tree.getRoot(), content);
    this.digest_log.push(newlog);
    return true;
  }
  else
    return false;
};

ChronoSync2013.prototype.logfind = function(digest)
{
  for (var i = 0; i < this.digest_log.length; i++) {
    if(digest == this.digest_log[i].digest)
      return i;
  }
  return -1;
};

/**
 * Process the sync interest from the applicationBroadcastPrefix. If we can't
 * satisfy the interest, add it to the pending interest table in
 * this.contentCache so that a future call to contentCacheAdd may satisfy it.
 */
ChronoSync2013.prototype.onInterest = function
  (prefix, interest, face, interestFilterId, filter)
{
  if (!this.enabled)
    // Ignore callbacks after the application calls shutdown().
    return;

  //search if the digest is already exist in the digest log

  var syncdigest = interest.getName().get(this.applicationBroadcastPrefix.size()).toEscapedString();
  if (interest.getName().size() == this.applicationBroadcastPrefix.size() + 2) {
    syncdigest = interest.getName().get(this.applicationBroadcastPrefix.size() + 1).toEscapedString();
  }
  if (interest.getName().size() == this.applicationBroadcastPrefix.size() + 2 || syncdigest == "00") {
    this.processRecoveryInst(interest, syncdigest, face);
  }
  else {
    this.contentCache.storePendingInterest(interest, face);

    if (syncdigest != this.digest_tree.getRoot()) {
      var index = this.logfind(syncdigest);
      var content = [];
      if(index == -1) {
        var self = this;
        // Are we sure that using a "/local/timeout" interest is the best future call approach?
        var timeout = new Interest(new Name("/local/timeout"));
        timeout.setInterestLifetimeMilliseconds(2000);
        this.face.expressInterest
          (timeout, this.dummyOnData,
           this.judgeRecovery.bind(this, timeout, syncdigest, face));
      }
      else {
        //common interest processing
        this.processSyncInst(index, syncdigest, face);
      }
    }
  }
};

/**
 * Process sync/recovery data.
 * @param {Interest}
 * @param {Data}
 */
ChronoSync2013.prototype.onData = function(interest, co)
{
  if (!this.enabled)
    // Ignore callbacks after the application calls shutdown().
    return;

  var arr = new Uint8Array(co.getContent().size());
  arr.set(co.getContent().buf());
  var content_t = this.SyncStateMsg.decode(arr.buffer);
  var content = content_t.ss;

  var isRecovery = false;

  if (this.digest_tree.getRoot() == "00") {
    isRecovery = true;
    this.initialOndata(content);
  }
  else {
    this.update(content);
    if (interest.getName().size() == this.applicationBroadcastPrefix.size() + 2)
      // Assume this is a recovery interest.
      isRecovery = true;
    else
      isRecovery = false;
  }

  var syncStates = [];

  for (var i = 0; i < content.length; i++) {
    if (content[i].type == 0) {
      syncStates.push(new ChronoSync2013.SyncState
        (content[i].name, content[i].seqno.session, content[i].seqno.seq));
    }
  }

  // Instead of using Protobuf, use our own definition of SyncStates to pass to onReceivedSyncState.
  try {
    this.onReceivedSyncState(syncStates, isRecovery);
  } catch (ex) {
    console.log("Error in onReceivedSyncState: " + NdnCommon.getErrorWithStackTrace(ex));
  }

  var n = new Name(this.applicationBroadcastPrefix);
  n.append(this.digest_tree.getRoot());

  var interest = new Interest(n);
  interest.setInterestLifetimeMilliseconds(this.sync_lifetime);

  this.face.expressInterest(interest, this.onData.bind(this), this.syncTimeout.bind(this));
};

/**
 * Interest variable not actually in use here
 */
ChronoSync2013.prototype.initialTimeOut = function(interest)
{
  if (!this.enabled)
    // Ignore callbacks after the application calls shutdown().
    return;

  console.log("no other people");

  this.usrseq++;
  try {
    this.onInitialized();
  } catch (ex) {
    console.log("Error in onInitialized: " + NdnCommon.getErrorWithStackTrace(ex));
  }
  var content = [new this.SyncState({ name:this.applicationDataPrefixUri,
                                 type:'UPDATE',
                                 seqno: {
                                   seq:this.usrseq,
                                   session:this.session
                                 }
                               })];
  this.update(content);
  var n = new Name(this.applicationBroadcastPrefix);
  n.append(this.digest_tree.getRoot());
  var retryInterest = new Interest(n);
  retryInterest.setInterestLifetimeMilliseconds(this.sync_lifetime);

  this.face.expressInterest(retryInterest, this.onData.bind(this), this.syncTimeout.bind(this));
};

ChronoSync2013.prototype.processRecoveryInst = function(interest, syncdigest, face)
{
  if (this.logfind(syncdigest) != -1) {
    var content = [];

    for(var i = 0; i < this.digest_tree.digestnode.length; i++) {
      content[i] = new this.SyncState({ name:this.digest_tree.digestnode[i].getDataPrefix(),
                                   type:'UPDATE',
                                   seqno:{
                                     seq:this.digest_tree.digestnode[i].getSequenceNo(),
                                     session:this.digest_tree.digestnode[i].getSessionNo()
                                    }
                                 });
    }

    if (content.length != 0) {
      var content_t = new this.SyncStateMsg({ss:content});
      var str = new Uint8Array(content_t.toArrayBuffer());
      var co = new Data(interest.getName());
      co.setContent(new Blob(str, false));
      if (interest.getName().get(-1).toEscapedString() == "00")
        // Limit the lifetime of replies to interest for "00" since they can be different.
        co.getMetaInfo().setFreshnessPeriod(1000);

      this.keyChain.sign(co, this.certificateName, function() {
        try {
          face.putData(co);
        } catch (e) {
          console.log(e.toString());
        }
      });
    }
  }
};

/**
 * Common interest processing, using digest log to find the difference after syncdigest_t
 * @return True if sent a data packet to satisfy the interest.
 */
ChronoSync2013.prototype.processSyncInst = function(index, syncdigest_t, face)
{
  var content = [];
  var data_name = [];
  var data_seq = [];
  var data_ses = [];

  for (var j = index + 1; j < this.digest_log.length; j++) {
    var temp = this.digest_log[j].getData();
    for (var i = 0 ; i < temp.length ; i++) {
      if (temp[i].type != 0) {
        continue;
      }
      if (this.digest_tree.find(temp[i].name, temp[i].seqno.session) != -1) {
        var n = data_name.indexOf(temp[i].name);
        if (n == -1) {
          data_name.push(temp[i].name);
          data_seq.push(temp[i].seqno.seq);
          data_ses.push(temp[i].seqno.session);
        }
        else {
          data_seq[n] = temp[i].seqno.seq;
          data_ses[n] = temp[i].seqno.session;
        }
      }
    }
  }

  for(var i = 0; i < data_name.length; i++) {
    content[i] = new this.SyncState({ name:data_name[i],
                                 type:'UPDATE',
                                 seqno: {
                                   seq:data_seq[i],
                                   session:data_ses[i]
                                 }
                               });
  }
  if (content.length != 0) {
    var content_t = new this.SyncStateMsg({ss:content});
    var str = new Uint8Array(content_t.toArrayBuffer());
    var n = new Name(this.prefix)
    n.append(this.chatroom).append(syncdigest_t);

    var co = new Data(n);
    co.setContent(new Blob(str, false));
    this.keyChain.sign(co, this.certificateName, function() {
      try {
        face.putData(co);
      }
      catch (e) {
        console.log(e.toString());
      }
    });
  }
};

/**
 * Send recovery interset.
 * @param {string} syncdigest_t
 */
ChronoSync2013.prototype.sendRecovery = function(syncdigest_t)
{
  var n = new Name(this.applicationBroadcastPrefix);
  n.append("recovery").append(syncdigest_t);

  var interest = new Interest(n);

  interest.setInterestLifetimeMilliseconds(this.sync_lifetime);

  this.face.expressInterest(interest, this.onData.bind(this), this.syncTimeout.bind(this));
};

/**
 * This is called by onInterest after a timeout to check if a recovery is needed.
 * This method has an interest argument because we use it as the onTimeout for
 * Face.expressInterest.
 * @param {Interest}
 * @param {string}
 * @param {Face}
 */
ChronoSync2013.prototype.judgeRecovery = function(interest, syncdigest_t, face)
{
  //console.log("*** judgeRecovery interest " + interest.getName().toUri() + " times out. Digest: " + syncdigest_t + " ***");
  var index = this.logfind(syncdigest_t);
  if (index != -1) {
    if (syncdigest_t != this.digest_tree.root)
      this.processSyncInst(index, syncdigest_t, face);
  }
  else
    this.sendRecovery(syncdigest_t);
};

ChronoSync2013.prototype.syncTimeout = function(interest)
{
  if (!this.enabled)
    // Ignore callbacks after the application calls shutdown().
    return;

  var component = interest.getName().get(4).toEscapedString();
  if (component == this.digest_tree.root) {
    var n = new Name(interest.getName());
    var newInterest = new Interest(n);

    interest.setInterestLifetimeMilliseconds(this.sync_lifetime);
    this.face.expressInterest(newInterest, this.onData.bind(this), this.syncTimeout.bind(this));
  }
};

ChronoSync2013.prototype.initialOndata = function(content)
{
  this.update(content);

  var digest_t = this.digest_tree.getRoot();
  for (var i = 0; i < content.length; i++) {
    if (content[i].name == this.applicationDataPrefixUri && content[i].seqno.session == this.session) {
      //if the user was an old comer, after add the static log he need to increase his seqno by 1
      var content_t = [new this.SyncState({ name:this.applicationDataPrefixUri,
                                       type:'UPDATE',
                                       seqno: {
                                         seq:content[i].seqno.seq + 1,
                                         session:this.session
                                       }
                                     })];
      if (this.update(content_t)) {
        var newlog = new ChronoSync2013.DigestLogEntry(this.digest_tree.getRoot(), content_t);
        this.digest_log.push(newlog);
        try {
          this.onInitialized();
        } catch (ex) {
          console.log("Error in onInitialized: " + NdnCommon.getErrorWithStackTrace(ex));
        }
      }
    }
  }

  var content_t;
  if (this.usrseq >= 0) {
    //send the data packet with new seqno back
    content_t = new this.SyncState({ name:this.applicationDataPrefixUri,
                                   type:'UPDATE',
                                   seqno: {
                                     seq:this.usrseq,
                                     session:this.session
                                   }
                                 });
  }
  else
    content_t = new this.SyncState({ name:this.applicationDataPrefixUri,
                                   type:'UPDATE',
                                   seqno: {
                                     seq:0,
                                     session:this.session
                                   }
                                 });
  var content_tt = new this.SyncStateMsg({ss:content_t});
  this.broadcastSyncState(digest_t, content_tt);

  if (this.digest_tree.find(this.applicationDataPrefixUri, this.session) == -1) {
    //the user haven't put himself in the digest tree
    this.usrseq++;
    var content = [new this.SyncState({ name:this.applicationDataPrefixUri,
                                   type:'UPDATE',
                                   seqno: {
                                     seq:this.usrseq,
                                     session:this.session
                                   }
                                 })];
    if (this.update(content)) {
      try {
        this.onInitialized();
      } catch (ex) {
        console.log("Error in onInitialized: " + NdnCommon.getErrorWithStackTrace(ex));
      }
    }
  }
};

ChronoSync2013.prototype.dummyOnData = function(interest, data)
{
  console.log("*** dummyOnData called. ***");
};/**
 * This class represents the digest tree for chrono-sync2013.
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Zhehao Wang, based on Jeff T.'s implementation in ndn-cpp
 *
 * 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.
 */

// Use capitalized Crypto to not clash with the browser's crypto.subtle.
/** @ignore */
var Crypto = require('../crypto.js');

/**
 * @constructor
 */
var DigestTree = function DigestTree()
{
  this.root = "00";
  this.digestnode = [];
};

exports.DigestTree = DigestTree;

// The meaning of a session is explained here:
// http://named-data.net/doc/ndn-ccl-api/chrono-sync2013.html
// DigestTree.Node works with seqno_seq and seqno_session, without protobuf definition,
DigestTree.Node = function DigestTreeNode(dataPrefix, seqno_session, seqno_seq)
{
  // In this context, this should mean DigestTree.Node instead
  this.dataPrefix = dataPrefix;
  this.seqno_session = seqno_session;
  this.seqno_seq = seqno_seq;

  this.recomputeDigest();
};

DigestTree.Node.prototype.getDataPrefix = function()
{
  return this.dataPrefix;
};

DigestTree.Node.prototype.getSessionNo = function()
{
  return this.seqno_session;
};

DigestTree.Node.prototype.getSequenceNo = function()
{
  return this.seqno_seq;
};

DigestTree.Node.prototype.getDigest = function()
{
  return this.digest;
};

DigestTree.Node.prototype.setSequenceNo = function(sequenceNo)
{
  this.seqno_seq = sequenceNo;
  this.recomputeDigest();
};

// Using Node.JS buffer, as documented here http://nodejs.org/api/buffer.html.
DigestTree.Node.prototype.Int32ToBuffer = function(value) {
  var result = new Buffer(4);
  for (var i = 0; i < 4; i++) {
    result[i] = value % 256;
    value = Math.floor(value / 256);
  }
  return result;
}

DigestTree.Node.prototype.recomputeDigest = function()
{
  var seqHash = Crypto.createHash('sha256');

  seqHash.update(this.Int32ToBuffer(this.seqno_session));
  seqHash.update(this.Int32ToBuffer(this.seqno_seq));

  var digest_seq = seqHash.digest();

  var nameHash = Crypto.createHash('sha256');
  nameHash.update(this.dataPrefix);
  var digest_name = nameHash.digest();

  var hash = Crypto.createHash('sha256');
  hash.update(digest_name);
  hash.update(digest_seq);

  this.digest = hash.digest('hex');
};

// Do the work of string and then sequence number compare
DigestTree.Node.Compare = function(node1, node2)
{
  if (node1.dataPrefix != node2.dataPrefix)
    return node1.dataPrefix < node2.dataPrefix;
  return node1.seqno_session < node2.seqno_session;
};

/**
 * Update the digest tree and recompute the root digest. If the combination of dataPrefix
 * and sessionNo already exists in the tree then update its sequenceNo (only if the given
 * sequenceNo is newer), otherwise add a new node.
 * @param {string} The name prefix.
 * @param {int} sessionNo The session number.
 * @param {int} sequenceNo The sequence number.
 * @return True if the digest tree is updated, false if not
 */
DigestTree.prototype.update = function(dataPrefix, sessionNo, sequenceNo)
{
  var n_index = this.find(dataPrefix, sessionNo);
  if (n_index >= 0) {
    if (this.digestnode[n_index].getSequenceNo() < sequenceNo)
      this.digestnode[n_index].setSequenceNo(sequenceNo);
    else
      return false;
  }
  else {
    var temp = new DigestTree.Node(dataPrefix, sessionNo, sequenceNo);
    this.digestnode.push(temp);
    this.digestnode.sort(this.sortNodes);
  }
  this.recomputeRoot();
  return true;
};

// Need to confirm this sort works with the insertion in ndn-cpp.
DigestTree.prototype.sortNodes = function()
{
  var temp;
  for (var i = this.digestnode.length; i > 0; i--) {
    for (var j = 0; j < i - 1; j++) {
      if (this.digestnode[j].getDataPrefix() > this.digestnode[j + 1].getDataPrefix()) {
        temp = this.digestnode[j];
        this.digestnode[j] = this.digestnode[j + 1];
        this.digestnode[j + 1] = temp;
      }
    }
  }
};

DigestTree.prototype.sortNodes = function (node1, node2)
{
  if (node1.getDataPrefix() == node2.getDataPrefix() &&
     node1.getSessionNo() == node2.getSessionNo())
    return 0;

  if ((node1.getDataPrefix() > node2.getDataPrefix()) ||
     ((node1.getDataPrefix() == node2.getDataPrefix()) &&
     (node1.getSessionNo() >node2.getSessionNo())))
    return 1;
  else
    return -1;
}

DigestTree.prototype.find = function(dataPrefix, sessionNo)
{
  for (var i = 0; i < this.digestnode.length; ++i) {
    if (this.digestnode[i].getDataPrefix() == dataPrefix &&
        this.digestnode[i].getSessionNo() == sessionNo)
      return i;
  }
  return -1;
};

DigestTree.prototype.size = function()
{
  return this.digestnode.size();
};

// Not really used
DigestTree.prototype.get = function(i)
{
  return this.digestnode[i];
};

DigestTree.prototype.getRoot = function()
{
  return this.root;
};

DigestTree.prototype.recomputeRoot = function()
{
  var md = Crypto.createHash('sha256');
  // The result of updateHex is related with the sequence of participants,
  // I don't think that should be the case.
  for (var i = 0; i < this.digestnode.length; i++) {
    md.update(new Buffer(this.digestnode[i].digest, 'hex'));
  }
  this.root = md.digest('hex');
};
// Just define the SyncStateProto object. We do a Protobuf import dynamically
// when we need it so that protobufjs is optional.
var SyncStateProto = {
    "package": "Sync",
    "messages": [
        {
            "name": "SyncState",
            "fields": [
                {
                    "rule": "required",
                    "type": "string",
                    "name": "name",
                    "id": 1,
                    "options": {}
                },
                {
                    "rule": "required",
                    "type": "ActionType",
                    "name": "type",
                    "id": 2,
                    "options": {}
                },
                {
                    "rule": "optional",
                    "type": "SeqNo",
                    "name": "seqno",
                    "id": 3,
                    "options": {}
                }
            ],
            "enums": [
                {
                    "name": "ActionType",
                    "values": [
                        {
                            "name": "UPDATE",
                            "id": 0
                        },
                        {
                            "name": "DELETE",
                            "id": 1
                        },
                        {
                            "name": "OTHER",
                            "id": 2
                        }
                    ],
                    "options": {}
                }
            ],
            "messages": [
                {
                    "name": "SeqNo",
                    "fields": [
                        {
                            "rule": "required",
                            "type": "uint32",
                            "name": "seq",
                            "id": 1,
                            "options": {}
                        },
                        {
                            "rule": "required",
                            "type": "uint32",
                            "name": "session",
                            "id": 2,
                            "options": {}
                        }
                    ],
                    "enums": [],
                    "messages": [],
                    "options": {}
                }
            ],
            "options": {}
        },
        {
            "name": "SyncStateMsg",
            "fields": [
                {
                    "rule": "repeated",
                    "type": "SyncState",
                    "name": "ss",
                    "id": 1,
                    "options": {}
                }
            ],
            "enums": [],
            "messages": [],
            "options": {}
        }
    ],
    "enums": [],
    "imports": [],
    "options": {}
};

exports.SyncStateProto = SyncStateProto;
/**
 * Copyright (C) 2014-2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

// Use capitalized Crypto to not clash with the browser's crypto.subtle.
/** @ignore */
var Crypto = require('../crypto.js'); /** @ignore */
var WireFormat = require('../encoding/wire-format.js').WireFormat; /** @ignore */
var TlvEncoder = require('../encoding/tlv/tlv-encoder.js').TlvEncoder; /** @ignore */
var Blob = require('./blob.js').Blob;

/**
 * A CommandInterestGenerator keeps track of a timestamp and generates command
 * interests according to the NFD Signed Command Interests protocol:
 * http://redmine.named-data.net/projects/nfd/wiki/Command_Interests
 *
 * Create a new CommandInterestGenerator and initialize the timestamp to now.
 * @constructor
 */
var CommandInterestGenerator = function CommandInterestGenerator()
{
  this.lastTimestamp = Math.round(new Date().getTime());
};

exports.CommandInterestGenerator = CommandInterestGenerator;

/**
 * Append a timestamp component and a random value component to interest's name.
 * This ensures that the timestamp is greater than the timestamp used in the
 * previous call. Then use keyChain to sign the interest which appends a
 * SignatureInfo component and a component with the signature bits. If the
 * interest lifetime is not set, this sets it.
 * @param {Interest} interest The interest whose name is append with components.
 * @param {KeyChain} keyChain The KeyChain for calling sign.
 * @param {Name} certificateName The certificate name of the key to use for
 * signing.
 * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
 * the SignatureInfo and to encode interest name for signing. If omitted, use
 * WireFormat.getDefaultWireFormat().
 * @param {function} onComplete (optional) This calls onComplete() when complete.
 * (Some crypto/database libraries only use a callback, so onComplete is
 * required to use these.)
 */
CommandInterestGenerator.prototype.generate = function
  (interest, keyChain, certificateName, wireFormat, onComplete)
{
  onComplete = (typeof wireFormat === "function") ? wireFormat : onComplete;
  wireFormat = (typeof wireFormat === "function" || !wireFormat) ?
    WireFormat.getDefaultWireFormat() : wireFormat;

  var timestamp = Math.round(new Date().getTime());
  while (timestamp <= this.lastTimestamp)
    timestamp += 1.0;

  // The timestamp is encoded as a TLV nonNegativeInteger.
  var encoder = new TlvEncoder(8);
  encoder.writeNonNegativeInteger(timestamp);
  interest.getName().append(new Blob(encoder.getOutput(), false));

  // The random value is a TLV nonNegativeInteger too, but we know it is 8
  // bytes, so we don't need to call the nonNegativeInteger encoder.
  interest.getName().append(new Blob(Crypto.randomBytes(8), false));

  // Update the timestamp before calling async sign.
  this.lastTimestamp = timestamp;

  keyChain.sign(interest, certificateName, wireFormat, function() {
    if (interest.getInterestLifetimeMilliseconds() == null ||
        interest.getInterestLifetimeMilliseconds() < 0)
      // The caller has not set the interest lifetime, so set it here.
      interest.setInterestLifetimeMilliseconds(1000.0);

    if (onComplete)
      onComplete();
  });
};
/**
 * Copyright (C) 2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var LOG = require('../log.js').Log.LOG;

/**
 * An InterestFilterTable is an internal class to hold a list of entries with
 * an interest Filter and its OnInterestCallback.
 * @constructor
 */
var InterestFilterTable = function InterestFilterTable()
{
  this.table_ = []; // of Entry
};

exports.InterestFilterTable = InterestFilterTable;

/**
 * InterestFilterTable.Entry holds an interestFilterId, an InterestFilter and
 * the OnInterestCallback with its related Face.
 * Create a new Entry with the given values.
 * @param {number} interestFilterId The ID from getNextEntryId().
 * @param {InterestFilter} filter The InterestFilter for this entry.
 * @param {function} onInterest The callback to call.
 * @param {Face} face The face on which was called registerPrefix or
 * setInterestFilter which is passed to the onInterest callback.
 * @constructor
 */
InterestFilterTable.Entry = function InterestFilterTableEntry
  (interestFilterId, filter, onInterest, face)
{
  this.interestFilterId_ = interestFilterId;
  this.filter_ = filter;
  this.onInterest_ = onInterest;
  this.face_ = face;
};

/**
 * Get the interestFilterId given to the constructor.
 * @return {number} The interestFilterId.
 */
InterestFilterTable.Entry.prototype.getInterestFilterId = function()
{
  return this.interestFilterId_;
};

/**
 * Get the InterestFilter given to the constructor.
 * @return {InterestFilter} The InterestFilter.
 */
InterestFilterTable.Entry.prototype.getFilter = function()
{
  return this.filter_;
};

/**
 * Get the onInterest callback given to the constructor.
 * @return {function} The onInterest callback.
 */
InterestFilterTable.Entry.prototype.getOnInterest = function()
{
  return this.onInterest_;
};

/**
 * Get the Face given to the constructor.
 * @return {Face} The Face.
 */
InterestFilterTable.Entry.prototype.getFace = function()
{
  return this.face_;
};

/**
 * Add a new entry to the table.
 * @param {number} interestFilterId The ID from Node.getNextEntryId().
 * @param {InterestFilter} filter The InterestFilter for this entry.
 * @param {function} onInterest The callback to call.
 * @param {Face} face The face on which was called registerPrefix or
 * setInterestFilter which is passed to the onInterest callback.
 */
InterestFilterTable.prototype.setInterestFilter = function
  (interestFilterId, filter, onInterest, face)
{
  this.table_.push(new InterestFilterTable.Entry
    (interestFilterId, filter, onInterest, face));
};

/**
 * Find all entries from the interest filter table where the interest conforms
 * to the entry's filter, and add to the matchedFilters list.
 * @param {Interest} interest The interest which may match the filter in
 * multiple entries.
 * @param {Array<InterestFilterTable.Entry>} matchedFilters Add each matching
 * InterestFilterTable.Entry from the interest filter table.  The caller should
 * pass in an empty array.
 */
InterestFilterTable.prototype.getMatchedFilters = function
  (interest, matchedFilters)
{
  for (var i = 0; i < this.table_.length; ++i) {
    var entry = this.table_[i];
    if (entry.getFilter().doesMatch(interest.getName()))
      matchedFilters.push(entry);
  }
};

/**
 * Remove the interest filter entry which has the interestFilterId from the
 * interest filter table. This does not affect another interest filter with a
 * different interestFilterId, even if it has the same prefix name. If there is
 * no entry with the interestFilterId, do nothing.
 * @param {number} interestFilterId The ID returned from setInterestFilter.
 */
InterestFilterTable.prototype.unsetInterestFilter = function(interestFilterId)
{
  // Go backwards through the list so we can erase entries.
  // Remove all entries even though interestFilterId should be unique.
  var count = 0;
  for (var i = this.table_.length - 1; i >= 0; --i) {
    if (this.table_[i].getInterestFilterId() == interestFilterId) {
      ++count;
      this.table_.splice(i, 1);
    }
  }

  if (count === 0)
    if (LOG > 0) console.log
      ("unsetInterestFilter: Didn't find interestFilterId " + interestFilterId);
};
/**
 * Copyright (C) 2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var NdnCommon = require('../util/ndn-common.js').NdnCommon; /** @ignore */
var LOG = require('../log.js').Log.LOG;

/**
 * A PendingInterestTable is an internal class to hold a list of pending
 * interests with their callbacks.
 * @constructor
 */
var PendingInterestTable = function PendingInterestTable()
{
  this.table_ = []; // of Entry
  this.removeRequests_ = []; // of number
};

exports.PendingInterestTable = PendingInterestTable;

/**
 * PendingInterestTable.Entry holds the callbacks and other fields for an entry
 * in the pending interest table.
 * Create a new Entry with the given fields. Note: You should not call this
 * directly but call PendingInterestTable.add.
 * @constructor
 */
PendingInterestTable.Entry = function PendingInterestTableEntry
  (pendingInterestId, interest, onData, onTimeout, onNetworkNack)
{
  this.pendingInterestId_ = pendingInterestId;
  this.interest_ = interest;
  this.onData_ = onData;
  this.onTimeout_ = onTimeout;
  this.onNetworkNack_ = onNetworkNack;
  this.timerId_ = -1;
};

/**
 * Get the pendingInterestId given to the constructor.
 * @return {number} The pendingInterestId.
 */
PendingInterestTable.Entry.prototype.getPendingInterestId = function()
{
  return this.pendingInterestId_;
};

/**
 * Get the interest given to the constructor (from Face.expressInterest).
 * @return {Interest} The interest. NOTE: You must not change the interest
 * object - if you need to change it then make a copy.
 */
PendingInterestTable.Entry.prototype.getInterest = function()
{
  return this.interest_;
};

/**
 * Get the OnData callback given to the constructor.
 * @return {function} The OnData callback.
 */
PendingInterestTable.Entry.prototype.getOnData = function()
{
  return this.onData_;
};

/**
 * Get the OnNetworkNack callback given to the constructor.
 * @return {function} The OnNetworkNack callback.
 */
PendingInterestTable.Entry.prototype.getOnNetworkNack = function()
{
  return this.onNetworkNack_;
};

/**
* Call onTimeout_ (if defined). This ignores exceptions from the call to
* onTimeout_.
*/
PendingInterestTable.Entry.prototype.callTimeout = function()
{
  if (this.onTimeout_) {
    try {
      this.onTimeout_(this.interest_);
    } catch (ex) {
      console.log("Error in onTimeout: " + NdnCommon.getErrorWithStackTrace(ex));
    }
  }
};

/**
 * Call setTimeout(callback, milliseconds) and remember the timer ID. If the
 * timer ID has already been set on a prevous call, do nothing.
 */
PendingInterestTable.Entry.prototype.setTimeout = function(callback, milliseconds)
{
  if (this.timerId_ !== -1)
    // Already set a timeout.
    return;
  this.timerId_ = setTimeout(callback, milliseconds);
};

/**
 * Clear the timeout timer and reset the timer ID.
 */
PendingInterestTable.Entry.prototype.clearTimeout = function()
{
  if (this.timerId_ !== -1) {
    clearTimeout(this.timerId_);
    this.timerId_ = -1;
  }
};

/**
 * Add a new entry to the pending interest table. Also set a timer to call the
 * timeout. However, if removePendingInterest was already called with the
 * pendingInterestId, don't add an entry and return null.
 * @param {number} pendingInterestId
 * @param {Interest} interestCopy
 * @param {function} onData
 * @param {function} onTimeout
 * @param {function} onNetworkNack
 * @return {PendingInterestTable.Entry} The new PendingInterestTable.Entry, or
 * null if removePendingInterest was already called with the pendingInterestId.
 */
PendingInterestTable.prototype.add = function
  (pendingInterestId, interestCopy, onData, onTimeout, onNetworkNack)
{
  var removeRequestIndex = this.removeRequests_.indexOf(pendingInterestId);
  if (removeRequestIndex >= 0) {
    // removePendingInterest was called with the pendingInterestId returned by
    //   expressInterest before we got here, so don't add a PIT entry.
    this.removeRequests_.splice(removeRequestIndex, 1);
    return null;
  }

  var entry = new PendingInterestTable.Entry
    (pendingInterestId, interestCopy, onData, onTimeout, onNetworkNack);
  this.table_.push(entry);

  // Set interest timer.
  var timeoutMilliseconds = (interestCopy.getInterestLifetimeMilliseconds() || 4000);
  var thisTable = this;
  var timeoutCallback = function() {
    if (LOG > 1) console.log("Interest time out: " + interestCopy.getName().toUri());

    // Remove the entry from the table.
    var index = thisTable.table_.indexOf(entry);
    if (index >= 0)
      thisTable.table_.splice(index, 1);

    entry.callTimeout();
  };

  entry.setTimeout(timeoutCallback, timeoutMilliseconds);
  return entry;
};

/**
 * Find all entries from the pending interest table where data conforms to
 * the entry's interest selectors, remove the entries from the table, and add to
 * the entries list.
 * @param {Data} data The incoming Data packet to find the interest for.
 * @param {Array<PendingInterestTable.Entry>} entries Add matching
 * PendingInterestTable.Entry from the pending interest table. The caller should
 * pass in an empty array.
 */
PendingInterestTable.prototype.extractEntriesForExpressedInterest = function
  (data, entries)
{
  // Go backwards through the list so we can erase entries.
  for (var i = this.table_.length - 1; i >= 0; --i) {
    var pendingInterest = this.table_[i];
    if (pendingInterest.getInterest().matchesData(data)) {
      pendingInterest.clearTimeout();
      entries.push(pendingInterest);
      this.table_.splice(i, 1);
    }
  }
};

/**
 * Find all entries from the pending interest table where the OnNetworkNack
 * callback is not null and the entry's interest is the same as the given
 * interest, remove the entries from the table, and add to the entries list. 
 * (We don't remove the entry if the OnNetworkNack callback is null so that
 * OnTimeout will be called later.) The interests are the same if their default
 * wire encoding is the same (which has everything including the name, nonce,
 * link object and selectors).
 * @param {Interest} interest The Interest to search for (typically from a Nack
 * packet).
 * @param {Array<PendingInterestTable.Entry>} entries Add matching
 * PendingInterestTable.Entry from the pending interest table. The caller should
 * pass in an empty array.
 */
PendingInterestTable.prototype.extractEntriesForNackInterest = function
  (interest, entries)
{
  var encoding = interest.wireEncode();

  // Go backwards through the list so we can erase entries.
  for (var i = this.table_.length - 1; i >= 0; --i) {
    var pendingInterest = this.table_[i];
    if (pendingInterest.getOnNetworkNack() == null)
      continue;

    // wireEncode returns the encoding cached when the interest was sent (if
    // it was the default wire encoding).
    if (pendingInterest.getInterest().wireEncode().equals(encoding)) {
      pendingInterest.clearTimeout();
      entries.push(pendingInterest);
      this.table_.splice(i, 1);
    }
  }
};

/**
 * Remove the pending interest entry with the pendingInterestId from the pending
 * interest table. This does not affect another pending interest with a
 * different pendingInterestId, even if it has the same interest name.
 * If there is no entry with the pendingInterestId, do nothing.
 * @param {number} pendingInterestId The ID returned from expressInterest.
 */
PendingInterestTable.prototype.removePendingInterest = function
  (pendingInterestId)
{
  if (pendingInterestId == null)
    return;

  // Go backwards through the list so we can erase entries.
  // Remove all entries even though pendingInterestId should be unique.
  var count = 0;
  for (var i = this.table_.length - 1; i >= 0; --i) {
    var entry = this.table_[i];
    if (entry.getPendingInterestId() == pendingInterestId) {
      entry.clearTimeout();
      this.table_.splice(i, 1);
      ++count;
    }
  }

  if (count === 0)
    if (LOG > 0) console.log
      ("removePendingInterest: Didn't find pendingInterestId " + pendingInterestId);

  if (count === 0) {
    // The pendingInterestId was not found. Perhaps this has been called before
    //   the callback in expressInterest can add to the PIT. Add this
    //   removal request which will be checked before adding to the PIT.
    if (this.removeRequests_.indexOf(pendingInterestId) < 0)
      // Not already requested, so add the request.
      this.removeRequests_.push(pendingInterestId);
  }
};
/**
 * Copyright (C) 2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 *
 * 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.
 */

/** @ignore */
var LOG = require('../log.js').Log.LOG;

/**
 * A RegisteredPrefixTable is an internal class to hold a list of registered
 * prefixes with information necessary to remove the registration later.
 * @param {InterestFilterTable} interestFilterTable See removeRegisteredPrefix(),
 * which may call interestFilterTable.unsetInterestFilter().
 * @constructor
 */
var RegisteredPrefixTable = function RegisteredPrefixTable(interestFilterTable)
{
  this.interestFilterTable_ = interestFilterTable;
  this.table_ = []; // of Entry
  this.removeRequests_ = []; // of number
};

exports.RegisteredPrefixTable = RegisteredPrefixTable;

/**
 * Add a new entry to the table. However, if removeRegisteredPrefix was already
 * called with the registeredPrefixId, don't add an entry and return false.
 * @param {number} registeredPrefixId The ID from Node.getNextEntryId().
 * @param {Name} prefix The name prefix.
 * @param {number} relatedInterestFilterId (optional) The related
 * interestFilterId for the filter set in the same registerPrefix operation. If
 * omitted, set to 0.
 * return {boolean} True if added an entry, false if removeRegisteredPrefix was
 * already called with the registeredPrefixId.
 */
RegisteredPrefixTable.prototype.add = function
  (registeredPrefixId, prefix, relatedInterestFilterId)
{
  var removeRequestIndex = this.removeRequests_.indexOf(registeredPrefixId);
  if (removeRequestIndex >= 0) {
    // removeRegisteredPrefix was called with the registeredPrefixId returned by
    //   registerPrefix before we got here, so don't add a registered prefix
    //   table entry.
    this.removeRequests_.splice(removeRequestIndex, 1);
    return false;
  }

  this.table_.push(new RegisteredPrefixTable._Entry
    (registeredPrefixId, prefix, relatedInterestFilterId));
  return true;
};

/**
 * Remove the registered prefix entry with the registeredPrefixId from the
 * registered prefix table. This does not affect another registered prefix with
 * a different registeredPrefixId, even if it has the same prefix name. If an
 * interest filter was automatically created by registerPrefix, also call
 * interestFilterTable_.unsetInterestFilter to remove it.
 * If there is no entry with the registeredPrefixId, do nothing.
 * @param {number} registeredPrefixId The ID returned from registerPrefix.
 */
RegisteredPrefixTable.prototype.removeRegisteredPrefix = function
  (registeredPrefixId)
{
  // Go backwards through the list so we can erase entries.
  // Remove all entries even though registeredPrefixId should be unique.
  var count = 0;
  for (var i = this.table_.length - 1; i >= 0; --i) {
    var entry = this.table_[i];
    if (entry.getRegisteredPrefixId() == registeredPrefixId) {
      ++count;

      if (entry.getRelatedInterestFilterId() > 0)
        // Remove the related interest filter.
        this.interestFilterTable_.unsetInterestFilter
          (entry.getRelatedInterestFilterId());

      this.table_.splice(i, 1);
    }
  }

  if (count === 0)
    if (LOG > 0) console.log
      ("removeRegisteredPrefix: Didn't find registeredPrefixId " + registeredPrefixId);

  if (count === 0) {
    // The registeredPrefixId was not found. Perhaps this has been called before
    //   the callback in registerPrefix can add to the registered prefix table.
    //   Add this removal request which will be checked before adding to the
    //   registered prefix table.
    if (this.removeRequests_.indexOf(registeredPrefixId) < 0)
      // Not already requested, so add the request.
      this.removeRequests_.push(registeredPrefixId);
  }
};

/**
 * RegisteredPrefixTable._Entry holds a registeredPrefixId and information
 * necessary to remove the registration later. It optionally holds a related
 * interestFilterId if the InterestFilter was set in the same registerPrefix
 * operation.
 * Create a RegisteredPrefixTable.Entry with the given values.
 * @param {number} registeredPrefixId The ID from Node.getNextEntryId().
 * @param {Name} prefix The name prefix.
 * @param {number} relatedInterestFilterId (optional) The related
 * interestFilterId for the filter set in the same registerPrefix operation. If
 * omitted, set to 0.
 * @constructor
 */
RegisteredPrefixTable._Entry = function RegisteredPrefixTableEntry
  (registeredPrefixId, prefix, relatedInterestFilterId)
{
  this.registeredPrefixId_ = registeredPrefixId;
  this.prefix_ = prefix;
  this.relatedInterestFilterId_ = relatedInterestFilterId;
};

/**
 * Get the registeredPrefixId given to the constructor.
 * @return {number} The registeredPrefixId.
 */
RegisteredPrefixTable._Entry.prototype.getRegisteredPrefixId = function()
{
  return this.registeredPrefixId;
};

/**
 * Get the name prefix given to the constructor.
 * @return {Name} The name prefix.
 */
RegisteredPrefixTable._Entry.prototype.getPrefix = function()
{
  return this.prefix;
};

/**
 * Get the related interestFilterId given to the constructor.
 * @return {number} The related interestFilterId.
 */
RegisteredPrefixTable._Entry.prototype.getRelatedInterestFilterId = function()
{
  return this.relatedInterestFilterId;
};
/**
 * Copyright (C) 2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * @author: From ndn-cxx fields.hpp https://github.com/named-data/ndn-cxx/blob/master/src/lp/fields.hpp
 *
 * 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.
 */

/**
 * IncomingFaceId represents the incoming face ID header field in an NDNLPv2 packet.
 * http://redmine.named-data.net/projects/nfd/wiki/NDNLPv2
 * @constructor
 */
var IncomingFaceId = function IncomingFaceId()
{
  this.faceId_ = null;
};

exports.IncomingFaceId = IncomingFaceId;

/**
 * Get the incoming face ID value.
 * @return {number} The face ID value.
 */
IncomingFaceId.prototype.getFaceId = function() { return this.faceId_; };

/**
 * Set the face ID value.
 * @param {number} faceId The incoming face ID value.
 */
IncomingFaceId.prototype.setFaceId = function(faceId)
{
  this.faceId_ = faceId;
};

/**
 * Get the first header field in lpPacket which is an IncomingFaceId. This is
 * an internal method which the application normally would not use.
 * @param {LpPacket} lpPacket The LpPacket with the header fields to search.
 * @return {IncomingFaceId} The first IncomingFaceId header field, or null if
 * not found.
 */
IncomingFaceId.getFirstHeader = function(lpPacket)
{
  for (var i = 0; i < lpPacket.countHeaderFields(); ++i) {
    var field = lpPacket.getHeaderField(i);
    if (field instanceof IncomingFaceId)
      return field;
  }

  return null;
};
/**
 * Copyright (C) 2016 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * @author: From ndn-cxx packet.hpp https://github.com/named-data/ndn-cxx/blob/master/src/lp/packet.hpp
 *
 * 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.
 */

/** @ignore */
var Blob = require('../util/blob.js').Blob;

/**
 * An LpPacket represents an NDNLPv2 packet including header fields an an
 * optional fragment. This is an internal class which the application normally
 * would not use.
 * http://redmine.named-data.net/projects/nfd/wiki/NDNLPv2
 * @constructor
 */
var LpPacket = function LpPacket()
{
  this.headerFields_ = [];
  this.fragmentWireEncoding_ = new Blob();
};

exports.LpPacket = LpPacket;

/**
 * Get the fragment wire encoding.
 * @return {Blob} The wire encoding, or an isNull Blob if not specified.
 */
LpPacket.prototype.getFragmentWireEncoding = function()
{
  return this.fragmentWireEncoding_;
};

/**
 * Get the number of header fields. This does not include the fragment.
 * @return {number} The number of header fields.
 */
LpPacket.prototype.countHeaderFields = function()
{ 
  return this.headerFields_.length;
};

/**
 * Get the header field at the given index.
 * @param {number} index The index, starting from 0. It is an error if index is
 * greater to or equal to countHeaderFields().
 * @return {object} The header field at the index.
 */
LpPacket.prototype.getHeaderField = function(index)
{ 
  return this.headerFields_[index];
};

/**
 * Remove all header fields and set the fragment to an isNull Blob.
 */
LpPacket.prototype.clear = function()
{
  this.headerFields_ = [];
  this.fragmentWireEncoding_ = new Blob();
};

/**
 * Set the fragment wire encoding.
 * @param {Blob} fragmentWireEncoding The fragment wire encoding or an isNull
 * Blob if not specified.
 */
LpPacket.prototype.setFragmentWireEncoding = function(fragmentWireEncoding)
{
  this.fragmentWireEncoding_ =
    typeof fragmentWireEncoding === 'object' && fragmentWireEncoding instanceof Blob ?
      fragmentWireEncoding : new Blob(fragmentWireEncoding);
};

/**
 * Add a header field. To add the fragment, use setFragmentWireEncoding().
 * @param {object} headerField The header field to add.
 */
LpPacket.prototype.addHeaderField = function(headerField)
{ 
  this.headerFields_.push(headerField);
};
/**
 * This class represents the top-level object for communicating with an NDN host.
 * Copyright (C) 2013-2016 Regents of the University of California.
 * @author: Meki Cherkaoui, Jeff Thompson <jefft0@remap.ucla.edu>, Wentao Shang
 *
 * 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.
 */

/** @ignore */
var DataUtils = require('./encoding/data-utils.js').DataUtils; /** @ignore */
var Name = require('./name.js').Name; /** @ignore */
var Interest = require('./interest.js').Interest; /** @ignore */
var Data = require('./data.js').Data; /** @ignore */
var ControlParameters = require('./control-parameters.js').ControlParameters; /** @ignore */
var ControlResponse = require('./control-response.js').ControlResponse; /** @ignore */
var InterestFilter = require('./interest-filter.js').InterestFilter; /** @ignore */
var WireFormat = require('./encoding/wire-format.js').WireFormat; /** @ignore */
var TlvWireFormat = require('./encoding/tlv-wire-format.js').TlvWireFormat; /** @ignore */
var Tlv = require('./encoding/tlv/tlv.js').Tlv; /** @ignore */
var TlvDecoder = require('./encoding/tlv/tlv-decoder.js').TlvDecoder; /** @ignore */
var ForwardingFlags = require('./forwarding-flags.js').ForwardingFlags; /** @ignore */
var Transport = require('./transport/transport.js').Transport; /** @ignore */
var TcpTransport = require('./transport/tcp-transport.js').TcpTransport; /** @ignore */
var UnixTransport = require('./transport/unix-transport.js').UnixTransport; /** @ignore */
var CommandInterestGenerator = require('./util/command-interest-generator.js').CommandInterestGenerator; /** @ignore */
var Blob = require('./util/blob.js').Blob; /** @ignore */
var NdnCommon = require('./util/ndn-common.js').NdnCommon; /** @ignore */
var NetworkNack = require('./network-nack.js').NetworkNack; /** @ignore */
var LpPacket = require('./lp/lp-packet.js').LpPacket; /** @ignore */
var InterestFilterTable = require('./impl/interest-filter-table.js').InterestFilterTable; /** @ignore */
var PendingInterestTable = require('./impl/pending-interest-table.js').PendingInterestTable; /** @ignore */
var RegisteredPrefixTable = require('./impl/registered-prefix-table.js').RegisteredPrefixTable; /** @ignore */
var fs = require('fs'); /** @ignore */
var LOG = require('./log.js').Log.LOG;

/**
 * Create a new Face with the given settings.
 * This throws an exception if Face.supported is false.
 * There are two forms of the constructor.  The first form takes the transport and connectionInfo:
 * Face(transport, connectionInfo).  The second form takes an optional settings object:
 * Face([settings]).
 * @constructor
 * @param {Transport} transport An object of a subclass of Transport to use for
 * communication.
 * @param {Transport.ConnectionInfo} connectionInfo This must be a ConnectionInfo
 * from the same subclass of Transport as transport. If omitted and transport is
 * a new UnixTransport() then attempt to create to the Unix socket for the local
 * forwarder.
 * @param {Object} settings (optional) An associative array with the following defaults:
 * {
 *   getTransport: function() { return new WebSocketTransport(); }, // If in the browser.
 *              OR function() { return new TcpTransport(); },       // If in Node.js.
 *              // If getTransport creates a UnixTransport and connectionInfo is null,
 *              // then connect to the local forwarder's Unix socket.
 *   getConnectionInfo: transport.defaultGetConnectionInfo, // a function, on each call it returns a new Transport.ConnectionInfo or null if there are no more hosts.
 *                                                          // If connectionInfo or host is not null, getConnectionInfo is ignored.
 *   connectionInfo: null,
 *   host: null, // If null and connectionInfo is null, use getConnectionInfo when connecting.
 *               // However, if connectionInfo is not null, use it instead.
 *   port: 9696, // If in the browser.
 *      OR 6363, // If in Node.js.
 *               // However, if connectionInfo is not null, use it instead.
 *   onopen: function() { if (LOG > 3) console.log("NDN connection established."); },
 *   onclose: function() { if (LOG > 3) console.log("NDN connection closed."); },
 * }
 */
var Face = function Face(transportOrSettings, connectionInfo)
{
  if (!Face.supported)
    throw new Error("The necessary JavaScript support is not available on this platform.");

  var settings;
  if (typeof transportOrSettings == 'object' && transportOrSettings instanceof Transport) {
    this.getConnectionInfo = null;
    this.transport = transportOrSettings;
    this.connectionInfo = (connectionInfo || null);
    // Use defaults for other settings.
    settings = {};

    if (this.connectionInfo == null) {
      if (this.transport && this.transport.__proto__ &&
          this.transport.__proto__.name == "UnixTransport") {
        // Try to create the default connectionInfo for UnixTransport.
        var filePath = Face.getUnixSocketFilePathForLocalhost();
        if (filePath != null)
          this.connectionInfo = new UnixTransport.ConnectionInfo(filePath);
        else
          console.log
            ("Face constructor: Cannot determine the default Unix socket file path for UnixTransport");
        if (LOG > 0)
          console.log("Using " + this.connectionInfo.toString());
      }
    }
  }
  else {
    settings = (transportOrSettings || {});
    // For the browser, browserify-tcp-transport.js replaces TcpTransport with WebSocketTransport.
    var getTransport = (settings.getTransport || function() { return new TcpTransport(); });
    this.transport = getTransport();
    this.getConnectionInfo = (settings.getConnectionInfo || this.transport.defaultGetConnectionInfo);

    this.connectionInfo = (settings.connectionInfo || null);
    if (this.connectionInfo == null) {
      var host = (settings.host !== undefined ? settings.host : null);

      if (this.transport && this.transport.__proto__ &&
          this.transport.__proto__.name == "UnixTransport") {
        // We are using UnixTransport on Node.js. There is no IP-style host and port.
        if (host != null)
          // Assume the host is the local Unix socket path.
          this.connectionInfo = new UnixTransport.ConnectionInfo(host);
        else {
          // If getConnectionInfo is not null, it will be used instead so no
          // need to set this.connectionInfo.
          if (this.getConnectionInfo == null) {
            var filePath = Face.getUnixSocketFilePathForLocalhost();
            if (filePath != null)
              this.connectionInfo = new UnixTransport.ConnectionInfo(filePath);
            else
              console.log
                ("Face constructor: Cannot determine the default Unix socket file path for UnixTransport");
          }
        }
      }
      else {
        if (host != null) {
          if (typeof WebSocketTransport != 'undefined')
            this.connectionInfo = new WebSocketTransport.ConnectionInfo
              (host, settings.port || 9696);
          else
            this.connectionInfo = new TcpTransport.ConnectionInfo
              (host, settings.port || 6363);
        }
      }
    }
  }

  // Deprecated: Set this.host and this.port for backwards compatibility.
  if (this.connectionInfo == null) {
    this.host = null;
    this.host = null;
  }
  else {
    this.host = this.connectionInfo.host;
    this.host = this.connectionInfo.port;
  }

  this.readyStatus = Face.UNOPEN;

  // Event handler
  this.onopen = (settings.onopen || function() { if (LOG > 3) console.log("Face connection established."); });
  this.onclose = (settings.onclose || function() { if (LOG > 3) console.log("Face connection closed."); });
  // This is used by reconnectAndExpressInterest.
  this.onConnectedCallbacks = [];
  this.commandKeyChain = null;
  this.commandCertificateName = new Name();
  this.commandInterestGenerator = new CommandInterestGenerator();
  this.timeoutPrefix = new Name("/local/timeout");

  this.pendingInterestTable_ = new PendingInterestTable();
  this.interestFilterTable_ = new InterestFilterTable();
  this.registeredPrefixTable_ = new RegisteredPrefixTable(this.interestFilterTable_);
  this.lastEntryId = 0;
};

exports.Face = Face;

Face.UNOPEN = 0;  // the Face is created but not opened yet
Face.OPEN_REQUESTED = 1;  // requested to connect but onopen is not called.
Face.OPENED = 2;  // connection to the forwarder opened
Face.CLOSED = 3;  // connection to the forwarder closed

TcpTransport.importFace(Face);

/**
 * If the forwarder's Unix socket file path exists, then return the file path.
 * Otherwise return an empty string. This uses Node.js blocking file system
 * utilities.
 * @return The Unix socket file path to use, or an empty string.
 */
Face.getUnixSocketFilePathForLocalhost = function()
{
  var filePath = "/var/run/nfd.sock";
  if (fs.existsSync(filePath))
    return filePath;
  else {
    filePath = "/tmp/.ndnd.sock";
    if (fs.existsSync(filePath))
      return filePath;
    else
      return "";
  }
}

/**
 * Return true if necessary JavaScript support is available, else log an error and return false.
 */
Face.getSupported = function()
{
  try {
    var dummy = new Buffer(1).slice(0, 1);
  }
  catch (ex) {
    console.log("NDN not available: Buffer not supported. " + ex);
    return false;
  }

  return true;
};

Face.supported = Face.getSupported();

Face.prototype.createRoute = function(hostOrConnectionInfo, port)
{
  if (hostOrConnectionInfo instanceof Transport.ConnectionInfo)
    this.connectionInfo = hostOrConnectionInfo;
  else
    this.connectionInfo = new TcpTransport.ConnectionInfo(hostOrConnectionInfo, port);

  // Deprecated: Set this.host and this.port for backwards compatibility.
  this.host = this.connectionInfo.host;
  this.host = this.connectionInfo.port;
};

Face.prototype.close = function()
{
  if (this.readyStatus != Face.OPENED)
    return;

  this.readyStatus = Face.CLOSED;
  this.transport.close();
};

/**
 * An internal method to get the next unique entry ID for the pending interest
 * table, interest filter table, etc. Most entry IDs are for the pending
 * interest table (there usually are not many interest filter table entries) so
 * we use a common pool to only have to have one method which is called by Face.
 *
 * @return {number} The next entry ID.
 */
Face.prototype.getNextEntryId = function()
{
  return ++this.lastEntryId;
};

/**
 * Return a function that selects a host at random from hostList and returns
 * makeConnectionInfo(host, port), and if no more hosts remain, return null.
 * @param {Array<string>} hostList An array of host names.
 * @param {number} port The port for the connection.
 * @param {function} makeConnectionInfo This calls makeConnectionInfo(host, port)
 * to make the Transport.ConnectionInfo. For example:
 * function(host, port) { return new TcpTransport.ConnectionInfo(host, port); }
 * @return {function} A function which returns a Transport.ConnectionInfo.
 */
Face.makeShuffledHostGetConnectionInfo = function(hostList, port, makeConnectionInfo)
{
  // Make a copy.
  hostList = hostList.slice(0, hostList.length);
  DataUtils.shuffle(hostList);

  return function() {
    if (hostList.length == 0)
      return null;

    return makeConnectionInfo(hostList.splice(0, 1)[0], port);
  };
};

/**
 * Send the interest through the transport, read the entire response and call 
 * onData, onTimeout or onNetworkNack as described below.
 * There are two forms of expressInterest. The first form takes the exact
 * interest (including lifetime):
 * expressInterest(interest, onData [, onTimeout] [, onNetworkNack] [, wireFormat]).
 * The second form creates the interest from a name and optional interest template:
 * expressInterest(name [, template], onData [, onTimeout] [, onNetworkNack] [, wireFormat]).
 * @param {Interest} interest The Interest to send which includes the interest lifetime for the timeout.
 * @param {function} onData When a matching data packet is received, this calls onData(interest, data) where
 * interest is the interest given to expressInterest and data is the received
 * Data object. NOTE: You must not change the interest object - if you need to
 * change it then make a copy.
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onTimeout (optional) If the interest times out according to the interest lifetime,
 *   this calls onTimeout(interest) where:
 *   interest is the interest given to expressInterest.
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onNetworkNack (optional) When a network Nack packet for the
 * interest is received and onNetworkNack is not null, this calls
 * onNetworkNack(interest, networkNack) and does not call onTimeout. interest is
 * the sent Interest and networkNack is the received NetworkNack. If
 * onNetworkNack is supplied, then onTimeout must be supplied too. However, if a
 * network Nack is received and onNetworkNack is null, do nothing and wait for
 * the interest to time out. (Therefore, an application which does not yet
 * process a network Nack reason treats a Nack the same as a timeout.)
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {Name} name The Name for the interest. (only used for the second form of expressInterest).
 * @param {Interest} template (optional) If not omitted, copy the interest selectors from this Interest.
 * If omitted, use a default interest lifetime. (only used for the second form of expressInterest).
 * @param {WireFormat} (optional) A WireFormat object used to encode the message.
 * If omitted, use WireFormat.getDefaultWireFormat().
 * @return {number} The pending interest ID which can be used with removePendingInterest.
 * @throws Error If the encoded interest size exceeds Face.getMaxNdnPacketSize().
 */
Face.prototype.expressInterest = function
  (interestOrName, arg2, arg3, arg4, arg5, arg6)
{
  var interest;
  if (typeof interestOrName === 'object' && interestOrName instanceof Interest)
    // Just use a copy of the interest.
    interest = new Interest(interestOrName);
  else {
    // The first argument is a name. Make the interest from the name and possible template.
    if (arg2 && typeof arg2 === 'object' && arg2 instanceof Interest) {
      var template = arg2;
      // Copy the template.
      interest = new Interest(template);
      interest.setName(interestOrName);

      // Shift the remaining args to be processed below.
      arg2 = arg3;
      arg3 = arg4;
      arg4 = arg5;
      arg5 = arg6;
    }
    else {
      // No template.
      interest = new Interest(interestOrName);
      interest.setInterestLifetimeMilliseconds(4000);   // default interest timeout
    }
  }

  var onData = arg2;
  var onTimeout;
  var onNetworkNack;
  var wireFormat;
  // arg3,       arg4,          arg5 may be:
  // OnTimeout,  OnNetworkNack, WireFormat
  // OnTimeout,  OnNetworkNack, null
  // OnTimeout,  WireFormat,    null
  // OnTimeout,  null,          null
  // WireFormat, null,          null
  // null,       null,          null
  if (typeof arg3 === "function")
    onTimeout = arg3;
  else
    onTimeout = function() {};

  if (typeof arg4 === "function")
    onNetworkNack = arg4;
  else
    onNetworkNack = null;

  if (arg3 instanceof WireFormat)
    wireFormat = arg3;
  else if (arg4 instanceof WireFormat)
    wireFormat = arg4;
  else if (arg5 instanceof WireFormat)
    wireFormat = arg5;
  else
    wireFormat = WireFormat.getDefaultWireFormat();

  var pendingInterestId = this.getNextEntryId();

  // Set the nonce in our copy of the Interest so it is saved in the PIT.
  interest.setNonce(Face.nonceTemplate_);
  interest.refreshNonce();

  if (this.connectionInfo == null) {
    if (this.getConnectionInfo == null)
      console.log('ERROR: connectionInfo is NOT SET');
    else {
      var thisFace = this;
      this.connectAndExecute(function() {
        thisFace.reconnectAndExpressInterest
          (pendingInterestId, interest, onData, onTimeout, onNetworkNack,
           wireFormat);
      });
    }
  }
  else
    this.reconnectAndExpressInterest
      (pendingInterestId, interest, onData, onTimeout, onNetworkNack, wireFormat);

  return pendingInterestId;
};

/**
 * If the host and port are different than the ones in this.transport, then call
 *   this.transport.connect to change the connection (or connect for the first time).
 * Then call expressInterestHelper.
 */
Face.prototype.reconnectAndExpressInterest = function
  (pendingInterestId, interest, onData, onTimeout, onNetworkNack, wireFormat)
{
  var thisFace = this;
  if (!this.connectionInfo.equals(this.transport.connectionInfo) || this.readyStatus === Face.UNOPEN) {
    this.readyStatus = Face.OPEN_REQUESTED;
    this.onConnectedCallbacks.push
      (function() {
        thisFace.expressInterestHelper
          (pendingInterestId, interest, onData, onTimeout, onNetworkNack,
           wireFormat);
      });

    this.transport.connect
     (this.connectionInfo, this,
      function() {
        thisFace.readyStatus = Face.OPENED;

        // Execute each action requested while the connection was opening.
        while (thisFace.onConnectedCallbacks.length > 0) {
          try {
            thisFace.onConnectedCallbacks.shift()();
          } catch (ex) {
            console.log("Face.reconnectAndExpressInterest: ignoring exception from onConnectedCallbacks: " + ex);
          }
        }

        if (thisFace.onopen)
          // Call Face.onopen after success
          thisFace.onopen();
      },
      function() { thisFace.closeByTransport(); });
  }
  else {
    if (this.readyStatus === Face.OPEN_REQUESTED)
      // The connection is still opening, so add to the interests to express.
      this.onConnectedCallbacks.push
        (function() {
          thisFace.expressInterestHelper
            (pendingInterestId, interest, onData, onTimeout, onNetworkNack,
             wireFormat);
        });
    else if (this.readyStatus === Face.OPENED)
      this.expressInterestHelper
        (pendingInterestId, interest, onData, onTimeout, onNetworkNack,
         wireFormat);
    else
      throw new Error
        ("reconnectAndExpressInterest: unexpected connection is not opened");
  }
};

/**
 * Do the work of reconnectAndExpressInterest once we know we are connected.
 * Add the PendingInterest and call this.transport.send to send the interest.
 */
Face.prototype.expressInterestHelper = function
  (pendingInterestId, interest, onData, onTimeout, onNetworkNack, wireFormat)
{
  if (this.pendingInterestTable_.add
      (pendingInterestId, interest, onData, onTimeout, onNetworkNack) == null)
    // removePendingInterest was already called with the pendingInterestId.
    return;

  // Special case: For timeoutPrefix we don't actually send the interest.
  if (!this.timeoutPrefix.match(interest.getName())) {
    var binaryInterest = interest.wireEncode(wireFormat);
    if (binaryInterest.size() > Face.getMaxNdnPacketSize())
      throw new Error
        ("The encoded interest size exceeds the maximum limit getMaxNdnPacketSize()");

    this.transport.send(binaryInterest.buf());
  }
};

/**
 * Remove the pending interest entry with the pendingInterestId from the pending
 * interest table. This does not affect another pending interest with a
 * different pendingInterestId, even if it has the same interest name.
 * If there is no entry with the pendingInterestId, do nothing.
 * @param {number} pendingInterestId The ID returned from expressInterest.
 */
Face.prototype.removePendingInterest = function(pendingInterestId)
{
  this.pendingInterestTable_.removePendingInterest(pendingInterestId);
};

/**
 * Set the KeyChain and certificate name used to sign command interests (e.g.
 * for registerPrefix).
 * @param {KeyChain} keyChain The KeyChain object for signing interests, which
 * must remain valid for the life of this Face. You must create the KeyChain
 * object and pass it in. You can create a default KeyChain for your system with
 * the default KeyChain constructor.
 * @param {Name} certificateName The certificate name for signing interests.
 * This makes a copy of the Name. You can get the default certificate name with
 * keyChain.getDefaultCertificateName() .
 */
Face.prototype.setCommandSigningInfo = function(keyChain, certificateName)
{
  this.commandKeyChain = keyChain;
  this.commandCertificateName = new Name(certificateName);
};

/**
 * Set the certificate name used to sign command interest (e.g. for
 * registerPrefix), using the KeyChain that was set with setCommandSigningInfo.
 * @param {Name} certificateName The certificate name for signing interest. This
 * makes a copy of the Name.
 */
Face.prototype.setCommandCertificateName = function(certificateName)
{
  this.commandCertificateName = new Name(certificateName);
};

/**
 * Append a timestamp component and a random value component to interest's name.
 * Then use the keyChain and certificateName from setCommandSigningInfo to sign
 * the interest. If the interest lifetime is not set, this sets it.
 * @note This method is an experimental feature. See the API docs for more
 * detail at
 * http://named-data.net/doc/ndn-ccl-api/face.html#face-makecommandinterest-method .
 * @param {Interest} interest The interest whose name is appended with
 * components.
 * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
 * the SignatureInfo and to encode the interest name for signing.  If omitted,
 * use WireFormat.getDefaultWireFormat().
 * @param {function} onComplete (optional) This calls onComplete() when complete.
 * If omitted, block until complete. (Some crypto/database libraries only use a
 * callback, so onComplete is required to use these.)
 */
Face.prototype.makeCommandInterest = function(interest, wireFormat, onComplete)
{
  onComplete = (typeof wireFormat === "function") ? wireFormat : onComplete;
  wireFormat = (typeof wireFormat === "function" || !wireFormat) ?
                 WireFormat.getDefaultWireFormat() : wireFormat;
  this.nodeMakeCommandInterest
    (interest, this.commandKeyChain, this.commandCertificateName, wireFormat,
     onComplete);
};

/**
 * Append a timestamp component and a random value component to interest's name.
 * Then use the keyChain and certificateName from setCommandSigningInfo to sign
 * the interest. If the interest lifetime is not set, this sets it.
 * @param {Interest} interest The interest whose name is appended with
 * components.
 * @param {KeyChain} keyChain The KeyChain for calling sign.
 * @param {Name} certificateName The certificate name of the key to use for
 * signing.
 * @param {WireFormat} wireFormat A WireFormat object used to encode
 * the SignatureInfo and to encode the interest name for signing.
 * @param {function} onComplete (optional) This calls onComplete() when complete.
 * (Some crypto/database libraries only use a callback, so onComplete is
 * required to use these.)
 */
Face.prototype.nodeMakeCommandInterest = function
  (interest, keyChain, certificateName, wireFormat, onComplete)
{
  this.commandInterestGenerator.generate
    (interest, keyChain, certificateName, wireFormat, onComplete);
};

/**
 * Register prefix with the connected NDN hub and call onInterest when a
 * matching interest is received. To register a prefix with NFD, you must
 * first call setCommandSigningInfo.
 * This uses the form:
 * @param {Name} prefix The Name prefix.
 * @param {function} onInterest (optional) If not null, this creates an interest
 * filter from prefix so that when an Interest is received which matches the
 * filter, this calls
 * onInterest(prefix, interest, face, interestFilterId, filter).
 * NOTE: You must not change the prefix object - if you need to change it then
 * make a copy. If onInterest is null, it is ignored and you must call
 * setInterestFilter.
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onRegisterFailed If register prefix fails for any reason,
 * this calls onRegisterFailed(prefix) where:
 *   prefix is the prefix given to registerPrefix.
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {function} onRegisterSuccess (optional) When this receives a success
 * message, this calls onRegisterSuccess(prefix, registeredPrefixId) where
 * prefix is the prefix given to registerPrefix and registeredPrefixId is
 * the value retured by registerPrefix. If onRegisterSuccess is null or omitted,
 * this does not use it. (The onRegisterSuccess parameter comes after
 * onRegisterFailed because it can be null or omitted, unlike onRegisterFailed.)
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 * @param {ForwardingFlags} flags (optional) The ForwardingFlags object for
 * finer control of which interests are forward to the application. If omitted,
 * use the default flags defined by the default ForwardingFlags constructor.
 * @return {number} The registered prefix ID which can be used with
 * removeRegisteredPrefix.
 */
Face.prototype.registerPrefix = function
  (prefix, onInterest, onRegisterFailed, onRegisterSuccess, flags, wireFormat)
{
  // Temporarlity reassign to resolve the different overloaded forms.
  var arg4 = onRegisterSuccess;
  var arg5 = flags;
  var arg6 = wireFormat;
  // arg4, arg5, arg6 may be:
  // OnRegisterSuccess, ForwardingFlags, WireFormat
  // OnRegisterSuccess, ForwardingFlags, null
  // OnRegisterSuccess, WireFormat,      null
  // OnRegisterSuccess, null,            null
  // ForwardingFlags,   WireFormat,      null
  // ForwardingFlags,   null,            null
  // WireFormat,        null,            null
  // null,              null,            null
  if (typeof arg4 === "function")
    onRegisterSuccess = arg4;
  else
    onRegisterSuccess = null;

  if (arg4 instanceof ForwardingFlags)
    flags = arg4;
  else if (arg5 instanceof ForwardingFlags)
    flags = arg5;
  else
    flags = new ForwardingFlags();

  if (arg4 instanceof WireFormat)
    wireFormat = arg4;
  else if (arg5 instanceof WireFormat)
    wireFormat = arg5;
  else if (arg6 instanceof WireFormat)
    wireFormat = arg6;
  else
    wireFormat = WireFormat.getDefaultWireFormat();

  if (!onRegisterFailed)
    onRegisterFailed = function() {};

  var registeredPrefixId = this.getNextEntryId();
  var thisFace = this;
  var onConnected = function() {
    thisFace.nfdRegisterPrefix
      (registeredPrefixId, prefix, onInterest, flags, onRegisterFailed,
       onRegisterSuccess, thisFace.commandKeyChain,
       thisFace.commandCertificateName, wireFormat);
  };

  if (this.connectionInfo == null) {
    if (this.getConnectionInfo == null)
      console.log('ERROR: connectionInfo is NOT SET');
    else
      this.connectAndExecute(onConnected);
  }
  else
    onConnected();

  return registeredPrefixId;
};

/**
 * Get the practical limit of the size of a network-layer packet. If a packet
 * is larger than this, the library or application MAY drop it.
 * @return {number} The maximum NDN packet size.
 */
Face.getMaxNdnPacketSize = function() { return NdnCommon.MAX_NDN_PACKET_SIZE; };

/**
 * A RegisterResponse has onData to receive the response Data packet from the
 * register prefix interest sent to the connected NDN hub. If this gets a bad
 * response or onTimeout is called, then call onRegisterFailed.
 */
Face.RegisterResponse = function RegisterResponse
  (prefix, onRegisterFailed, onRegisterSuccess, registeredPrefixId, parent,
   onInterest)
{
  this.prefix = prefix;
  this.onRegisterFailed = onRegisterFailed;
  this.onRegisterSuccess= onRegisterSuccess;
  this.registeredPrefixId = registeredPrefixId;
  this.parent = parent;
  this.onInterest = onInterest;
};

Face.RegisterResponse.prototype.onData = function(interest, responseData)
{
  // Decode responseData.getContent() and check for a success code.
  var controlResponse = new ControlResponse();
  try {
    controlResponse.wireDecode(responseData.getContent(), TlvWireFormat.get());
  }
  catch (e) {
    // Error decoding the ControlResponse.
    if (LOG > 0)
      console.log("Register prefix failed: Error decoding the NFD response: " + e);
    if (this.onRegisterFailed) {
      try {
        this.onRegisterFailed(this.prefix);
      } catch (ex) {
        console.log("Error in onRegisterFailed: " + NdnCommon.getErrorWithStackTrace(ex));
      }
    }
    return;
  }

  // Status code 200 is "OK".
  if (controlResponse.getStatusCode() != 200) {
    if (LOG > 0)
      console.log("Register prefix failed: Expected NFD status code 200, got: " +
                  controlResponse.getStatusCode());
    if (this.onRegisterFailed) {
      try {
        this.onRegisterFailed(this.prefix);
      } catch (ex) {
        console.log("Error in onRegisterFailed: " + NdnCommon.getErrorWithStackTrace(ex));
      }
    }
    return;
  }

  // Success, so we can add to the registered prefix table.
  if (this.registeredPrefixId != 0) {
    var interestFilterId = 0;
    if (this.onInterest != null)
      // registerPrefix was called with the "combined" form that includes the
      // callback, so add an InterestFilterEntry.
      interestFilterId = this.parent.setInterestFilter
        (new InterestFilter(this.prefix), this.onInterest);

    if (!this.parent.registeredPrefixTable_.add
        (this.registeredPrefixId, this.prefix, interestFilterId)) {
      // removeRegisteredPrefix was already called with the registeredPrefixId.
      if (interestFilterId > 0)
        // Remove the related interest filter we just added.
        this.parent.unsetInterestFilter(interestFilterId);

      return;
    }
  }

  if (LOG > 2)
    console.log("Register prefix succeeded with the NFD forwarder for prefix " +
                this.prefix.toUri());
  if (this.onRegisterSuccess != null) {
    try {
      this.onRegisterSuccess(this.prefix, this.registeredPrefixId);
    } catch (ex) {
      console.log("Error in onRegisterSuccess: " + NdnCommon.getErrorWithStackTrace(ex));
    }
  }
};

/**
 * We timed out waiting for the response.
 */
Face.RegisterResponse.prototype.onTimeout = function(interest)
{
  if (LOG > 2)
    console.log("Timeout for NFD register prefix command.");
  if (this.onRegisterFailed) {
    try {
      this.onRegisterFailed(this.prefix);
    } catch (ex) {
      console.log("Error in onRegisterFailed: " + NdnCommon.getErrorWithStackTrace(ex));
    }
  }
};

/**
 * Do the work of registerPrefix to register with NFD.
 * @param {number} registeredPrefixId The Face.getNextEntryId() which
 * registerPrefix got so it could return it to the caller. If this is 0, then
 * don't add to registeredPrefixTable (assuming it has already been done).
 * @param {Name} prefix
 * @param {function} onInterest
 * @param {ForwardingFlags} flags
 * @param {function} onRegisterFailed
 * @param {function} onRegisterSuccess
 * @param {KeyChain} commandKeyChain
 * @param {Name} commandCertificateName
 * @param {WireFormat} wireFormat
 */
Face.prototype.nfdRegisterPrefix = function
  (registeredPrefixId, prefix, onInterest, flags, onRegisterFailed,
   onRegisterSuccess, commandKeyChain, commandCertificateName, wireFormat)
{
  if (commandKeyChain == null)
      throw new Error
        ("registerPrefix: The command KeyChain has not been set. You must call setCommandSigningInfo.");
  if (commandCertificateName.size() == 0)
      throw new Error
        ("registerPrefix: The command certificate name has not been set. You must call setCommandSigningInfo.");

  var controlParameters = new ControlParameters();
  controlParameters.setName(prefix);
  controlParameters.setForwardingFlags(flags);

  // Make the callback for this.isLocal().
  var thisFace = this;
  var onIsLocalResult = function(isLocal) {
    var commandInterest = new Interest();
    if (isLocal) {
      commandInterest.setName(new Name("/localhost/nfd/rib/register"));
      // The interest is answered by the local host, so set a short timeout.
      commandInterest.setInterestLifetimeMilliseconds(2000.0);
    }
    else {
      commandInterest.setName(new Name("/localhop/nfd/rib/register"));
      // The host is remote, so set a longer timeout.
      commandInterest.setInterestLifetimeMilliseconds(4000.0);
    }
    // NFD only accepts TlvWireFormat packets.
    commandInterest.getName().append
      (controlParameters.wireEncode(TlvWireFormat.get()));
    thisFace.nodeMakeCommandInterest
      (commandInterest, commandKeyChain, commandCertificateName,
       TlvWireFormat.get(), function() {
      // Send the registration interest.
      var response = new Face.RegisterResponse
         (prefix, onRegisterFailed, onRegisterSuccess, registeredPrefixId,
          thisFace, onInterest);
      thisFace.reconnectAndExpressInterest
        (null, commandInterest, response.onData.bind(response),
         response.onTimeout.bind(response), null, wireFormat);
    });
  };

  this.isLocal
    (onIsLocalResult,
     function(message) {
       if (LOG > 0)
         console.log("Error in Transport.isLocal: " + message);
       if (onRegisterFailed) {
         try {
           onRegisterFailed(prefix);
         } catch (ex) {
           console.log("Error in onRegisterFailed: " + NdnCommon.getErrorWithStackTrace(ex));
         }
       }
     });
};

/**
 * Remove the registered prefix entry with the registeredPrefixId from the
 * registered prefix table. This does not affect another registered prefix with
 * a different registeredPrefixId, even if it has the same prefix name. If an
 * interest filter was automatically created by registerPrefix, also remove it.
 * If there is no entry with the registeredPrefixId, do nothing.
 *
 * @param {number} registeredPrefixId The ID returned from registerPrefix.
 */
Face.prototype.removeRegisteredPrefix = function(registeredPrefixId)
{
  this.registeredPrefixTable_.removeRegisteredPrefix(registeredPrefixId);
};

/**
 * Add an entry to the local interest filter table to call the onInterest
 * callback for a matching incoming Interest. This method only modifies the
 * library's local callback table and does not register the prefix with the
 * forwarder. It will always succeed. To register a prefix with the forwarder,
 * use registerPrefix. There are two forms of setInterestFilter.
 * The first form uses the exact given InterestFilter:
 * setInterestFilter(filter, onInterest).
 * The second form creates an InterestFilter from the given prefix Name:
 * setInterestFilter(prefix, onInterest).
 * @param {InterestFilter} filter The InterestFilter with a prefix and optional
 * regex filter used to match the name of an incoming Interest. This makes a
 * copy of filter.
 * @param {Name} prefix The Name prefix used to match the name of an incoming
 * Interest.
 * @param {function} onInterest When an Interest is received which matches the
 * filter, this calls onInterest(prefix, interest, face, interestFilterId, filter).
 * NOTE: The library will log any exceptions thrown by this callback, but for
 * better error handling the callback should catch and properly handle any
 * exceptions.
 */
Face.prototype.setInterestFilter = function(filterOrPrefix, onInterest)
{
  var interestFilterId = this.getNextEntryId();
  this.interestFilterTable_.setInterestFilter
    (interestFilterId, new InterestFilter(filterOrPrefix), onInterest, this);
  return interestFilterId;
};

/**
 * Remove the interest filter entry which has the interestFilterId from the
 * interest filter table. This does not affect another interest filter with a
 * different interestFilterId, even if it has the same prefix name. If there is
 * no entry with the interestFilterId, do nothing.
 * @param {number} interestFilterId The ID returned from setInterestFilter.
 */
Face.prototype.unsetInterestFilter = function(interestFilterId)
{
  this.interestFilterTable_.unsetInterestFilter(interestFilterId);
};

/**
 * The OnInterest callback calls this to put a Data packet which satisfies an
 * Interest.
 * @param {Data} data The Data packet which satisfies the interest.
 * @param {WireFormat} wireFormat (optional) A WireFormat object used to encode
 * the Data packet. If omitted, use WireFormat.getDefaultWireFormat().
 * @throws Error If the encoded Data packet size exceeds getMaxNdnPacketSize().
 */
Face.prototype.putData = function(data, wireFormat)
{
  wireFormat = (wireFormat || WireFormat.getDefaultWireFormat());

  var encoding = data.wireEncode(wireFormat);
  if (encoding.size() > Face.getMaxNdnPacketSize())
    throw new Error
      ("The encoded Data packet size exceeds the maximum limit getMaxNdnPacketSize()");

  this.transport.send(encoding.buf());
};

/**
 * Send the encoded packet out through the transport.
 * @param {Buffer} encoding The Buffer with the encoded packet to send.
 * @throws Error If the encoded packet size exceeds getMaxNdnPacketSize().
 */
Face.prototype.send = function(encoding)
{
  if (encoding.length > Face.getMaxNdnPacketSize())
    throw new Error
      ("The encoded packet size exceeds the maximum limit getMaxNdnPacketSize()");

  this.transport.send(encoding);
};

/**
 * Check if the face is local based on the current connection through the
 * Transport; some Transport may cause network I/O (e.g. an IP host name lookup).
 * @param {function} onResult On success, this calls onResult(isLocal) where
 * isLocal is true if the host is local, false if not. We use callbacks because
 * this may need to do network I/O (e.g. an IP host name lookup).
 * @param {function} onError On failure for DNS lookup or other error, this
 * calls onError(message) where message is an error string.
 */
Face.prototype.isLocal = function(onResult, onError)
{
  // TODO: How to call transport.isLocal when this.connectionInfo is null? (This
  // happens when the application does not supply a host but relies on the
  // getConnectionInfo function to select a host.) For now return true to keep
  // the same behavior from before we added Transport.isLocal.
  if (this.connectionInfo == null)
    onResult(false);
  else
    this.transport.isLocal(this.connectionInfo, onResult, onError);
};

/**
 * This is called when an entire element is received, such as a Data or Interest.
 */
Face.prototype.onReceivedElement = function(element)
{
  if (LOG > 3) console.log('Complete element received. Length ' + element.length + '. Start decoding.');

  var lpPacket = null;
  if (element[0] == Tlv.LpPacket_LpPacket) {
    // Decode the LpPacket and replace element with the fragment.
    lpPacket = new LpPacket();
    // Set copy false so that the fragment is a slice which will be copied below.
    // The header fields are all integers and don't need to be copied.
    TlvWireFormat.get().decodeLpPacket(lpPacket, element, false);
    element = lpPacket.getFragmentWireEncoding().buf();
  }

  // First, decode as Interest or Data.
  var interest = null;
  var data = null;
  if (element[0] == Tlv.Interest || element[0] == Tlv.Data) {
    var decoder = new TlvDecoder (element);
    if (decoder.peekType(Tlv.Interest, element.length)) {
      interest = new Interest();
      interest.wireDecode(element, TlvWireFormat.get());

      if (lpPacket != null)
        interest.setLpPacket(lpPacket);
    }
    else if (decoder.peekType(Tlv.Data, element.length)) {
      data = new Data();
      data.wireDecode(element, TlvWireFormat.get());

      if (lpPacket != null)
        data.setLpPacket(lpPacket);
    }
  }

  if (lpPacket !== null) {
    // We have decoded the fragment, so remove the wire encoding to save memory.
    lpPacket.setFragmentWireEncoding(new Blob());

    var networkNack = NetworkNack.getFirstHeader(lpPacket);
    if (networkNack != null) {
      if (interest == null)
        // We got a Nack but not for an Interest, so drop the packet.
        return;

      var pitEntries = [];
      this.pendingInterestTable_.extractEntriesForNackInterest(interest, pitEntries);
      for (var i = 0; i < pitEntries.length; ++i) {
        var pendingInterest = pitEntries[i];
        try {
          pendingInterest.getOnNetworkNack()(pendingInterest.getInterest(), networkNack);
        } catch (ex) {
          console.log("Error in onNetworkNack: " + NdnCommon.getErrorWithStackTrace(ex));
        }
      }

      // We have processed the network Nack packet.
      return;
    }
  }

  // Now process as Interest or Data.
  if (interest !== null) {
    if (LOG > 3) console.log('Interest packet received.');

    // Call all interest filter callbacks which match.
    var matchedFilters = [];
    this.interestFilterTable_.getMatchedFilters(interest, matchedFilters);
    for (var i = 0; i < matchedFilters.length; ++i) {
      var entry = matchedFilters[i];
      if (LOG > 3)
        console.log("Found interest filter for " + interest.getName().toUri());
      try {
        entry.getOnInterest()
          (entry.getFilter().getPrefix(), interest, this,
           entry.getInterestFilterId(), entry.getFilter());
      } catch (ex) {
        console.log("Error in onInterest: " + NdnCommon.getErrorWithStackTrace(ex));
      }
    }
  }
  else if (data !== null) {
    if (LOG > 3) console.log('Data packet received.');

    var pendingInterests = [];
    this.pendingInterestTable_.extractEntriesForExpressedInterest
      (data, pendingInterests);
    // Process each matching PIT entry (if any).
    for (var i = 0; i < pendingInterests.length; ++i) {
      var pendingInterest = pendingInterests[i];
      try {
        pendingInterest.getOnData()(pendingInterest.getInterest(), data);
      } catch (ex) {
        console.log("Error in onData: " + NdnCommon.getErrorWithStackTrace(ex));
      }
    }
  }
};

/**
 * Assume this.getConnectionInfo is not null.  This is called when
 * this.connectionInfo is null or its host is not alive.
 * Get a connectionInfo, connect, then execute onConnected().
 */
Face.prototype.connectAndExecute = function(onConnected)
{
  var connectionInfo = this.getConnectionInfo();
  if (connectionInfo == null) {
    console.log('ERROR: No more connectionInfo from getConnectionInfo');
    this.connectionInfo = null;
    // Deprecated: Set this.host and this.port for backwards compatibility.
    this.host = null;
    this.host = null;

    return;
  }

  if (connectionInfo.equals(this.connectionInfo)) {
    console.log
      ('ERROR: The host returned by getConnectionInfo is not alive: ' +
       this.connectionInfo.toString());
    return;
  }

  this.connectionInfo = connectionInfo;
  if (LOG>0) console.log("connectAndExecute: trying host from getConnectionInfo: " +
                         this.connectionInfo.toString());
  // Deprecated: Set this.host and this.port for backwards compatibility.
  this.host = this.connectionInfo.host;
  this.host = this.connectionInfo.port;

  // Fetch any content.
  var interest = new Interest(new Name("/"));
  interest.setInterestLifetimeMilliseconds(4000);

  var thisFace = this;
  var timerID = setTimeout(function() {
    if (LOG>0) console.log("connectAndExecute: timeout waiting for host " + thisFace.host);
      // Try again.
      thisFace.connectAndExecute(onConnected);
  }, 3000);

  this.reconnectAndExpressInterest
    (null, interest,
     function(localInterest, localData) {
        // The host is alive, so cancel the timeout and continue with onConnected().
        clearTimeout(timerID);

        if (LOG>0)
          console.log("connectAndExecute: connected to host " + thisFace.host);
        onConnected();
     },
     function(localInterest) { /* Ignore timeout */ },
     null, WireFormat.getDefaultWireFormat());
};

/**
 * This is called by the Transport when the connection is closed by the remote host.
 */
Face.prototype.closeByTransport = function()
{
  this.readyStatus = Face.CLOSED;
  this.onclose();
};

Face.nonceTemplate_ = new Blob(new Buffer(4), false);
(function(n,t,i){"use strict";function s(n,t){return typeof t!="object"&&(t=t()),Object.keys(t).forEach(function(i){n[i]=t[i]}),n}function y(n){return{from:function(t){return n.prototype=Object.create(t.prototype),n.prototype.constructor=n,{extend:function(i){s(n.prototype,typeof i!="object"?i(t.prototype):i)}}}}}function p(n,t){return t(n)}function u(n,t){function cr(){w.on("versionchange",function(){w.close();w.on("error").fire(new g("Database version changed by other database connection."))})}function di(n){this._cfg={version:n,storesSource:null,dbschema:{},tables:{},contentUpgrade:null};this.stores({})}function lr(n,t,i,u){var e,f,s,h,l,c;if(n===0)Object.keys(st).forEach(function(n){gi(t,n,st[n].primKey,st[n].indexes)}),e=w._createTransaction(yt,ui,st),e.idbtrans=t,e.idbtrans.onerror=o(i,["populating database"]),e.on("error").subscribe(i),r.newPSD(function(){r.PSD.trans=e;try{w.on("populate").fire(e)}catch(n){u.onerror=t.onerror=function(n){n.preventDefault()};try{t.abort()}catch(f){}t.db.close();i(n)}});else{if(f=[],s=ri.filter(function(t){return t._cfg.version===n})[0],!s)throw new g("Dexie specification of currently installed DB version is missing");st=w._dbSchema=s._cfg.dbschema;h=!1;l=ri.filter(function(t){return t._cfg.version>n});l.forEach(function(n){var e=st,r=n._cfg.dbschema,u;fr(e,t);fr(r,t);st=w._dbSchema=r;u=ar(e,r);u.add.forEach(function(n){f.push(function(t,i){gi(t,n[0],n[1].primKey,n[1].indexes);i()})});u.change.forEach(function(n){if(n.recreate)throw new g("Not yet support for changing primary key");else f.push(function(t,i){var r=t.objectStore(n.name);n.add.forEach(function(n){nr(r,n)});n.change.forEach(function(n){r.deleteIndex(n.name);nr(r,n)});n.del.forEach(function(n){r.deleteIndex(n)});i()})});n._cfg.contentUpgrade&&f.push(function(t,u){var f,e;h=!0;f=w._createTransaction(yt,[].slice.call(t.db.objectStoreNames,0),r);f.idbtrans=t;e=0;f._promise=p(f._promise,function(n){return function(t,i,r){function f(n){return function(){n.apply(this,arguments);--e==0&&u()}}return++e,n.call(this,t,function(n,t){arguments[0]=f(n);arguments[1]=f(t);i.apply(this,arguments)},r)}});t.onerror=o(i,["running upgrader function for version",n._cfg.version]);f.on("error").subscribe(i);n._cfg.contentUpgrade(f);e===0&&u()});h&&dr()||f.push(function(n,t){yr(r,n);t()})});c=function(){try{f.length?f.shift()(t,c):vr(st,t)}catch(n){u.onerror=t.onerror=function(n){n.preventDefault()};try{t.abort()}catch(r){}t.db.close();i(n)}};c()}}function ar(n,t){var f={del:[],add:[],change:[]},r,e,o,i,c,s,u,l,h;for(r in n)t[r]||f.del.push(r);for(r in t)if(e=n[r],o=t[r],e)if(i={name:r,def:t[r],recreate:!1,del:[],add:[],change:[]},e.primKey.src!==o.primKey.src)i.recreate=!0,f.change.push(i);else{c=e.indexes.reduce(function(n,t){return n[t.name]=t,n},{});s=o.indexes.reduce(function(n,t){return n[t.name]=t,n},{});for(u in c)s[u]||i.del.push(u);for(u in s)l=c[u],h=s[u],l?l.src!==h.src&&i.change.push(h):i.add.push(h);(i.recreate||i.del.length>0||i.add.length>0||i.change.length>0)&&f.change.push(i)}else f.add.push([r,o]);return f}function gi(n,t,i,r){var u=n.db.createObjectStore(t,i.keyPath?{keyPath:i.keyPath,autoIncrement:i.auto}:{autoIncrement:i.auto});return r.forEach(function(n){nr(u,n)}),u}function vr(n,t){Object.keys(n).forEach(function(i){t.db.objectStoreNames.contains(i)||gi(t,i,n[i].primKey,n[i].indexes)})}function yr(n,t){for(var u,r=0;r<t.db.objectStoreNames.length;++r)u=t.db.objectStoreNames[r],(n[u]===null||n[u]===i)&&t.db.deleteObjectStore(u)}function nr(n,t){n.createIndex(t.name,t.keyPath,{unique:t.unique,multiEntry:t.multi})}function pr(n,t){throw new g("Table "+t[0]+" not part of transaction. Original Scope Function Source: "+u.Promise.PSD.trans.scopeFunc.toString());}function ei(n,t,i,r){this.name=n;this.schema=i;this.hook=ni[n]?ni[n].hook:v(null,{creating:[at,f],reading:[lt,nt],updating:[vt,f],deleting:[wt,f]});this._tpf=t;this._collClass=r||li}function tr(n,t,i,r){ei.call(this,n,t,i,r||rr)}function ir(n,t,i,r){function o(n,t,i,r){return s._promise(n,i,r)}var s=this,f,u,e;for(this.db=w,this.mode=n,this.storeNames=t,this.idbtrans=null,this.on=v(this,["complete","error"],"abort"),this._reculock=0,this._blockedFuncs=[],this._psd=null,this.active=!0,this._dbschema=i,r&&(this.parent=r),this._tpf=o,this.tables=Object.create(ki),f=t.length-1;f!==-1;--f)u=t[f],e=w._tableFactory(n,i[u],o),this.tables[u]=e,this[u]||(this[u]=e)}function ci(n,t,i){this._ctx={table:n,index:t===":id"?null:t,collClass:n._collClass,or:i}}function li(n,t){var r=null,u=null,i;if(t)try{r=t()}catch(f){u=f}i=n._ctx;this._ctx={table:i.table,index:i.index,isPrimKey:!i.index||i.table.schema.primKey.keyPath&&i.index===i.table.schema.primKey.name,range:r,op:"openCursor",dir:"next",unique:"",algorithm:null,filter:null,isMatch:null,offset:0,limit:Infinity,error:u,or:i.or}}function rr(){li.apply(this,arguments)}function wr(n,t){return n._cfg.version-t._cfg.version}function ur(n,t,i,u,f,e){i.forEach(function(i){var o=w._tableFactory(u,f[i],t);n.forEach(function(n){n[i]||(e?Object.defineProperty(n,i,{configurable:!0,enumerable:!0,get:function(){var n=r.PSD&&r.PSD.trans;return n&&n.db===w?n.tables[i]:o}}):n[i]=o)})})}function br(n){n.forEach(function(n){for(var t in n)n[t]instanceof ei&&delete n[t]})}function pi(n,t,i,u,f,e){var s=r.PSD;e=e||nt;n.onerror||(n.onerror=o(f));n.onsuccess=t?k(function(){var r=n.result,o;r?(o=function(){r.continue()},t(r,function(n){o=n},u,f)&&i(e(r.value),r,function(n){o=n}),o()):u()},f,s):k(function(){var t=n.result,r;t?(r=function(){t.continue()},i(e(t.value),t,function(n){r=n}),r()):u()},f,s)}function kr(n){var t=[];return n.split(",").forEach(function(n){n=n.trim();var i=n.replace("&","").replace("++","").replace("*",""),r=i.indexOf("[")!==0?i:n.substring(n.indexOf("[")+1,n.indexOf("]")).split("+");t.push(new a(i,r||null,n.indexOf("&")!==-1,n.indexOf("*")!==-1,n.indexOf("++")!==-1,Array.isArray(r),r.indexOf(".")!==-1))}),t}function wi(n,t){return n<t?-1:n>t?1:0}function or(n,t){return n<t?1:n>t?-1:0}function sr(n){return function(t,i){for(var r=0,u;;){if(u=n(t[r],i[r]),u!==0)return u;if(++r,r===t.length||r===i.length)return n(t.length,i.length)}}}function bi(n,t){return n?t?function(){return n.apply(this,arguments)&&t.apply(this,arguments)}:n:t}function dr(){return navigator.userAgent.indexOf("Trident")>=0||navigator.userAgent.indexOf("MSIE")>=0}function gr(){if(w.verno=et.version/10,w._dbSchema=st={},ui=[].slice.call(et.objectStoreNames,0),ui.length!==0){var n=et.transaction(ft(ui),"readonly");ui.forEach(function(t){for(var u,s,r=n.objectStore(t),i=r.keyPath,f=i&&typeof i=="string"&&i.indexOf(".")!==-1,h=new a(i,i||"",!1,!1,!!r.autoIncrement,i&&typeof i!="string",f),o=[],e=0;e<r.indexNames.length;++e)u=r.index(r.indexNames[e]),i=u.keyPath,f=i&&typeof i=="string"&&i.indexOf(".")!==-1,s=new a(u.name,i,!!u.unique,!!u.multiEntry,!1,i&&typeof i!="string",f),o.push(s);st[t]=new ut(t,h,o,{})});ur([ni],w._transPromiseFactory,Object.keys(st),yt,st)}}function fr(n,t){for(var i,r,u,o,s=t.db.objectStoreNames,f=0;f<s.length;++f)for(i=s[f],r=t.objectStore(i),u=0;u<r.indexNames.length;++u){var h=r.indexNames[u],e=r.index(h).keyPath,c=typeof e=="string"?e:"["+[].slice.call(e).join("+")+"]";n[i]&&(o=n[i].idxByName[c],o&&(o.name=h))}}var hr=t&&t.addons||u.addons,oi=u.dependencies,ai=oi.indexedDB,kt=oi.IDBKeyRange,nu=oi.IDBTransaction,tu=oi.DOMError,yi=oi.TypeError,g=oi.Error,st=this._dbSchema={},ri=[],ui=[],ni={},ki={},et=null,si=!0,fi=null,vi=!1,ti="readonly",yt="readwrite",w=this,ii=[],hi=!1,er=!!ct();this.version=function(n){if(et)throw new g("Cannot add version when database is open");this.verno=Math.max(this.verno,n);var t=ri.filter(function(t){return t._cfg.version===n})[0];return t?t:(t=new di(n),ri.push(t),ri.sort(wr),t)};s(di.prototype,{stores:function(n){var i,t;return this._cfg.storesSource=this._cfg.storesSource?s(this._cfg.storesSource,n):n,i={},ri.forEach(function(n){s(i,n._cfg.storesSource)}),t=this._cfg.dbschema={},this._parseStoresSpec(i,t),st=w._dbSchema=t,br([ni,w,ki]),ur([ki],pr,Object.keys(t),yt,t),ur([ni,w,this._cfg.tables],w._transPromiseFactory,Object.keys(t),yt,t,!0),ui=Object.keys(t),this},upgrade:function(n){var t=this;return e(function(){n(w._createTransaction(yt,Object.keys(t._cfg.dbschema),t._cfg.dbschema))}),this._cfg.contentUpgrade=n,this},_parseStoresSpec:function(n,t){Object.keys(n).forEach(function(i){if(n[i]!==null){var u={},f=kr(n[i]),r=f.shift();if(r.multi)throw new g("Primary key cannot be multi-valued");r.keyPath&&r.auto&&h(u,r.keyPath,0);f.forEach(function(n){if(n.auto)throw new g("Only primary key can be marked as autoIncrement (++)");if(!n.keyPath)throw new g("Index must have a name and cannot be an empty string");h(u,n.keyPath,n.compound?n.keyPath.map(function(){return""}):"")});t[i]=new ut(i,r,f,u)}})}});this._allTables=ni;this._tableFactory=function(n,t,i){return n===ti?new ei(t.name,i,t,li):new tr(t.name,i,t)};this._createTransaction=function(n,t,i,r){return new ir(n,t,i,r)};this._transPromiseFactory=function(n,t,i){var f,u;return!si||r.PSD&&r.PSD.letThrough?(u=w._createTransaction(n,t,st),u._promise(n,function(n,t){u.error(function(n){w.on("error").fire(n)});i(function(t){u.complete(function(){n(t)})},t,u)})):f=new r(function(r,u){ii.push({resume:function(){var e=w._transPromiseFactory(n,t,i);f.onuncatched=e.onuncatched;e.then(r,u)}})})};this._whenReady=function(n){return si&&(!r.PSD||!r.PSD.letThrough)?new r(function(t,i){e(function(){new r(function(){n(t,i)})});ii.push({resume:function(){n(t,i)}})}):new r(n)};this.verno=0;this.open=function(){return new r(function(t,i){function f(n){try{u.transaction.abort()}catch(t){}vi=!1;fi=n;si=!1;i(fi);ii.forEach(function(n){n.resume()});ii=[]}if(et||vi)throw new g("Database already opened or being opened");var u,e=!1;try{if(fi=null,vi=!0,ri.length===0&&(hi=!0),!ai)throw new g("indexedDB API not found. If using IE10+, make sure to run your code on a server URL (not locally). If using Safari, make sure to include indexedDB polyfill.");u=hi?ai.open(n):ai.open(n,Math.round(w.verno*10));u.onerror=o(f,["opening database",n]);u.onblocked=function(n){w.on("blocked").fire(n)};u.onupgradeneeded=k(function(t){var i,r;hi&&!w._allowEmptyDB?(u.onerror=function(n){n.preventDefault()},u.transaction.abort(),u.result.close(),i=ai.deleteDatabase(n),i.onsuccess=i.onerror=function(){f(new g("Database '"+n+"' doesnt exist"))}):(t.oldVersion===0&&(e=!0),u.transaction.onerror=o(f),r=t.oldVersion>Math.pow(2,62)?0:t.oldVersion,lr(r/10,u.transaction,f,u))},f);u.onsuccess=k(function(){vi=!1;et=u.result;hi?gr():et.objectStoreNames.length>0&&fr(st,et.transaction(ft(et.objectStoreNames),ti));et.onversionchange=w.on("versionchange").fire;er||rt(function(t){if(t.indexOf(n)===-1)return t.push(n)});r.newPSD(function(){function i(){si=!1;ii.forEach(function(n){n.resume()});ii=[];t()}r.PSD.letThrough=!0;try{var n=w.on.ready.fire();n&&typeof n.then=="function"?n.then(i,function(n){et.close();et=null;f(n)}):b(i)}catch(u){f(u)}})},f)}catch(s){f(s)}})};this.close=function(){et&&(et.close(),et=null,si=!0,fi=null)};this.delete=function(){var t=arguments;return new r(function(i,r){function u(){w.close();var t=ai.deleteDatabase(n);t.onsuccess=function(){er||rt(function(t){var i=t.indexOf(n);if(i>=0)return t.splice(i,1)});i()};t.onerror=o(r,["deleting",n]);t.onblocked=function(){w.on("blocked").fire()}}if(t.length>0)throw new g("Arguments not allowed in db.delete()");vi?ii.push({resume:u}):u()})};this.backendDB=function(){return et};this.isOpen=function(){return et!==null};this.hasFailed=function(){return fi!==null};this.dynamicallyOpened=function(){return hi};this.name=n;Object.defineProperty(this,"tables",{get:function(){return Object.keys(ni).map(function(n){return ni[n]})}});this.on=v(this,"error","populate","blocked",{ready:[bt,f],versionchange:[pt,f]});this.on.ready.subscribe=p(this.on.ready.subscribe,function(n){return function(t,i){function r(){return i||w.on.ready.unsubscribe(r),t.apply(this,arguments)}n.call(this,r);w.isOpen()&&(si?ii.push({resume:r}):r())}});e(function(){w.on("populate").fire(w._createTransaction(yt,ui,st));w.on("error").fire(new g)});this.transaction=function(n,t,i){function s(t,e){var s=null,c,a,h;try{if(f)throw f;s=w._createTransaction(n,o,st,u);c=o.map(function(n){return s.tables[n]});c.push(s);h=0;r.newPSD(function(){r.PSD.trans=s;s.scopeFunc=i;u&&(s.idbtrans=u.idbtrans,s._promise=p(s._promise,function(n){return function(t,i,u){function f(n){return function(t){var i;return r._rootExec(function(){i=n(t);r._tickFinalize(function(){--h==0&&s.active&&(s.active=!1,s.on.complete.fire())})}),i}}return++h,n.call(this,t,function(n,t,r){return i(f(n),f(t),r)},u)}}));s.complete(function(){t(a)});s.error(function(n){s.idbtrans&&(s.idbtrans.onerror=ht);try{s.abort()}catch(i){}u&&(u.active=!1,u.on.error.fire(n));var t=e(n);u||t||w.on.error.fire(n)});r._rootExec(function(){a=i.apply(s,c)})});(!s.idbtrans||u&&h===0)&&s._nop()}catch(l){s&&s.idbtrans&&(s.idbtrans.onerror=ht);s&&s.abort();u&&u.on.error.fire(l);b(function(){e(l)||w.on("error").fire(l)})}}var u,e;t=[].slice.call(arguments,1,arguments.length-1);i=arguments[arguments.length-1];u=r.PSD&&r.PSD.trans;u&&u.db===w&&n.indexOf("!")===-1||(u=null);e=n.indexOf("?")!==-1;n=n.replace("!","").replace("?","");var h=Array.isArray(t[0])?t.reduce(function(n,t){return n.concat(t)}):t,f=null,o=h.map(function(n){return typeof n=="string"?n:(n instanceof ei||(f=f||new yi("Invalid type. Arguments following mode must be instances of Table or String")),n.name)});return n=="r"||n==ti?n=ti:n=="rw"||n==yt?n=yt:f=new g("Invalid transaction mode: "+n),u&&(f||(u&&u.mode===ti&&n===yt&&(e?u=null:f=f||new g("Cannot enter a sub-transaction with READWRITE mode when parent transaction is READONLY")),u&&o.forEach(function(n){u.tables.hasOwnProperty(n)||(e?u=null:f=f||new g("Table "+n+" not included in parent transaction. Parent Transaction function: "+u.scopeFunc.toString()))}))),u?u._promise(n,s,"lock"):w._whenReady(s)};this.table=function(n){if(!hi&&!ni.hasOwnProperty(n))throw new g("Table does not exist");return ni[n]};s(ei.prototype,function(){function n(){throw new g("Current Transaction is READONLY");}return{_trans:function(n,t,i){return this._tpf(n,[this.name],t,i)},_idbstore:function(n,t,i){var r=this;return this._tpf(n,[this.name],function(n,i,u){t(n,i,u.idbtrans.objectStore(r.name),u)},i)},get:function(n,t){var i=this;return e(function(){t(i.schema.instanceTemplate)}),this._idbstore(ti,function(t,r,u){var f=u.get(n);f.onerror=o(r,["getting",n,"from",i.name]);f.onsuccess=function(){t(i.hook.reading.fire(f.result))}}).then(t)},where:function(n){return new ci(this,n)},count:function(n){return this.toCollection().count(n)},offset:function(n){return this.toCollection().offset(n)},limit:function(n){return this.toCollection().limit(n)},reverse:function(){return this.toCollection().reverse()},filter:function(n){return this.toCollection().and(n)},each:function(n){var t=this;return e(function(){n(t.schema.instanceTemplate)}),this._idbstore(ti,function(i,r,u){var f=u.openCursor();f.onerror=o(r,["calling","Table.each()","on",t.name]);pi(f,null,n,i,r,t.hook.reading.fire)})},toArray:function(n){var t=this;return e(function(){n([t.schema.instanceTemplate])}),this._idbstore(ti,function(n,i,r){var u=[],f=r.openCursor();f.onerror=o(i,["calling","Table.toArray()","on",t.name]);pi(f,null,function(n){u.push(n)},function(){n(u)},i,t.hook.reading.fire)}).then(n)},orderBy:function(n){return new this._collClass(new ci(this,n))},toCollection:function(){return new this._collClass(new ci(this))},mapToClass:function(n,t){var i,r;return this.schema.mappedClass=n,i=Object.create(n.prototype),this.schema.primKey.keyPath&&(h(i,this.schema.primKey.keyPath,this.schema.primKey.auto?0:""),ot(n.prototype,this.schema.primKey.keyPath)),t&&it(i,t),this.schema.instanceTemplate=i,r=Object.setPrototypeOf?function(t){return t?(Object.setPrototypeOf(t,n.prototype),t):t}:function(t){var r,i;if(!t)return t;r=Object.create(n.prototype);for(i in t)t.hasOwnProperty(i)&&(r[i]=t[i]);return r},this.schema.readHook&&this.hook.reading.unsubscribe(this.schema.readHook),this.schema.readHook=r,this.hook("reading",r),n},defineClass:function(n){return this.mapToClass(u.defineClass(n),n)},add:n,put:n,"delete":n,clear:n,update:n}});y(tr).from(ei).extend(function(){return{add:function(n,t){var u=this,r=this.hook.creating.fire;return this._idbstore(yt,function(e,s,l,a){var v={},w,y,p;r!==f&&(w=t||(l.keyPath?c(n,l.keyPath):i),y=r.call(v,w,n,a),w===i&&y!==i&&(l.keyPath?h(n,l.keyPath,y):t=y));p=t?l.add(n,t):l.add(n);p.onerror=o(function(n){if(v.onerror)v.onerror(n);return s(n)},["adding",n,"into",u.name]);p.onsuccess=function(t){var i=l.keyPath;if(i&&h(n,i,t.target.result),v.onsuccess)v.onsuccess(t.target.result);e(p.result)}})},put:function(n,t){var r=this,u=this.hook.creating.fire,e=this.hook.updating.fire;return u!==f||e!==f?this._trans(yt,function(u,f,e){var o=t||r.schema.primKey.keyPath&&c(n,r.schema.primKey.keyPath);o===i?e.tables[r.name].add(n).then(u,f):(e._lock(),n=l(n),e.tables[r.name].where(":id").equals(o).modify(function(){this.value=n}).then(function(i){return i===0?e.tables[r.name].add(n,t):o}).finally(function(){e._unlock()}).then(u,f))}):this._idbstore(yt,function(i,u,f){var e=t?f.put(n,t):f.put(n);e.onerror=o(u,["putting",n,"into",r.name]);e.onsuccess=function(t){var r=f.keyPath;r&&h(n,r,t.target.result);i(e.result)}})},"delete":function(n){return this.hook.deleting.subscribers.length?this.where(":id").equals(n).delete():this._idbstore(yt,function(t,i,r){var u=r.delete(n);u.onerror=o(i,["deleting",n,"from",r.name]);u.onsuccess=function(){t(u.result)}})},clear:function(){return this.hook.deleting.subscribers.length?this.toCollection().delete():this._idbstore(yt,function(n,t,i){var r=i.clear();r.onerror=o(t,["clearing",i.name]);r.onsuccess=function(){n(r.result)}})},update:function(n,t){if(typeof t!="object"||Array.isArray(t))throw new g("db.update(keyOrObject, modifications). modifications must be an object.");if(typeof n!="object"||Array.isArray(n))return this.where(":id").equals(n).modify(t);Object.keys(t).forEach(function(i){h(n,i,t[i])});var u=c(n,this.schema.primKey.keyPath);return u===i&&r.reject(new g("Object does not contain its primary key")),this.where(":id").equals(u).modify(t)}}});s(ir.prototype,{_lock:function(){return++this._reculock,this._reculock===1&&r.PSD&&(r.PSD.lockOwnerFor=this),this},_unlock:function(){if(--this._reculock==0)for(r.PSD&&(r.PSD.lockOwnerFor=null);this._blockedFuncs.length>0&&!this._locked();){var n=this._blockedFuncs.shift();try{n()}catch(t){}}return this},_locked:function(){return this._reculock&&(!r.PSD||r.PSD.lockOwnerFor!==this)},_nop:function(n){this.tables[this.storeNames[0]].get(0).then(n)},_promise:function(n,t,i){var f=this;return r.newPSD(function(){var e;return f._locked()?e=new r(function(r,u){f._blockedFuncs.push(function(){f._promise(n,t,i).then(r,u)})}):(e=f.active?new r(function(r,e){if(!f.idbtrans&&n){if(!et)throw fi?new g("Database not open. Following error in populate, ready or upgrade function made Dexie.open() fail: "+fi):new g("Database not open");var o=f.idbtrans=et.transaction(ft(f.storeNames),f.mode);o.onerror=function(n){f.on("error").fire(n&&n.target.error);n.preventDefault();f.abort()};o.onabort=function(n){f.active=!1;f.on("abort").fire(n)};o.oncomplete=function(n){f.active=!1;f.on("complete").fire(n)}}i&&f._lock();try{t(r,e,f)}catch(s){u.ignoreTransaction(function(){f.on("error").fire(s)});f.abort();e(s)}}):r.reject(gt(new g("Transaction is inactive. Original Scope Function Source: "+f.scopeFunc.toString()))),f.active&&i&&e.finally(function(){f._unlock()})),e.onuncatched=function(n){u.ignoreTransaction(function(){f.on("error").fire(n)});f.abort()},e})},complete:function(n){return this.on("complete",n)},error:function(n){return this.on("error",n)},abort:function(){if(this.idbtrans&&this.active)try{this.active=!1;this.idbtrans.abort();this.on.error.fire(new g("Transaction Aborted"))}catch(n){}},table:function(n){if(!this.tables.hasOwnProperty(n))throw new g("Table "+n+" not in transaction");return this.tables[n]}});s(ci.prototype,function(){function n(n,t){try{throw t;}catch(i){n._ctx.error=i}return n}function i(n){return Array.prototype.slice.call(n.length===1&&Array.isArray(n[0])?n[0]:n)}function r(n){return n==="next"?function(n){return n.toUpperCase()}:function(n){return n.toLowerCase()}}function u(n){return n==="next"?function(n){return n.toLowerCase()}:function(n){return n.toUpperCase()}}function f(n,t,i,r,u,f){for(var h,s=Math.min(n.length,r.length),o=-1,e=0;e<s;++e){if(h=t[e],h!==r[e])return u(n[e],i[e])<0?n.substr(0,e)+i[e]+i.substr(e+1):u(n[e],r[e])<0?n.substr(0,e)+r[e]+i.substr(e+1):o>=0?n.substr(0,o)+t[o]+i.substr(o+1):null;u(n[e],h)<0&&(o=e)}return s<r.length&&f==="next"?n+i.substr(n.length):s<n.length&&f==="prev"?n.substr(0,i.length):o<0?null:n.substr(0,o)+r[o]+i.substr(o+1)}function t(n,t,i){function a(n){s=r(n);e=u(n);h=n==="next"?wi:or;c=s(i);o=e(i);l=n}var s,e,h,c,o,l;a("next");n._ondirectionchange=function(n){a(n)};n._addAlgorithm(function(n,i,r){var u=n.key,s,a;return typeof u!="string"?!1:(s=e(u),t(s,o)?(i(function(){n.continue()}),!0):(a=f(u,s,c,o,h,l),a?i(function(){n.continue(a)}):i(r),!1))})}return{between:function(n,t,i,r){return(i=i!==!1,r=r===!0,n>t||n===t&&(i||r)&&!(i&&r))?new this._ctx.collClass(this,function(){return kt.only(n)}).limit(0):new this._ctx.collClass(this,function(){return kt.bound(n,t,!i,!r)})},equals:function(n){return new this._ctx.collClass(this,function(){return kt.only(n)})},above:function(n){return new this._ctx.collClass(this,function(){return kt.lowerBound(n,!0)})},aboveOrEqual:function(n){return new this._ctx.collClass(this,function(){return kt.lowerBound(n)})},below:function(n){return new this._ctx.collClass(this,function(){return kt.upperBound(n,!0)})},belowOrEqual:function(n){return new this._ctx.collClass(this,function(){return kt.upperBound(n)})},startsWith:function(t){return typeof t!="string"?n(new this._ctx.collClass(this),new yi("String expected")):this.between(t,t+String.fromCharCode(65535),!0,!0)},startsWithIgnoreCase:function(i){if(typeof i!="string")return n(new this._ctx.collClass(this),new yi("String expected"));if(i==="")return this.startsWith(i);var r=new this._ctx.collClass(this,function(){return kt.bound(i.toUpperCase(),i.toLowerCase()+String.fromCharCode(65535))});return t(r,function(n,t){return n.indexOf(t)===0},i),r._ondirectionchange=function(){n(r,new g("reverse() not supported with WhereClause.startsWithIgnoreCase()"))},r},equalsIgnoreCase:function(i){if(typeof i!="string")return n(new this._ctx.collClass(this),new yi("String expected"));var r=new this._ctx.collClass(this,function(){return kt.bound(i.toUpperCase(),i.toLowerCase())});return t(r,function(n,t){return n===t},i),r},anyOf:function(){var f=this._ctx,e=f.table.schema,o=f.index?e.idxByName[f.index]:e.primKey,s=o&&o.compound,n=i(arguments),t=s?sr(wi):wi,u,r;return(n.sort(t),n.length===0)?new this._ctx.collClass(this,function(){return kt.only("")}).limit(0):(u=new this._ctx.collClass(this,function(){return kt.bound(n[0],n[n.length-1])}),u._ondirectionchange=function(i){t=i==="next"?wi:or;s&&(t=sr(t));n.sort(t)},r=0,u._addAlgorithm(function(i,u,f){for(var e=i.key;t(e,n[r])>0;)if(++r,r===n.length)return u(f),!1;return t(e,n[r])===0?(u(function(){i.continue()}),!0):(u(function(){i.continue(n[r])}),!1)}),u)}}});s(li.prototype,function(){function t(n,t){n.filter=bi(n.filter,t)}function f(n,t){n.isMatch=bi(n.isMatch,t)}function r(n,t){if(n.isPrimKey)return t;var i=n.table.schema.idxByName[n.index];if(!i)throw new g("KeyPath "+n.index+" on object store "+t.name+" is not indexed");return n.isPrimKey?t:t.index(i.name)}function u(n,t){return r(n,t)[n.op](n.range||null,n.dir+n.unique)}function i(n,t,i,r,f){n.or?function(){function e(){++c==2&&i()}function h(n,i,u){if(!o||o(i,u,e,r)){var f=i.primaryKey.toString();s.hasOwnProperty(f)||(s[f]=!0,t(n,i,u))}}var o=n.filter,s={},l=n.table.schema.primKey.keyPath,c=0;n.or._iterate(h,e,r,f);pi(u(n,f),n.algorithm,h,e,r,n.table.hook.reading.fire)}():pi(u(n,f),bi(n.algorithm,n.filter),t,i,r,n.table.hook.reading.fire)}function n(n){return n.table.schema.instanceTemplate}return{_read:function(n,t){var i=this._ctx;return i.error?i.table._trans(null,function(n,t){t(i.error)}):i.table._idbstore(ti,n).then(t)},_write:function(n){var t=this._ctx;return t.error?t.table._trans(null,function(n,i){i(t.error)}):t.table._idbstore(yt,n,"locked")},_addAlgorithm:function(n){var t=this._ctx;t.algorithm=bi(t.algorithm,n)},_iterate:function(n,t,r,u){return i(this._ctx,n,t,r,u)},each:function(t){var r=this._ctx;return e(function(){t(n(r))}),this._read(function(n,u,f){i(r,t,n,u,f)})},count:function(n){var f,t,u;return e(function(){n(0)}),f=this,t=this._ctx,t.filter||t.algorithm||t.or?(u=0,this._read(function(n,r,f){i(t,function(){return++u,!1},function(){n(u)},r,f)},n)):this._read(function(n,i,u){var e=r(t,u),s=t.range?e.count(t.range):e.count();s.onerror=o(i,["calling","count()","on",f.name]);s.onsuccess=function(i){n(Math.min(i.target.result,Math.max(0,t.limit-t.offset)))}},n)},sortBy:function(t,i){function u(n,t){return t?u(n[r[t]],t-1):n[h]}function c(n,t){var i=u(n,o),r=u(t,o);return i<r?-f:i>r?f:0}var s=this._ctx,f;e(function(){i([n(s)])});var r=t.split(".").reverse(),h=r[0],o=r.length-1;return f=this._ctx.dir==="next"?1:-1,this.toArray(function(n){return n.sort(c)}).then(i)},toArray:function(t){var r=this._ctx;return e(function(){t([n(r)])}),this._read(function(n,t,u){var f=[];i(r,function(n){f.push(n)},function(){n(f)},t,u)},t)},offset:function(n){var i=this._ctx;return n<=0?this:(i.offset+=n,i.or||i.algorithm||i.filter?t(i,function(){return--n<0}):t(i,function(t,i){return n===0?!0:n===1?(--n,!1):(i(function(){t.advance(n);n=0}),!1)}),this)},limit:function(n){return this._ctx.limit=Math.min(this._ctx.limit,n),t(this._ctx,function(t,i,r){return--n<=0&&i(r),n>=0}),this},until:function(i,r){var u=this._ctx;return e(function(){i(n(u))}),t(this._ctx,function(n,t,u){return i(n.value)?(t(u),r):!0}),this},first:function(t){var i=this;return e(function(){t(n(i._ctx))}),this.limit(1).toArray(function(n){return n[0]}).then(t)},last:function(n){return this.reverse().first(n)},and:function(i){var r=this;return e(function(){i(n(r._ctx))}),t(this._ctx,function(n){return i(n.value)}),f(this._ctx,i),this},or:function(n){return new ci(this._ctx.table,n,this)},reverse:function(){return this._ctx.dir=this._ctx.dir==="prev"?"next":"prev",this._ondirectionchange&&this._ondirectionchange(this._ctx.dir),this},desc:function(){return this.reverse()},eachKey:function(t){var i=this,r=this._ctx;return e(function(){t(n(i._ctx)[i._ctx.index])}),r.isPrimKey||(r.op="openKeyCursor"),this.each(function(n,i){t(i.key,i)})},eachUniqueKey:function(n){return this._ctx.unique="unique",this.eachKey(n)},keys:function(t){var u,i,r;return e(function(){t([n(i)[u._ctx.index]])}),u=this,i=this._ctx,i.isPrimKey||(i.op="openKeyCursor"),r=[],this.each(function(n,t){r.push(t.key)}).then(function(){return r}).then(t)},uniqueKeys:function(n){return this._ctx.unique="unique",this.keys(n)},firstKey:function(n){var t=this;return this.limit(1).keys(function(n){return n[0]}).then(n)},lastKey:function(n){return this.reverse().firstKey(n)},distinct:function(){var n={};return t(this._ctx,function(t){var i=t.primaryKey.toString(),r=n.hasOwnProperty(i);return n[i]=!0,!r}),this}}});y(rr).from(li).extend({modify:function(n){var a=this,t=this._ctx,r=t.table.hook,i=r.updating.fire,u=r.deleting.fire;return e(function(){typeof n=="function"&&n.call({value:t.table.schema.instanceTemplate},t.table.schema.instanceTemplate)}),this._write(function(r,e,v,y){function st(n,i){var r,u,f;if(et=i.primaryKey,r={primKey:i.primaryKey,value:n},w.call(r,n)!==!1)u=!r.hasOwnProperty("value"),f=u?i.delete():i.update(r.value),++ut,f.onerror=o(function(n){if(p.push(n),nt.push(r.primKey),r.onerror)r.onerror(n);return it(),!0},u?["deleting",n,"from",t.table.name]:["modifying",n,"on",t.table.name]),f.onsuccess=function(){if(r.onsuccess)r.onsuccess(r.value);++b;it()};else if(r.onsuccess)r.onsuccess(r.value)}function ot(n){return n&&(p.push(n),nt.push(et)),e(new d("Error modifying one or more objects",p,b,nt))}function it(){ft&&b+p.length===ut&&(p.length>0?ot():r(b))}var w,k,rt,g;typeof n=="function"?w=i===f&&u===f?n:function(t){var f=l(t),e,r;if(n.call(this,t)===!1)return!1;this.hasOwnProperty("value")?(e=dt(f,this.value),r=i.call(this,e,this.primKey,f,y),r&&(t=this.value,Object.keys(r).forEach(function(n){h(t,n,r[n])}))):u.call(this,this.primKey,t,y)}:i===f?(k=Object.keys(n),rt=k.length,w=function(t){for(var i,u,f=!1,r=0;r<rt;++r)i=k[r],u=n[i],c(t,i)!==u&&(h(t,i,u),f=!0);return f}):(g=n,n=tt(g),w=function(t){var u=!1,r=i.call(this,n,this.primKey,l(t),y);return r&&s(n,r),Object.keys(n).forEach(function(i){var r=n[i];c(t,i)!==r&&(h(t,i,r),u=!0)}),r&&(n=tt(g)),u});var ut=0,b=0,ft=!1,p=[],nt=[],et=null;a._iterate(st,function(){ft=!0;it()},ot,v)})},"delete":function(){return this.modify(function(){delete this.value})}});s(this,{Collection:li,Table:ei,Transaction:ir,Version:di,WhereClause:ci,WriteableCollection:rr,WriteableTable:tr});cr();hr.forEach(function(n){n(w)})}function f(){}function nt(n){return n}function lt(n,t){return n===nt?t:function(i){return t(n(i))}}function w(n,t){return function(){n.apply(this,arguments);t.apply(this,arguments)}}function at(n,t){return n===f?t:function(){var f=n.apply(this,arguments),r,u,e;return f!==i&&(arguments[0]=f),r=this.onsuccess,u=this.onerror,delete this.onsuccess,delete this.onerror,e=t.apply(this,arguments),r&&(this.onsuccess=this.onsuccess?w(r,this.onsuccess):r),u&&(this.onerror=this.onerror?w(u,this.onerror):u),e!==i?e:f}}function vt(n,t){return n===f?t:function(){var r=n.apply(this,arguments),f,e,u;return r!==i&&s(arguments[0],r),f=this.onsuccess,e=this.onerror,delete this.onsuccess,delete this.onerror,u=t.apply(this,arguments),f&&(this.onsuccess=this.onsuccess?w(f,this.onsuccess):f),e&&(this.onerror=this.onerror?w(e,this.onerror):e),r===i?u===i?i:u:u===i?r:s(r,u)}}function yt(n,t){return n===f?t:function(){return n.apply(this,arguments)===!1?!1:t.apply(this,arguments)}}function pt(n,t){return n===f?t:function(){return t.apply(this,arguments)===!1?!1:n.apply(this,arguments)}}function wt(n,t){return n===f?t:function(){n.apply(this,arguments);t.apply(this,arguments)}}function bt(n,t){return n===f?t:function(){var i=n.apply(this,arguments),r,u;return i&&typeof i.then=="function"?(r=this,u=arguments,i.then(function(){return t.apply(r,u)})):t.apply(this,arguments)}}function v(t){function i(n,t,i){if(Array.isArray(n))return c(n);if(typeof n=="object")return h(n);t||(t=yt);i||(i=f);var r={subscribers:[],fire:i,subscribe:function(n){r.subscribers.push(n);r.fire=t(r.fire,n)},unsubscribe:function(n){r.subscribers=r.subscribers.filter(function(t){return t!==n});r.fire=r.subscribers.reduce(t,i)}};return u[n]=e[n]=r,r}function h(t){Object.keys(t).forEach(function(r){var f=t[r],u;if(Array.isArray(f))i(r,t[r][0],t[r][1]);else if(f==="asap")u=i(r,null,function(){var t=arguments;u.subscribers.forEach(function(i){b(function(){i.apply(n,t)})})}),u.subscribe=function(n){u.subscribers.indexOf(n)===-1&&u.subscribers.push(n)},u.unsubscribe=function(n){var t=u.subscribers.indexOf(n);t!==-1&&u.subscribers.splice(t,1)};else throw new Error("Invalid event config");})}function c(n){function r(){if(t)return!1;t=!0}var t=!1;n.forEach(function(n){i(n).subscribe(r)})}var o=arguments,u={},e=function(n,i){if(i){var f=[].slice.call(arguments,1),r=u[n];return r.subscribe.apply(r,f),t}if(typeof n=="string")return u[n]},r,s;for(e.addEventType=i,r=1,s=o.length;r<s;++r)i(o[r]);return e}function kt(n){if(!n)throw new Error("Assertion failed");}function b(t){n.setImmediate?setImmediate(t):setTimeout(t,0)}function et(n){var t=setTimeout(n,1e3);clearTimeout(t)}function k(n,t,i){return function(){var u=r.PSD;r.PSD=i;try{n.apply(this,arguments)}catch(f){t(f)}finally{r.PSD=u}}}function c(n,t){var f,r,o,s,u,e;if(n.hasOwnProperty(t))return n[t];if(!t)return n;if(typeof t!="string"){for(f=[],r=0,o=t.length;r<o;++r)s=c(n,t[r]),f.push(s);return f}return(u=t.indexOf("."),u!==-1)?(e=n[t.substr(0,u)],e===i?i:c(e,t.substr(u+1))):i}function h(n,t,r){var u,c,e,f,s,o;if(n&&t!==i)if(typeof t!="string"&&"length"in t)for(kt(typeof r!="string"&&"length"in r),u=0,c=t.length;u<c;++u)h(n,t[u],r[u]);else e=t.indexOf("."),e!==-1?(f=t.substr(0,e),s=t.substr(e+1),s===""?r===i?delete n[f]:n[f]=r:(o=n[f],o||(o=n[f]={}),h(o,s,r))):r===i?delete n[t]:n[t]=r}function ot(n,t){h(n,t,i)}function tt(n){var i={};for(var t in n)n.hasOwnProperty(t)&&(i[t]=n[t]);return i}function l(n){var t,i,u,r;if(!n||typeof n!="object")return n;if(Array.isArray(n))for(t=[],i=0,u=n.length;i<u;++i)t.push(l(n[i]));else if(n instanceof Date)t=new Date,t.setTime(n.getTime());else{t=n.constructor?Object.create(n.constructor.prototype):{};for(r in n)n.hasOwnProperty(r)&&(t[r]=l(n[r]))}return t}function dt(n,t){var u={};for(var r in n)n.hasOwnProperty(r)&&(t.hasOwnProperty(r)?n[r]!==t[r]&&JSON.stringify(n[r])!=JSON.stringify(t[r])&&(u[r]=t[r]):u[r]=i);for(r in t)t.hasOwnProperty(r)&&!n.hasOwnProperty(r)&&(u[r]=t[r]);return u}function st(n){if(typeof n=="function")return new n;if(Array.isArray(n))return[st(n[0])];if(n&&typeof n=="object"){var t={};return it(t,n),t}return n}function it(n,t){Object.keys(t).forEach(function(i){var r=st(t[i]);n[i]=r})}function o(n,t){return function(i){var r=i&&i.target.error||new Error,u;return t&&(u=" occurred when "+t.map(function(n){switch(typeof n){case"function":return n();case"string":return n;default:return JSON.stringify(n)}}).join(" "),r.name?r.toString=function(){return r.name+u+(r.message?". "+r.message:"")}:r=r+u),n(r),i&&(i.stopPropagation&&i.stopPropagation(),i.preventDefault&&i.preventDefault()),!1}}function gt(n){try{throw n;}catch(t){return t}}function ht(n){n.preventDefault()}function rt(n){var t,i=u.dependencies.localStorage;if(!i)return n([]);try{t=JSON.parse(i.getItem("Dexie.DatabaseNames")||"[]")}catch(r){t=[]}n(t)&&i.setItem("Dexie.DatabaseNames",JSON.stringify(t))}function a(n,t,i,r,u,f,e){this.name=n;this.keyPath=t;this.unique=i;this.multi=r;this.auto=u;this.compound=f;this.dotted=e;var o=typeof t=="string"?t:t&&"["+[].join.call(t,"+")+"]";this.src=(i?"&":"")+(r?"*":"")+(u?"++":"")+o}function ut(n,t,i,r){this.name=n;this.primKey=t||new a;this.indexes=i||[new a];this.instanceTemplate=r;this.mappedClass=null;this.idxByName=i.reduce(function(n,t){return n[t.name]=t,n},{})}function d(n,t,i,r){this.name="ModifyError";this.failures=t;this.failedKeys=r;this.successCount=i;this.message=t.join("\n")}function ft(n){return n.length===1?n[0]:n}function ct(){var n=u.dependencies.indexedDB,t=n&&(n.getDatabaseNames||n.webkitGetDatabaseNames);return t&&t.bind(n)}var r=function(){function y(n){u.push([n,a.call(arguments,1)])}function p(){var r=u,t,f,i;for(u=[],t=0,f=r.length;t<f;++t)i=r[t],i[0].apply(n,i[1])}function t(n){if(typeof this!="object")throw new TypeError("Promises must be constructed via new");if(typeof n!="function")throw new TypeError("not a function");this._state=null;this._value=null;this._deferreds=[];this._catched=!1;var r=this,u=!0;this._PSD=t.PSD;try{k(this,n,function(n){u?i(c,r,n):c(r,n)},function(n){return u?(i(s,r,n),!1):s(r,n)})}finally{u=!1}}function o(n,f){var s,o,l,a,b,c;if(n._state===null){n._deferreds.push(f);return}if(s=n._state?f.onFulfilled:f.onRejected,s===null)return(n._state?f.resolve:f.reject)(n._value);l=r;r=!1;i=y;try{a=t.PSD;t.PSD=n._PSD;o=s(n._value);n._state||o&&typeof o.then=="function"&&o._state===!1||w(n);f.resolve(o)}catch(v){if(b=f.reject(v),!b&&n.onuncatched)try{n.onuncatched(v)}catch(v){}}finally{if(t.PSD=a,l){do{while(u.length>0)p();if(c=e.pop(),c)try{c()}catch(v){}}while(e.length>0||u.length>0);i=h;r=!0}}}function d(n){var f=r,t;r=!1;i=y;try{n()}finally{if(f){do{while(u.length>0)p();if(t=e.pop(),t)try{t()}catch(o){}}while(e.length>0||u.length>0);i=h;r=!0}}}function w(n){n._catched=!0;n._parent&&w(n._parent)}function c(n,i){var r=t.PSD;t.PSD=n._PSD;try{if(i===n)throw new TypeError("A promise cannot be resolved with itself.");if(i&&(typeof i=="object"||typeof i=="function")&&typeof i.then=="function"){k(n,function(n,t){i.then(n,t)},function(t){c(n,t)},function(t){s(n,t)});return}n._state=!0;n._value=i;b.call(n)}catch(u){s(u)}finally{t.PSD=r}}function s(n,i){var r=t.PSD;if(t.PSD=n._PSD,n._state=!1,n._value=i,b.call(n),!n._catched)try{if(n.onuncatched)n.onuncatched(n._value);t.on.error.fire(n._value)}catch(u){}return t.PSD=r,n._catched}function b(){for(var n=0,t=this._deferreds.length;n<t;n++)o(this,this._deferreds[n]);this._deferreds=[]}function l(n,t,i,r){this.onFulfilled=typeof n=="function"?n:null;this.onRejected=typeof t=="function"?t:null;this.resolve=i;this.reject=r}function k(n,t,i,r){var u=!1;try{t(function(n){u||(u=!0,i(n))},function(t){return u?n._catched:(u=!0,r(t))})}catch(f){return u?void 0:r(f)}}var a=[].slice,h=typeof setImmediate=="undefined"?function(t){var i=arguments;setTimeout(function(){t.apply(n,a.call(i,1))},0)}:setImmediate,i=h,r=!0,u=[],e=[];return t.on=v(null,"error"),t.all=function(){var n=Array.prototype.slice.call(arguments.length===1&&Array.isArray(arguments[0])?arguments[0]:arguments);return new t(function(t,i){function f(r,e){try{if(e&&(typeof e=="object"||typeof e=="function")){var o=e.then;if(typeof o=="function"){o.call(e,function(n){f(r,n)},i);return}}n[r]=e;--u==0&&t(n)}catch(s){i(s)}}var u,r;if(n.length===0)return t([]);for(u=n.length,r=0;r<n.length;r++)f(r,n[r])})},t.prototype.then=function(n,r){var f=this,u=new t(function(t,u){f._state===null?o(f,new l(n,r,t,u)):i(o,f,new l(n,r,t,u))});return u._PSD=this._PSD,u.onuncatched=this.onuncatched,u._parent=this,u},t.prototype._then=function(n,t){o(this,new l(n,t,f,f))},t.prototype["catch"]=function(n){if(arguments.length===1)return this.then(null,n);var i=arguments[0],r=arguments[1];return typeof i=="function"?this.then(null,function(n){return n instanceof i?r(n):t.reject(n)}):this.then(null,function(n){return n&&n.name===i?r(n):t.reject(n)})},t.prototype["finally"]=function(n){return this.then(function(t){return n(),t},function(i){return n(),t.reject(i)})},t.prototype.onuncatched=null,t.resolve=function(n){var i=new t(function(){});return i._state=!0,i._value=n,i},t.reject=function(n){var i=new t(function(){});return i._state=!1,i._value=n,i},t.race=function(n){return new t(function(t,i){n.map(function(n){n.then(t,i)})})},t.PSD=null,t.newPSD=function(n){var i=t.PSD;t.PSD=i?Object.create(i):{};try{return n()}finally{t.PSD=i}},t._rootExec=d,t._tickFinalize=function(n){if(r)throw new Error("Not in a virtual tick");e.push(n)},t}(),e=function(){},g;y(d).from(Error);u.delete=function(n){var t=new u(n),i=t.delete();return i.onblocked=function(n){t.on("blocked",n);return this},i};u.getDatabaseNames=function(n){return new r(function(n,t){var r=ct(),i;r?(i=r(),i.onsuccess=function(t){n([].slice.call(t.target.result,0))},i.onerror=o(t)):rt(function(t){return n(t),!1})}).then(n)};u.defineClass=function(n){function t(n){n&&s(this,n)}return it(t.prototype,n),t};u.ignoreTransaction=function(n){return r.newPSD(function(){return r.PSD.trans=null,n()})};u.spawn=function(){return n.console&&console.warn("Dexie.spawn() is deprecated. Use Dexie.ignoreTransaction() instead."),u.ignoreTransaction.apply(this,arguments)};u.vip=function(n){return r.newPSD(function(){return r.PSD.letThrough=!0,n()})};Object.defineProperty(u,"currentTransaction",{get:function(){return r.PSD&&r.PSD.trans||null}});u.Promise=r;u.derive=y;u.extend=s;u.override=p;u.events=v;u.getByKeyPath=c;u.setByKeyPath=h;u.delByKeyPath=ot;u.shallowClone=tt;u.deepClone=l;u.addons=[];u.fakeAutoComplete=e;u.asap=b;u.ModifyError=d;u.MultiModifyError=d;u.IndexSpec=a;u.TableSchema=ut;g=n.idbModules&&n.idbModules.shimIndexedDB?n.idbModules:{};u.dependencies={indexedDB:g.shimIndexedDB||n.indexedDB||n.mozIndexedDB||n.webkitIndexedDB||n.msIndexedDB,IDBKeyRange:g.IDBKeyRange||n.IDBKeyRange||n.webkitIDBKeyRange,IDBTransaction:g.IDBTransaction||n.IDBTransaction||n.webkitIDBTransaction,Error:n.Error||String,SyntaxError:n.SyntaxError||String,TypeError:n.TypeError||String,DOMError:n.DOMError||String,localStorage:(typeof chrome!="undefined"&&chrome!==null?chrome.storage:void 0)!=null?null:n.localStorage};u.version=1.1;t("Dexie",u);et(function(){e=et})}).apply(null,typeof define=="function"&&define.amd?[self||window,function(n,t){define(n,function(){return t})}]:typeof global!="undefined"&&typeof module!="undefined"&&module.exports?[global,function(n,t){module.exports=t}]:[self||window,function(n,t){(self||window)[n]=t}]);
//# sourceMappingURL=Dexie.min.js.map
