private static byte[] DecodingByteArrayHelper(SafeBerHandle berElement, char fmt, ref int error) { error = 0; IntPtr result = IntPtr.Zero; berval binaryValue = new berval(); byte[] byteArray = null; // can't use SafeBerval here as CLR creates a SafeBerval which points to a different memory location, but when doing memory // deallocation, wldap has special check. So have to use IntPtr directly here. error = BerPal.ScanNextPtr(berElement, new string(fmt, 1), ref result); try { if (!BerPal.IsBerDecodeError(error)) { if (result != IntPtr.Zero) { Marshal.PtrToStructure(result, binaryValue); byteArray = new byte[binaryValue.bv_len]; Marshal.Copy(binaryValue.bv_val, byteArray, 0, binaryValue.bv_len); } } else { Debug.WriteLine("ber_scanf for format character 'O' failed"); } } finally { if (result != IntPtr.Zero) { BerPal.FreeBerval(result); } } return(byteArray); }
public static byte[] Encode(string format, params object[] value) { if (format == null) { throw new ArgumentNullException(nameof(format)); } // no need to turn on invalid encoding detection as we just do string->byte[] conversion. UTF8Encoding utf8Encoder = new UTF8Encoding(); byte[] encodingResult = null; // value is allowed to be null in certain scenario, so if it is null, just set it to empty array. if (value == null) { value = Array.Empty <object>(); } Debug.WriteLine("Begin encoding\n"); // allocate the berelement SafeBerHandle berElement = new SafeBerHandle(); int valueCount = 0; int error = 0; for (int formatCount = 0; formatCount < format.Length; formatCount++) { char fmt = format[formatCount]; if (fmt == '{' || fmt == '}' || fmt == '[' || fmt == ']' || fmt == 'n') { // no argument needed error = BerPal.PrintEmptyArgument(berElement, new string(fmt, 1)); } else if (fmt == 't' || fmt == 'i' || fmt == 'e') { if (valueCount >= value.Length) { // we don't have enough argument for the format string Debug.WriteLine("value argument is not valid, valueCount >= value.Length\n"); throw new ArgumentException(SR.BerConverterNotMatch); } if (!(value[valueCount] is int)) { // argument is wrong Debug.WriteLine("type should be int\n"); throw new ArgumentException(SR.BerConverterNotMatch); } // one int argument error = BerPal.PrintInt(berElement, new string(fmt, 1), (int)value[valueCount]); // increase the value count valueCount++; } else if (fmt == 'b') { if (valueCount >= value.Length) { // we don't have enough argument for the format string Debug.WriteLine("value argument is not valid, valueCount >= value.Length\n"); throw new ArgumentException(SR.BerConverterNotMatch); } if (!(value[valueCount] is bool)) { // argument is wrong Debug.WriteLine("type should be boolean\n"); throw new ArgumentException(SR.BerConverterNotMatch); } // one int argument error = BerPal.PrintInt(berElement, new string(fmt, 1), (bool)value[valueCount] ? 1 : 0); // increase the value count valueCount++; } else if (fmt == 's') { if (valueCount >= value.Length) { // we don't have enough argument for the format string Debug.WriteLine("value argument is not valid, valueCount >= value.Length\n"); throw new ArgumentException(SR.BerConverterNotMatch); } if (value[valueCount] != null && !(value[valueCount] is string)) { // argument is wrong Debug.WriteLine("type should be string, but receiving value has type of "); Debug.WriteLine(value[valueCount].GetType()); throw new ArgumentException(SR.BerConverterNotMatch); } // one string argument byte[] tempValue = null; if (value[valueCount] != null) { tempValue = utf8Encoder.GetBytes((string)value[valueCount]); } error = EncodingByteArrayHelper(berElement, tempValue, 'o'); // increase the value count valueCount++; } else if (fmt == 'o' || fmt == 'X') { // we need to have one arguments if (valueCount >= value.Length) { // we don't have enough argument for the format string Debug.WriteLine("value argument is not valid, valueCount >= value.Length\n"); throw new ArgumentException(SR.BerConverterNotMatch); } if (value[valueCount] != null && !(value[valueCount] is byte[])) { // argument is wrong Debug.WriteLine("type should be byte[], but receiving value has type of "); Debug.WriteLine(value[valueCount].GetType()); throw new ArgumentException(SR.BerConverterNotMatch); } byte[] tempValue = (byte[])value[valueCount]; error = EncodingByteArrayHelper(berElement, tempValue, fmt); valueCount++; } else if (fmt == 'v') { // we need to have one arguments if (valueCount >= value.Length) { // we don't have enough argument for the format string Debug.WriteLine("value argument is not valid, valueCount >= value.Length\n"); throw new ArgumentException(SR.BerConverterNotMatch); } if (value[valueCount] != null && !(value[valueCount] is string[])) { // argument is wrong Debug.WriteLine("type should be string[], but receiving value has type of "); Debug.WriteLine(value[valueCount].GetType()); throw new ArgumentException(SR.BerConverterNotMatch); } string[] stringValues = (string[])value[valueCount]; byte[][] tempValues = null; if (stringValues != null) { tempValues = new byte[stringValues.Length][]; for (int i = 0; i < stringValues.Length; i++) { string s = stringValues[i]; if (s == null) { tempValues[i] = null; } else { tempValues[i] = utf8Encoder.GetBytes(s); } } } error = EncodingMultiByteArrayHelper(berElement, tempValues, 'V'); valueCount++; } else if (fmt == 'V') { // we need to have one arguments if (valueCount >= value.Length) { // we don't have enough argument for the format string Debug.WriteLine("value argument is not valid, valueCount >= value.Length\n"); throw new ArgumentException(SR.BerConverterNotMatch); } if (value[valueCount] != null && !(value[valueCount] is byte[][])) { // argument is wrong Debug.WriteLine("type should be byte[][], but receiving value has type of "); Debug.WriteLine(value[valueCount].GetType()); throw new ArgumentException(SR.BerConverterNotMatch); } byte[][] tempValue = (byte[][])value[valueCount]; error = EncodingMultiByteArrayHelper(berElement, tempValue, fmt); valueCount++; } else { Debug.WriteLine("Format string contains undefined character: "); Debug.WriteLine(new string(fmt, 1)); throw new ArgumentException(SR.BerConverterUndefineChar); } // process the return value if (error == -1) { Debug.WriteLine("ber_printf failed\n"); throw new BerConversionException(); } } // get the binary value back berval binaryValue = new berval(); IntPtr flattenptr = IntPtr.Zero; try { // can't use SafeBerval here as CLR creates a SafeBerval which points to a different memory location, but when doing memory // deallocation, wldap has special check. So have to use IntPtr directly here. error = BerPal.FlattenBerElement(berElement, ref flattenptr); if (error == -1) { Debug.WriteLine("ber_flatten failed\n"); throw new BerConversionException(); } if (flattenptr != IntPtr.Zero) { Marshal.PtrToStructure(flattenptr, binaryValue); } if (binaryValue == null || binaryValue.bv_len == 0) { encodingResult = Array.Empty <byte>(); } else { encodingResult = new byte[binaryValue.bv_len]; Marshal.Copy(binaryValue.bv_val, encodingResult, 0, binaryValue.bv_len); } } finally { if (flattenptr != IntPtr.Zero) { BerPal.FreeBerval(flattenptr); } } return(encodingResult); }