sdfsdfs
This commit is contained in:
634
node_modules/asn1.js/lib/asn1/base/node.js
generated
vendored
Normal file
634
node_modules/asn1.js/lib/asn1/base/node.js
generated
vendored
Normal file
@@ -0,0 +1,634 @@
|
||||
var Reporter = require('../base').Reporter;
|
||||
var EncoderBuffer = require('../base').EncoderBuffer;
|
||||
var DecoderBuffer = require('../base').DecoderBuffer;
|
||||
var assert = require('minimalistic-assert');
|
||||
|
||||
// Supported tags
|
||||
var tags = [
|
||||
'seq', 'seqof', 'set', 'setof', 'objid', 'bool',
|
||||
'gentime', 'utctime', 'null_', 'enum', 'int', 'objDesc',
|
||||
'bitstr', 'bmpstr', 'charstr', 'genstr', 'graphstr', 'ia5str', 'iso646str',
|
||||
'numstr', 'octstr', 'printstr', 't61str', 'unistr', 'utf8str', 'videostr'
|
||||
];
|
||||
|
||||
// Public methods list
|
||||
var methods = [
|
||||
'key', 'obj', 'use', 'optional', 'explicit', 'implicit', 'def', 'choice',
|
||||
'any', 'contains'
|
||||
].concat(tags);
|
||||
|
||||
// Overrided methods list
|
||||
var overrided = [
|
||||
'_peekTag', '_decodeTag', '_use',
|
||||
'_decodeStr', '_decodeObjid', '_decodeTime',
|
||||
'_decodeNull', '_decodeInt', '_decodeBool', '_decodeList',
|
||||
|
||||
'_encodeComposite', '_encodeStr', '_encodeObjid', '_encodeTime',
|
||||
'_encodeNull', '_encodeInt', '_encodeBool'
|
||||
];
|
||||
|
||||
function Node(enc, parent) {
|
||||
var state = {};
|
||||
this._baseState = state;
|
||||
|
||||
state.enc = enc;
|
||||
|
||||
state.parent = parent || null;
|
||||
state.children = null;
|
||||
|
||||
// State
|
||||
state.tag = null;
|
||||
state.args = null;
|
||||
state.reverseArgs = null;
|
||||
state.choice = null;
|
||||
state.optional = false;
|
||||
state.any = false;
|
||||
state.obj = false;
|
||||
state.use = null;
|
||||
state.useDecoder = null;
|
||||
state.key = null;
|
||||
state['default'] = null;
|
||||
state.explicit = null;
|
||||
state.implicit = null;
|
||||
state.contains = null;
|
||||
|
||||
// Should create new instance on each method
|
||||
if (!state.parent) {
|
||||
state.children = [];
|
||||
this._wrap();
|
||||
}
|
||||
}
|
||||
module.exports = Node;
|
||||
|
||||
var stateProps = [
|
||||
'enc', 'parent', 'children', 'tag', 'args', 'reverseArgs', 'choice',
|
||||
'optional', 'any', 'obj', 'use', 'alteredUse', 'key', 'default', 'explicit',
|
||||
'implicit', 'contains'
|
||||
];
|
||||
|
||||
Node.prototype.clone = function clone() {
|
||||
var state = this._baseState;
|
||||
var cstate = {};
|
||||
stateProps.forEach(function(prop) {
|
||||
cstate[prop] = state[prop];
|
||||
});
|
||||
var res = new this.constructor(cstate.parent);
|
||||
res._baseState = cstate;
|
||||
return res;
|
||||
};
|
||||
|
||||
Node.prototype._wrap = function wrap() {
|
||||
var state = this._baseState;
|
||||
methods.forEach(function(method) {
|
||||
this[method] = function _wrappedMethod() {
|
||||
var clone = new this.constructor(this);
|
||||
state.children.push(clone);
|
||||
return clone[method].apply(clone, arguments);
|
||||
};
|
||||
}, this);
|
||||
};
|
||||
|
||||
Node.prototype._init = function init(body) {
|
||||
var state = this._baseState;
|
||||
|
||||
assert(state.parent === null);
|
||||
body.call(this);
|
||||
|
||||
// Filter children
|
||||
state.children = state.children.filter(function(child) {
|
||||
return child._baseState.parent === this;
|
||||
}, this);
|
||||
assert.equal(state.children.length, 1, 'Root node can have only one child');
|
||||
};
|
||||
|
||||
Node.prototype._useArgs = function useArgs(args) {
|
||||
var state = this._baseState;
|
||||
|
||||
// Filter children and args
|
||||
var children = args.filter(function(arg) {
|
||||
return arg instanceof this.constructor;
|
||||
}, this);
|
||||
args = args.filter(function(arg) {
|
||||
return !(arg instanceof this.constructor);
|
||||
}, this);
|
||||
|
||||
if (children.length !== 0) {
|
||||
assert(state.children === null);
|
||||
state.children = children;
|
||||
|
||||
// Replace parent to maintain backward link
|
||||
children.forEach(function(child) {
|
||||
child._baseState.parent = this;
|
||||
}, this);
|
||||
}
|
||||
if (args.length !== 0) {
|
||||
assert(state.args === null);
|
||||
state.args = args;
|
||||
state.reverseArgs = args.map(function(arg) {
|
||||
if (typeof arg !== 'object' || arg.constructor !== Object)
|
||||
return arg;
|
||||
|
||||
var res = {};
|
||||
Object.keys(arg).forEach(function(key) {
|
||||
if (key == (key | 0))
|
||||
key |= 0;
|
||||
var value = arg[key];
|
||||
res[value] = key;
|
||||
});
|
||||
return res;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Overrided methods
|
||||
//
|
||||
|
||||
overrided.forEach(function(method) {
|
||||
Node.prototype[method] = function _overrided() {
|
||||
var state = this._baseState;
|
||||
throw new Error(method + ' not implemented for encoding: ' + state.enc);
|
||||
};
|
||||
});
|
||||
|
||||
//
|
||||
// Public methods
|
||||
//
|
||||
|
||||
tags.forEach(function(tag) {
|
||||
Node.prototype[tag] = function _tagMethod() {
|
||||
var state = this._baseState;
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
|
||||
assert(state.tag === null);
|
||||
state.tag = tag;
|
||||
|
||||
this._useArgs(args);
|
||||
|
||||
return this;
|
||||
};
|
||||
});
|
||||
|
||||
Node.prototype.use = function use(item) {
|
||||
assert(item);
|
||||
var state = this._baseState;
|
||||
|
||||
assert(state.use === null);
|
||||
state.use = item;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
Node.prototype.optional = function optional() {
|
||||
var state = this._baseState;
|
||||
|
||||
state.optional = true;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
Node.prototype.def = function def(val) {
|
||||
var state = this._baseState;
|
||||
|
||||
assert(state['default'] === null);
|
||||
state['default'] = val;
|
||||
state.optional = true;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
Node.prototype.explicit = function explicit(num) {
|
||||
var state = this._baseState;
|
||||
|
||||
assert(state.explicit === null && state.implicit === null);
|
||||
state.explicit = num;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
Node.prototype.implicit = function implicit(num) {
|
||||
var state = this._baseState;
|
||||
|
||||
assert(state.explicit === null && state.implicit === null);
|
||||
state.implicit = num;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
Node.prototype.obj = function obj() {
|
||||
var state = this._baseState;
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
|
||||
state.obj = true;
|
||||
|
||||
if (args.length !== 0)
|
||||
this._useArgs(args);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
Node.prototype.key = function key(newKey) {
|
||||
var state = this._baseState;
|
||||
|
||||
assert(state.key === null);
|
||||
state.key = newKey;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
Node.prototype.any = function any() {
|
||||
var state = this._baseState;
|
||||
|
||||
state.any = true;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
Node.prototype.choice = function choice(obj) {
|
||||
var state = this._baseState;
|
||||
|
||||
assert(state.choice === null);
|
||||
state.choice = obj;
|
||||
this._useArgs(Object.keys(obj).map(function(key) {
|
||||
return obj[key];
|
||||
}));
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
Node.prototype.contains = function contains(item) {
|
||||
var state = this._baseState;
|
||||
|
||||
assert(state.use === null);
|
||||
state.contains = item;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
//
|
||||
// Decoding
|
||||
//
|
||||
|
||||
Node.prototype._decode = function decode(input, options) {
|
||||
var state = this._baseState;
|
||||
|
||||
// Decode root node
|
||||
if (state.parent === null)
|
||||
return input.wrapResult(state.children[0]._decode(input, options));
|
||||
|
||||
var result = state['default'];
|
||||
var present = true;
|
||||
|
||||
var prevKey = null;
|
||||
if (state.key !== null)
|
||||
prevKey = input.enterKey(state.key);
|
||||
|
||||
// Check if tag is there
|
||||
if (state.optional) {
|
||||
var tag = null;
|
||||
if (state.explicit !== null)
|
||||
tag = state.explicit;
|
||||
else if (state.implicit !== null)
|
||||
tag = state.implicit;
|
||||
else if (state.tag !== null)
|
||||
tag = state.tag;
|
||||
|
||||
if (tag === null && !state.any) {
|
||||
// Trial and Error
|
||||
var save = input.save();
|
||||
try {
|
||||
if (state.choice === null)
|
||||
this._decodeGeneric(state.tag, input, options);
|
||||
else
|
||||
this._decodeChoice(input, options);
|
||||
present = true;
|
||||
} catch (e) {
|
||||
present = false;
|
||||
}
|
||||
input.restore(save);
|
||||
} else {
|
||||
present = this._peekTag(input, tag, state.any);
|
||||
|
||||
if (input.isError(present))
|
||||
return present;
|
||||
}
|
||||
}
|
||||
|
||||
// Push object on stack
|
||||
var prevObj;
|
||||
if (state.obj && present)
|
||||
prevObj = input.enterObject();
|
||||
|
||||
if (present) {
|
||||
// Unwrap explicit values
|
||||
if (state.explicit !== null) {
|
||||
var explicit = this._decodeTag(input, state.explicit);
|
||||
if (input.isError(explicit))
|
||||
return explicit;
|
||||
input = explicit;
|
||||
}
|
||||
|
||||
var start = input.offset;
|
||||
|
||||
// Unwrap implicit and normal values
|
||||
if (state.use === null && state.choice === null) {
|
||||
if (state.any)
|
||||
var save = input.save();
|
||||
var body = this._decodeTag(
|
||||
input,
|
||||
state.implicit !== null ? state.implicit : state.tag,
|
||||
state.any
|
||||
);
|
||||
if (input.isError(body))
|
||||
return body;
|
||||
|
||||
if (state.any)
|
||||
result = input.raw(save);
|
||||
else
|
||||
input = body;
|
||||
}
|
||||
|
||||
if (options && options.track && state.tag !== null)
|
||||
options.track(input.path(), start, input.length, 'tagged');
|
||||
|
||||
if (options && options.track && state.tag !== null)
|
||||
options.track(input.path(), input.offset, input.length, 'content');
|
||||
|
||||
// Select proper method for tag
|
||||
if (state.any)
|
||||
result = result;
|
||||
else if (state.choice === null)
|
||||
result = this._decodeGeneric(state.tag, input, options);
|
||||
else
|
||||
result = this._decodeChoice(input, options);
|
||||
|
||||
if (input.isError(result))
|
||||
return result;
|
||||
|
||||
// Decode children
|
||||
if (!state.any && state.choice === null && state.children !== null) {
|
||||
state.children.forEach(function decodeChildren(child) {
|
||||
// NOTE: We are ignoring errors here, to let parser continue with other
|
||||
// parts of encoded data
|
||||
child._decode(input, options);
|
||||
});
|
||||
}
|
||||
|
||||
// Decode contained/encoded by schema, only in bit or octet strings
|
||||
if (state.contains && (state.tag === 'octstr' || state.tag === 'bitstr')) {
|
||||
var data = new DecoderBuffer(result);
|
||||
result = this._getUse(state.contains, input._reporterState.obj)
|
||||
._decode(data, options);
|
||||
}
|
||||
}
|
||||
|
||||
// Pop object
|
||||
if (state.obj && present)
|
||||
result = input.leaveObject(prevObj);
|
||||
|
||||
// Set key
|
||||
if (state.key !== null && (result !== null || present === true))
|
||||
input.leaveKey(prevKey, state.key, result);
|
||||
else if (prevKey !== null)
|
||||
input.exitKey(prevKey);
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
Node.prototype._decodeGeneric = function decodeGeneric(tag, input, options) {
|
||||
var state = this._baseState;
|
||||
|
||||
if (tag === 'seq' || tag === 'set')
|
||||
return null;
|
||||
if (tag === 'seqof' || tag === 'setof')
|
||||
return this._decodeList(input, tag, state.args[0], options);
|
||||
else if (/str$/.test(tag))
|
||||
return this._decodeStr(input, tag, options);
|
||||
else if (tag === 'objid' && state.args)
|
||||
return this._decodeObjid(input, state.args[0], state.args[1], options);
|
||||
else if (tag === 'objid')
|
||||
return this._decodeObjid(input, null, null, options);
|
||||
else if (tag === 'gentime' || tag === 'utctime')
|
||||
return this._decodeTime(input, tag, options);
|
||||
else if (tag === 'null_')
|
||||
return this._decodeNull(input, options);
|
||||
else if (tag === 'bool')
|
||||
return this._decodeBool(input, options);
|
||||
else if (tag === 'objDesc')
|
||||
return this._decodeStr(input, tag, options);
|
||||
else if (tag === 'int' || tag === 'enum')
|
||||
return this._decodeInt(input, state.args && state.args[0], options);
|
||||
|
||||
if (state.use !== null) {
|
||||
return this._getUse(state.use, input._reporterState.obj)
|
||||
._decode(input, options);
|
||||
} else {
|
||||
return input.error('unknown tag: ' + tag);
|
||||
}
|
||||
};
|
||||
|
||||
Node.prototype._getUse = function _getUse(entity, obj) {
|
||||
|
||||
var state = this._baseState;
|
||||
// Create altered use decoder if implicit is set
|
||||
state.useDecoder = this._use(entity, obj);
|
||||
assert(state.useDecoder._baseState.parent === null);
|
||||
state.useDecoder = state.useDecoder._baseState.children[0];
|
||||
if (state.implicit !== state.useDecoder._baseState.implicit) {
|
||||
state.useDecoder = state.useDecoder.clone();
|
||||
state.useDecoder._baseState.implicit = state.implicit;
|
||||
}
|
||||
return state.useDecoder;
|
||||
};
|
||||
|
||||
Node.prototype._decodeChoice = function decodeChoice(input, options) {
|
||||
var state = this._baseState;
|
||||
var result = null;
|
||||
var match = false;
|
||||
|
||||
Object.keys(state.choice).some(function(key) {
|
||||
var save = input.save();
|
||||
var node = state.choice[key];
|
||||
try {
|
||||
var value = node._decode(input, options);
|
||||
if (input.isError(value))
|
||||
return false;
|
||||
|
||||
result = { type: key, value: value };
|
||||
match = true;
|
||||
} catch (e) {
|
||||
input.restore(save);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}, this);
|
||||
|
||||
if (!match)
|
||||
return input.error('Choice not matched');
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
//
|
||||
// Encoding
|
||||
//
|
||||
|
||||
Node.prototype._createEncoderBuffer = function createEncoderBuffer(data) {
|
||||
return new EncoderBuffer(data, this.reporter);
|
||||
};
|
||||
|
||||
Node.prototype._encode = function encode(data, reporter, parent) {
|
||||
var state = this._baseState;
|
||||
if (state['default'] !== null && state['default'] === data)
|
||||
return;
|
||||
|
||||
var result = this._encodeValue(data, reporter, parent);
|
||||
if (result === undefined)
|
||||
return;
|
||||
|
||||
if (this._skipDefault(result, reporter, parent))
|
||||
return;
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
Node.prototype._encodeValue = function encode(data, reporter, parent) {
|
||||
var state = this._baseState;
|
||||
|
||||
// Decode root node
|
||||
if (state.parent === null)
|
||||
return state.children[0]._encode(data, reporter || new Reporter());
|
||||
|
||||
var result = null;
|
||||
|
||||
// Set reporter to share it with a child class
|
||||
this.reporter = reporter;
|
||||
|
||||
// Check if data is there
|
||||
if (state.optional && data === undefined) {
|
||||
if (state['default'] !== null)
|
||||
data = state['default']
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
// Encode children first
|
||||
var content = null;
|
||||
var primitive = false;
|
||||
if (state.any) {
|
||||
// Anything that was given is translated to buffer
|
||||
result = this._createEncoderBuffer(data);
|
||||
} else if (state.choice) {
|
||||
result = this._encodeChoice(data, reporter);
|
||||
} else if (state.contains) {
|
||||
content = this._getUse(state.contains, parent)._encode(data, reporter);
|
||||
primitive = true;
|
||||
} else if (state.children) {
|
||||
content = state.children.map(function(child) {
|
||||
if (child._baseState.tag === 'null_')
|
||||
return child._encode(null, reporter, data);
|
||||
|
||||
if (child._baseState.key === null)
|
||||
return reporter.error('Child should have a key');
|
||||
var prevKey = reporter.enterKey(child._baseState.key);
|
||||
|
||||
if (typeof data !== 'object')
|
||||
return reporter.error('Child expected, but input is not object');
|
||||
|
||||
var res = child._encode(data[child._baseState.key], reporter, data);
|
||||
reporter.leaveKey(prevKey);
|
||||
|
||||
return res;
|
||||
}, this).filter(function(child) {
|
||||
return child;
|
||||
});
|
||||
content = this._createEncoderBuffer(content);
|
||||
} else {
|
||||
if (state.tag === 'seqof' || state.tag === 'setof') {
|
||||
// TODO(indutny): this should be thrown on DSL level
|
||||
if (!(state.args && state.args.length === 1))
|
||||
return reporter.error('Too many args for : ' + state.tag);
|
||||
|
||||
if (!Array.isArray(data))
|
||||
return reporter.error('seqof/setof, but data is not Array');
|
||||
|
||||
var child = this.clone();
|
||||
child._baseState.implicit = null;
|
||||
content = this._createEncoderBuffer(data.map(function(item) {
|
||||
var state = this._baseState;
|
||||
|
||||
return this._getUse(state.args[0], data)._encode(item, reporter);
|
||||
}, child));
|
||||
} else if (state.use !== null) {
|
||||
result = this._getUse(state.use, parent)._encode(data, reporter);
|
||||
} else {
|
||||
content = this._encodePrimitive(state.tag, data);
|
||||
primitive = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Encode data itself
|
||||
var result;
|
||||
if (!state.any && state.choice === null) {
|
||||
var tag = state.implicit !== null ? state.implicit : state.tag;
|
||||
var cls = state.implicit === null ? 'universal' : 'context';
|
||||
|
||||
if (tag === null) {
|
||||
if (state.use === null)
|
||||
reporter.error('Tag could be omitted only for .use()');
|
||||
} else {
|
||||
if (state.use === null)
|
||||
result = this._encodeComposite(tag, primitive, cls, content);
|
||||
}
|
||||
}
|
||||
|
||||
// Wrap in explicit
|
||||
if (state.explicit !== null)
|
||||
result = this._encodeComposite(state.explicit, false, 'context', result);
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
Node.prototype._encodeChoice = function encodeChoice(data, reporter) {
|
||||
var state = this._baseState;
|
||||
|
||||
var node = state.choice[data.type];
|
||||
if (!node) {
|
||||
assert(
|
||||
false,
|
||||
data.type + ' not found in ' +
|
||||
JSON.stringify(Object.keys(state.choice)));
|
||||
}
|
||||
return node._encode(data.value, reporter);
|
||||
};
|
||||
|
||||
Node.prototype._encodePrimitive = function encodePrimitive(tag, data) {
|
||||
var state = this._baseState;
|
||||
|
||||
if (/str$/.test(tag))
|
||||
return this._encodeStr(data, tag);
|
||||
else if (tag === 'objid' && state.args)
|
||||
return this._encodeObjid(data, state.reverseArgs[0], state.args[1]);
|
||||
else if (tag === 'objid')
|
||||
return this._encodeObjid(data, null, null);
|
||||
else if (tag === 'gentime' || tag === 'utctime')
|
||||
return this._encodeTime(data, tag);
|
||||
else if (tag === 'null_')
|
||||
return this._encodeNull();
|
||||
else if (tag === 'int' || tag === 'enum')
|
||||
return this._encodeInt(data, state.args && state.reverseArgs[0]);
|
||||
else if (tag === 'bool')
|
||||
return this._encodeBool(data);
|
||||
else if (tag === 'objDesc')
|
||||
return this._encodeStr(data, tag);
|
||||
else
|
||||
throw new Error('Unsupported tag: ' + tag);
|
||||
};
|
||||
|
||||
Node.prototype._isNumstr = function isNumstr(str) {
|
||||
return /^[0-9 ]*$/.test(str);
|
||||
};
|
||||
|
||||
Node.prototype._isPrintstr = function isPrintstr(str) {
|
||||
return /^[A-Za-z0-9 '\(\)\+,\-\.\/:=\?]*$/.test(str);
|
||||
};
|
Reference in New Issue
Block a user