public static TlvObject Query(byte[] data, int tag) { /* * Search for the tag. */ TlvConstructed myTag = new TlvConstructed(); myTag.Value = data; return(myTag.Find(tag)); }
public static TlvObject Query(byte[] data, string path) { /* * Transform the path into its separate tags and validate them. */ List <int> myNumbers = new List <int>(); foreach (string t in path.Split('/')) { try { myNumbers.Add(Int32.Parse(t, NumberStyles.HexNumber, CultureInfo.InvariantCulture)); } catch { throw new ArgumentException(@"Error parsing the BER path", @"path"); } } TlvObject myTag = new TlvConstructed(); myTag.Value = data; /* * Search recursively for the tag. */ for (int i = 0; i < myNumbers.Count; i++) { myTag = ((TlvConstructed)myTag).Find(myNumbers[i]); if (null == myTag) { // The path wasn't found return(null); } } // Return what we found return(myTag); }
/// <summary> /// Finds the specified tag. /// </summary> /// <param name="tag">The tag.</param> /// <returns></returns> public TlvObject Find(int tag) { int myIndex = 0; TlvObject myTLV = null; while (myIndex < Value.Length) { /* * RETRIEVE THE TAG TYPE * The bit B6 of the leading byte of the tag field shall encode the tag type, * i.e. the type of the data object. * * B6=0 introduces a primitive data object * B6=1 introduces a constructed data object */ if ((Value[myIndex] & 0x20) == 0x20) { myTLV = new TlvConstructed(); } else { myTLV = new TlvPrimitive(); } /* * RETRIEVE THE TAG NUMBER * * If the bits B5-B1 of the leading byte are not all set to 1, then may they * shall encode an integer equal to the tag number which therefore lies in the * range from 0 to 30. Then the tag field consists of a single byte. * * Otherwise (B5-B1 set to 1 in the leading byte), the tag field shall * continue on one or more shubsequent bytes. * * The bit B8 of each subsequent byte shall be set to 1, unless it is the * last subsequent byte * The bits B7-B1 of the first subsequent byte shall not be all set to 0 * The bits B7-B1 of the first subsequent byte, folowed by the bits B7 to B1 * of each further subsequent byte, up to and including the bits B7-B1 of * the last subsequent byte, shall encode an integer equal to the tag * number (thus strictly positive). */ if (0x1F == (Value[myIndex] & 0x1F)) { // Set the first byte of the tag number myTLV.Number = Value[myIndex]; while (true) { // Move to the next byte myIndex++; // Shift the number over by 8 bits myTLV.Number <<= 8; // Assign the next value to the lower byte myTLV.Number |= Value[myIndex]; // If the MSB is clear then this is our last byte if ((Value[myIndex] & 0x80) == 0x00) { break; } } } else { // This is a low-tag number /* * NOTE: When documentation refers to the tag number it also * seems to include the class/type information so we won't trim * it out here. */ myTLV.Number = Value[myIndex]; } // Move to the next byte myIndex++; /* * LENGTH */ int myLength = 0; if (0x80 == (Value[myIndex] & 0x80)) { // This is a long length int myLengthBytes = Value[myIndex] & 0x7F; for (int i = 0; i < myLengthBytes; i++) { // Move to the next byte myIndex++; // Shift our length over by 8 bits myLength <<= 8; // Copy the value myLength |= Value[myIndex]; } } else { // This is a short length (msb is 0 here so we take the whole byte) myLength = Value[myIndex]; } // Move to the next byte myIndex++; // Is this the tag we're looking for? if (myTLV.Number == tag) { // Set our tag value myTLV.Value = new byte[myLength]; Array.Copy(Value, myIndex, myTLV.Value, 0, myLength); // Finished! return(myTLV); } else { // Move to the next tag myIndex += myLength; } } // Nothing was found return(null); }