/// <summary> /// Check whether a Contact contains properties for the paths of MAPI Groups. /// </summary> /// <param name="contact">The contact to check for MAPI-groupness</param> /// <returns> /// Returns true if the contact would have values for either MemberIds or /// MemberNameEmailPairs if the contact was viewed as a MAPI group. False /// otherwise. /// </returns> /// <remarks> /// This does not check that the properties are valid, just that the property /// paths of MAPI Group properties exist in the given contact. /// </remarks> public static bool HasMapiProperties(Contact contact) { Verify.IsNotNull(contact, "contact"); using (Stream stm = contact.GetBinaryProperty(_ContactIdKey, null)) { if (null != stm) { return true; } } using (Stream stm = contact.GetBinaryProperty(_NameEmailKey, null)) { if (null != stm) { return true; } } return false; }
/// <summary> /// Get a view over the contact that accesses Windows Contacts group properties. /// </summary> /// <param name="contact">The contact to create the group-view over.</param> /// <remarks> /// This does not create an actively updated view over the contact's properties. /// Changes to the contact in memory or on disk are not reflected by this instance. /// </remarks> public MapiGroupView(Contact contact) : base(contact) { var encoding = new UnicodeEncoding(); _contactIds = new List<string>(); _oneOffs = new List<Person>(); using (Stream stm = contact.GetBinaryProperty(_ContactIdKey, null)) { if (null != stm) { using (var binreader = new BinaryReader(stm)) { try { int idCount = binreader.ReadInt32(); for (int i = 0; i < idCount; ++i) { int cb = binreader.ReadInt32(); byte[] id = binreader.ReadBytes(cb); // Seeing a double-null termination. Trim it... Assert.AreEqual<byte>(0, id[id.Length - 1]); Assert.AreEqual<byte>(0, id[id.Length - 2]); string mapiId = encoding.GetString(id, 0, id.Length - 2); if (!mapiId.StartsWith(_MapiPrefix, StringComparison.Ordinal)) { throw new FormatException("Group contains invalid member data. ContactIds don't match the expected format."); } _contactIds.Add(mapiId.Substring(_MapiPrefix.Length)); } } catch (EndOfStreamException) { throw new FormatException("Group contains invalid member data. The data stream ended prematurely."); } if (stm.Position != stm.Length) { throw new FormatException("Group contains invalid member data. More data was found than was specified in the header."); } } } } using (Stream stm = contact.GetBinaryProperty(_NameEmailKey, null)) { if (null != stm) { using (var binreader = new BinaryReader(stm)) { try { int pairCount = binreader.ReadInt32(); for (int i = 0; i < pairCount; ++i) { int cb = binreader.ReadInt32(); byte[] id = binreader.ReadBytes(cb); // Seeing a double-null termination. Trim it... Assert.AreEqual<byte>(0, id[id.Length - 1]); Assert.AreEqual<byte>(0, id[id.Length - 2]); string mapiId = encoding.GetString(id, _OneOffPrefixJunk, id.Length - 2 - _OneOffPrefixJunk); // Should contain three elements: Name, e-mail type, e-mail address. string[] tokens = mapiId.Split(new[] {'\0'}, StringSplitOptions.None); if (3 != tokens.Length) { throw new FormatException("Group contains invalid one-off member data."); } // Throw away the e-mail address type. _oneOffs.Add(new Person(tokens[0], null, tokens[2], null)); } } catch (EndOfStreamException) { throw new FormatException("Group contains invalid member data. The data stream ended prematurely."); } if (stm.Position != stm.Length) { throw new FormatException("Group contains invalid member data. More data was found than was specified in the header."); } } } } }
private static Photo _CreatePhoto(Contact contact, string arrayNode) { Assert.IsTrue(arrayNode.StartsWith(PropertyNames.PhotoCollection + PropertyNames.PhotoArrayNode, StringComparison.Ordinal)); Uri url = null; string urlString = contact.GetStringProperty(arrayNode + PropertyNames.Url); if (!string.IsNullOrEmpty(urlString)) { if (!Uri.TryCreate(urlString, UriKind.RelativeOrAbsolute, out url)) { url = new Uri(_stockInvalidUrl); } } var photoType = new StringBuilder(); Stream photoStream = contact.GetBinaryProperty(arrayNode + PropertyNames.Value, photoType); return new Photo(photoStream, null == photoStream ? null : photoType.ToString(), url); }
private static Certificate _CreateCertificate(Contact contact, string arrayNode) { Assert.IsTrue(arrayNode.StartsWith(PropertyNames.CertificateCollection + PropertyNames.CertificateArrayNode, StringComparison.Ordinal)); var sbType = new StringBuilder(); Stream value = contact.GetBinaryProperty(arrayNode + PropertyNames.Value, sbType); var sbThumbPrintType = new StringBuilder(); Stream thumbprint = contact.GetBinaryProperty(arrayNode + PropertyNames.Thumbprint, sbThumbPrintType); return new Certificate(value, sbType.ToString(), thumbprint, sbThumbPrintType.ToString()); }