Home Reference Source

src/AttributeTypeAndValue.js

  1. import * as asn1js from "asn1js";
  2. import { getParametersValue, isEqualBuffer, clearProps } from "pvutils";
  3. import { stringPrep } from "./common.js";
  4. //**************************************************************************************
  5. /**
  6. * Class from RFC5280
  7. */
  8. export default class AttributeTypeAndValue
  9. {
  10. //**********************************************************************************
  11. /**
  12. * Constructor for AttributeTypeAndValue class
  13. * @param {Object} [parameters={}]
  14. * @property {Object} [schema] asn1js parsed value
  15. */
  16. constructor(parameters = {})
  17. {
  18. //region Internal properties of the object
  19. /**
  20. * @type {string}
  21. * @description type
  22. */
  23. this.type = getParametersValue(parameters, "type", AttributeTypeAndValue.defaultValues("type"));
  24. /**
  25. * @type {Object}
  26. * @description Value of the AttributeTypeAndValue class
  27. */
  28. this.value = getParametersValue(parameters, "value", AttributeTypeAndValue.defaultValues("value"));
  29. //endregion
  30.  
  31. //region If input argument array contains "schema" for this object
  32. if("schema" in parameters)
  33. this.fromSchema(parameters.schema);
  34. //endregion
  35. }
  36. //**********************************************************************************
  37. /**
  38. * Return default values for all class members
  39. * @param {string} memberName String name for a class member
  40. */
  41. static defaultValues(memberName)
  42. {
  43. switch(memberName)
  44. {
  45. case "type":
  46. return "";
  47. case "value":
  48. return {};
  49. default:
  50. throw new Error(`Invalid member name for AttributeTypeAndValue class: ${memberName}`);
  51. }
  52. }
  53. //**********************************************************************************
  54. /**
  55. * Return value of asn1js schema for current class
  56. * @param {Object} parameters Input parameters for the schema
  57. * @returns {Object} asn1js schema object
  58. */
  59. static schema(parameters = {})
  60. {
  61. //AttributeTypeAndValue ::= Sequence {
  62. // type AttributeType,
  63. // value AttributeValue }
  64. //
  65. //AttributeType ::= OBJECT IDENTIFIER
  66. //
  67. //AttributeValue ::= ANY -- DEFINED BY AttributeType
  68.  
  69. /**
  70. * @type {Object}
  71. * @property {string} [blockName] Name for entire block
  72. * @property {string} [type] Name for "type" element
  73. * @property {string} [value] Name for "value" element
  74. */
  75. const names = getParametersValue(parameters, "names", {});
  76.  
  77. return (new asn1js.Sequence({
  78. name: (names.blockName || ""),
  79. value: [
  80. new asn1js.ObjectIdentifier({ name: (names.type || "") }),
  81. new asn1js.Any({ name: (names.value || "") })
  82. ]
  83. }));
  84. }
  85. //**********************************************************************************
  86. /**
  87. * Convert parsed asn1js object into current class
  88. * @param {!Object} schema
  89. */
  90. fromSchema(schema)
  91. {
  92. //region Clear input data first
  93. clearProps(schema, [
  94. "type",
  95. "typeValue"
  96. ]);
  97. //endregion
  98. //region Check the schema is valid
  99. const asn1 = asn1js.compareSchema(schema,
  100. schema,
  101. AttributeTypeAndValue.schema({
  102. names: {
  103. type: "type",
  104. value: "typeValue"
  105. }
  106. })
  107. );
  108.  
  109. if(asn1.verified === false)
  110. throw new Error("Object's schema was not verified against input data for AttributeTypeAndValue");
  111. //endregion
  112.  
  113. //region Get internal properties from parsed schema
  114. this.type = asn1.result.type.valueBlock.toString();
  115. // noinspection JSUnresolvedVariable
  116. this.value = asn1.result.typeValue;
  117. //endregion
  118. }
  119. //**********************************************************************************
  120. /**
  121. * Convert current object to asn1js object and set correct values
  122. * @returns {Object} asn1js object
  123. */
  124. toSchema()
  125. {
  126. //region Construct and return new ASN.1 schema for this object
  127. return (new asn1js.Sequence({
  128. value: [
  129. new asn1js.ObjectIdentifier({ value: this.type }),
  130. this.value
  131. ]
  132. }));
  133. //endregion
  134. }
  135. //**********************************************************************************
  136. /**
  137. * Convertion for the class to JSON object
  138. * @returns {Object}
  139. */
  140. toJSON()
  141. {
  142. const _object = {
  143. type: this.type
  144. };
  145.  
  146. if(Object.keys(this.value).length !== 0)
  147. _object.value = this.value.toJSON();
  148. else
  149. _object.value = this.value;
  150.  
  151. return _object;
  152. }
  153. //**********************************************************************************
  154. /**
  155. * Compare two AttributeTypeAndValue values, or AttributeTypeAndValue with ArrayBuffer value
  156. * @param {(AttributeTypeAndValue|ArrayBuffer)} compareTo The value compare to current
  157. * @returns {boolean}
  158. */
  159. isEqual(compareTo)
  160. {
  161. if(compareTo instanceof AttributeTypeAndValue)
  162. {
  163. if(this.type !== compareTo.type)
  164. return false;
  165. // noinspection OverlyComplexBooleanExpressionJS
  166. if(((this.value instanceof asn1js.Utf8String) && (compareTo.value instanceof asn1js.Utf8String)) ||
  167. ((this.value instanceof asn1js.BmpString) && (compareTo.value instanceof asn1js.BmpString)) ||
  168. ((this.value instanceof asn1js.UniversalString) && (compareTo.value instanceof asn1js.UniversalString)) ||
  169. ((this.value instanceof asn1js.NumericString) && (compareTo.value instanceof asn1js.NumericString)) ||
  170. ((this.value instanceof asn1js.PrintableString) && (compareTo.value instanceof asn1js.PrintableString)) ||
  171. ((this.value instanceof asn1js.TeletexString) && (compareTo.value instanceof asn1js.TeletexString)) ||
  172. ((this.value instanceof asn1js.VideotexString) && (compareTo.value instanceof asn1js.VideotexString)) ||
  173. ((this.value instanceof asn1js.IA5String) && (compareTo.value instanceof asn1js.IA5String)) ||
  174. ((this.value instanceof asn1js.GraphicString) && (compareTo.value instanceof asn1js.GraphicString)) ||
  175. ((this.value instanceof asn1js.VisibleString) && (compareTo.value instanceof asn1js.VisibleString)) ||
  176. ((this.value instanceof asn1js.GeneralString) && (compareTo.value instanceof asn1js.GeneralString)) ||
  177. ((this.value instanceof asn1js.CharacterString) && (compareTo.value instanceof asn1js.CharacterString)))
  178. {
  179. const value1 = stringPrep(this.value.valueBlock.value);
  180. const value2 = stringPrep(compareTo.value.valueBlock.value);
  181. if(value1.localeCompare(value2) !== 0)
  182. return false;
  183. }
  184. else // Comparing as two ArrayBuffers
  185. {
  186. if(isEqualBuffer(this.value.valueBeforeDecode, compareTo.value.valueBeforeDecode) === false)
  187. return false;
  188. }
  189. return true;
  190. }
  191. if(compareTo instanceof ArrayBuffer)
  192. return isEqualBuffer(this.value.valueBeforeDecode, compareTo);
  193.  
  194. return false;
  195. }
  196. //**********************************************************************************
  197. }
  198. //**************************************************************************************