// // Property.cs // // Author: Kees van Spelde // // Copyright (c) 2013-2018 Magic-Sessions. (www.magic-sessions.com) // // 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. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // using System; using System.IO; using System.Text; using MsgReader.Exceptions; // ReSharper disable InconsistentNaming namespace MsgReader.Outlook { /// /// Pointer to a variable of type SPropValue that specifies the property value array describing the properties /// for the recipient. The rgPropVals member can be NULL. /// public class Property { #region Properties /// /// The id of the property /// internal ushort Id { get; } /// /// Returns the Property as a readable string without the streamprefix and type /// /// public string ShortName => Id.ToString("X4"); /// /// Returns the Property as a readable string /// /// public string Name => MapiTags.SubStorageStreamPrefix + Id.ToString("X4") + ((ushort)Type).ToString("X4"); /// /// The /// internal PropertyType Type { get; } /// /// Returns true when this property is part of a multivalue property /// internal bool MultiValue { get; } /// /// The property data /// internal byte[] Data { get; } /// /// Returns as an integer when is set to /// , /// or /// /// Raised when the is not or /// internal int ToInt { get { switch (Type) { case PropertyType.PT_SHORT: return BitConverter.ToInt16(Data, 0); case PropertyType.PT_LONG: return BitConverter.ToInt32(Data, 0); default: throw new MRInvalidProperty("Type is not PT_SHORT or PT_LONG"); } } } /// /// Returns as a single when is set to /// /// /// Raised when the is not internal float ToSingle { get { switch (Type) { case PropertyType.PT_FLOAT: return BitConverter.ToSingle(Data, 0); default: throw new MRInvalidProperty("Type is not PT_FLOAT"); } } } /// /// Returns as a single when is set to /// /// /// Raised when the is not internal double ToDouble { get { switch (Type) { case PropertyType.PT_DOUBLE: return BitConverter.ToDouble(Data, 0); default: throw new MRInvalidProperty("Type is not PT_DOUBLE"); } } } /// /// Returns as a decimal when is set to /// /// /// Raised when the is not internal decimal ToDecimal { get { switch (Type) { case PropertyType.PT_FLOAT: return ByteArrayToDecimal(Data, 0); default: throw new MRInvalidProperty("Type is not PT_FLOAT"); } } } /// /// Returns as a datetime when is set to /// /// or /// /// Raised when the is not set to or /// internal DateTime ToDateTime { get { switch (Type) { case PropertyType.PT_APPTIME: var oaDate = BitConverter.ToDouble(Data, 0); return DateTime.FromOADate(oaDate); case PropertyType.PT_SYSTIME: var fileTime = BitConverter.ToInt64(Data, 0); return DateTime.FromFileTime(fileTime); default: throw new MRInvalidProperty("Type is not PT_APPTIME or PT_SYSTIME"); } } } /// /// Returns as a boolean when is set to /// /// Raised when the is not set to internal bool ToBool { get { switch (Type) { case PropertyType.PT_BOOLEAN: return BitConverter.ToBoolean(Data, 0); default: throw new MRInvalidProperty("Type is not PT_BOOLEAN"); } } } /// /// Returns as a boolean when is set to /// /// /// Raised when the is not set to internal long ToLong { get { switch (Type) { case PropertyType.PT_LONG: case PropertyType.PT_LONGLONG: return BitConverter.ToInt64(Data, 0); default: throw new MRInvalidProperty("Type is not PtypInteger64"); } } } /// /// Returns as a string when is set to /// or /// /// Raised when the is not set to /// or public new string ToString { get { switch (Type) { case PropertyType.PT_UNICODE: case PropertyType.PT_STRING8: var encoding = Type == PropertyType.PT_STRING8 ? Encoding.Default : Encoding.Unicode; using (var memoryStream = new MemoryStream(Data)) using (var streamReader = new StreamReader(memoryStream, encoding)) { var streamContent = streamReader.ReadToEnd(); return streamContent.TrimEnd('\0'); } default: var encoding2 = Type == PropertyType.PT_STRING8 ? Encoding.Default : Encoding.Unicode; using (var memoryStream = new MemoryStream(Data)) using (var streamReader = new StreamReader(memoryStream, encoding2)) { var streamContent = streamReader.ReadToEnd(); return streamContent.TrimEnd('\0'); } //throw new MRInvalidProperty("Type is not PT_UNICODE or PT_STRING8"); } } } /// /// Returns as a byte[] when is set to /// /// /// Raised when the is not set to public byte[] ToBinary { get { switch (Type) { case PropertyType.PT_BINARY: return Data; default: throw new MRInvalidProperty("Type is not PT_BINARY"); } } } /// /// Returns as a Guid when is set to /// /// /// Raised when the is not set to public Guid ToGuid { get { switch (Type) { case PropertyType.PT_CLSID: return new Guid(Data); default: throw new MRInvalidProperty("Type is not PT_CLSID"); } } } #endregion #region ByteArrayToDecimal /// /// Converts a byte array to a decimal /// /// The byte array /// The offset to start reading /// private static decimal ByteArrayToDecimal(byte[] source, int offset) { var i1 = BitConverter.ToInt32(source, offset); var i2 = BitConverter.ToInt32(source, offset + 4); var i3 = BitConverter.ToInt32(source, offset + 8); var i4 = BitConverter.ToInt32(source, offset + 12); return new decimal(new[] { i1, i2, i3, i4 }); } #endregion #region Constructor /// /// Creates this object and sets all its propertues /// /// The id of the property /// The /// The property data /// Set to true to indicate that this property is part of a /// multivalue property public Property(ushort id, PropertyType type, byte[] data, bool multiValue = false) { Id = id; Type = type; Data = data; MultiValue = multiValue; } #endregion } }