/MSNPSHARP_DEV/MSNPSharp/NSMessageHandler.MSNP21.cs
http://msnp-sharp.googlecode.com/ · C# · 1927 lines · 1373 code · 384 blank · 170 comment · 317 complexity · 0724eb27bab0f61a6387a37595e18c21 MD5 · raw file
Large files are truncated click here to view the full file
- #region
- /*
- Copyright (c) 2002-2012, Bas Geertsema, Xih Solutions
- (http://www.xihsolutions.net), Thiago.Sayao, Pang Wu, Ethem Evlice, Andy Phan, Chang Liu.
- All rights reserved. http://code.google.com/p/msnp-sharp/
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
- * Neither the names of Bas Geertsema or Xih Solutions nor the names of its
- contributors may be used to endorse or promote products derived from this
- software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- THE POSSIBILITY OF SUCH DAMAGE.
- */
- #endregion
-
- using System;
- using System.IO;
- using System.Net;
- using System.Xml;
- using System.Web;
- using System.Text;
- using System.Drawing;
- using System.Diagnostics;
- using System.Collections.Generic;
-
- namespace MSNPSharp
- {
- using MSNPSharp.Core;
- using MSNPSharp.P2P;
- using MSNPSharp.Apps;
-
- partial class NSMessageHandler
- {
- #region Public Events
-
- /// <summary>
- /// Occurs when any contact changes status.
- /// </summary>
- public event EventHandler<ContactStatusChangedEventArgs> ContactStatusChanged;
- protected internal virtual void OnContactStatusChanged(ContactStatusChangedEventArgs e)
- {
- if (ContactStatusChanged != null)
- ContactStatusChanged(this, e);
- }
-
- /// <summary>
- /// Occurs when any contact goes from offline status to another status.
- /// </summary>
- public event EventHandler<ContactStatusChangedEventArgs> ContactOnline;
- protected internal virtual void OnContactOffline(ContactStatusChangedEventArgs e)
- {
- if (ContactOffline != null)
- ContactOffline(this, e);
-
- Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose,
- e.Contact.ToString() + " goes to " + e.NewStatus + " from " + e.OldStatus + (e.Via == null ? String.Empty : " via=" + e.Via.ToString()) + "\r\n", GetType().Name);
- }
-
- /// <summary>
- /// Occurs when any contact goes from any status to offline status.
- /// </summary>
- public event EventHandler<ContactStatusChangedEventArgs> ContactOffline;
- protected internal virtual void OnContactOnline(ContactStatusChangedEventArgs e)
- {
- if (ContactOnline != null)
- ContactOnline(this, e);
-
- Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose,
- e.Contact.ToString() + " goes to " + e.NewStatus + " from " + e.OldStatus + (e.Via == null ? String.Empty : " via=" + e.Via.ToString()) + "\r\n", GetType().Name);
- }
-
- /// <summary>
- /// Occurs when a user is typing.
- /// </summary>
- public event EventHandler<TypingArrivedEventArgs> TypingMessageReceived;
- protected virtual void OnTypingMessageReceived(TypingArrivedEventArgs e)
- {
- if (TypingMessageReceived != null)
- TypingMessageReceived(this, e);
-
- Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose,
- "TYPING: " + e.OriginalSender.ToString() + (e.Sender == e.OriginalSender ? String.Empty : ";by=" + e.Sender.ToString()));
- }
-
- /// <summary>
- /// Occurs when we receive a nudge message by a user.
- /// </summary>
- public event EventHandler<NudgeArrivedEventArgs> NudgeReceived;
- protected virtual void OnNudgeReceived(NudgeArrivedEventArgs e)
- {
- if (NudgeReceived != null)
- NudgeReceived(this, e);
-
- Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose,
- "NUDGE: " + e.OriginalSender + (e.Sender == e.OriginalSender ? String.Empty : ";by=" + e.Sender.ToString()));
- }
-
- /// <summary>
- /// Occurs when we receive a text message from a user.
- /// </summary>
- public event EventHandler<TextMessageArrivedEventArgs> TextMessageReceived;
- protected virtual void OnTextMessageReceived(TextMessageArrivedEventArgs e)
- {
- if (TextMessageReceived != null)
- TextMessageReceived(this, e);
-
- Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose,
- "TEXT MESSAGE: " + e.OriginalSender.ToString() + (e.Sender == e.OriginalSender ? String.Empty : ";by=" + e.Sender.ToString()) + "\r\n" + e.TextMessage.ToDebugString());
- }
-
-
- /// <summary>
- /// Fired when a contact sends a emoticon definition.
- /// </summary>
- public event EventHandler<EmoticonDefinitionEventArgs> EmoticonDefinitionReceived;
- protected virtual void OnEmoticonDefinitionReceived(EmoticonDefinitionEventArgs e)
- {
- if (EmoticonDefinitionReceived != null)
- EmoticonDefinitionReceived(this, e);
- }
-
- /// <summary>
- /// Fired when a contact sends a wink definition.
- /// </summary>
- public event EventHandler<WinkEventArgs> WinkDefinitionReceived;
- protected virtual void OnWinkDefinitionReceived(WinkEventArgs e)
- {
- if (WinkDefinitionReceived != null)
- WinkDefinitionReceived(this, e);
- }
-
- /// <summary>
- /// Occurs when a multiparty chat created remotely. Owner is joined automatically by the library.
- /// </summary>
- public event EventHandler<MultipartyCreatedEventArgs> MultipartyCreatedRemotely;
- protected virtual void OnMultipartyCreatedRemotely(MultipartyCreatedEventArgs e)
- {
- if (MultipartyCreatedRemotely != null)
- MultipartyCreatedRemotely(this, e);
- }
-
- /// <summary>
- /// Occurs when a contact joined the group chat.
- /// </summary>
- public event EventHandler<GroupChatParticipationEventArgs> JoinedGroupChat;
- protected virtual void OnJoinedGroupChat(GroupChatParticipationEventArgs e)
- {
- Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose,
- e.Contact + " joined group chat " + e.Via.ToString(), GetType().Name);
-
- if (JoinedGroupChat != null)
- JoinedGroupChat(this, e);
- }
-
- /// <summary>
- /// Occurs when a contact left the group chat.
- /// </summary>
- public event EventHandler<GroupChatParticipationEventArgs> LeftGroupChat;
- protected virtual void OnLeftGroupChat(GroupChatParticipationEventArgs e)
- {
- if (LeftGroupChat != null)
- LeftGroupChat(this, e);
-
- Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose,
- e.Contact + " left group chat " + e.Via.ToString(), GetType().Name);
- }
-
- /// <summary>
- /// Occurs after the user on another end point closed the IM window.
- /// </summary>
- public event EventHandler<CloseIMWindowEventArgs> RemoteEndPointCloseIMWindow;
- protected virtual void OnRemoteEndPointCloseIMWindow(CloseIMWindowEventArgs e)
- {
- if (RemoteEndPointCloseIMWindow != null)
- RemoteEndPointCloseIMWindow(this, e);
-
- if (e.Sender != null && e.SenderEndPoint != null)
- {
- string partiesString = string.Empty;
- foreach (Contact party in e.Parties)
- {
- partiesString += party.ToString() + "\r\n";
- }
-
- Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose,
- "User at End Point: " + e.SenderEndPoint.ToString() + " has closed the IM window.\r\n" +
- "Parties in the conversation: \r\n" +
- partiesString);
- }
- }
-
- #endregion
-
- #region MULTIPARTY
-
- #region CreateMultiparty
-
- internal class MultipartyObject
- {
- public event EventHandler<MultipartyCreatedEventArgs> MultipartyCreatedLocally;
-
- public int TransactionID;
- public List<string> InviteQueueHash;
- public Contact MultiParty;
-
- public MultipartyObject(int transId, List<string> inviteQueueHash, Contact multiParty,
- EventHandler<MultipartyCreatedEventArgs> onCreated)
- {
- TransactionID = transId;
- InviteQueueHash = new List<string>(inviteQueueHash);
- MultiParty = multiParty;
-
- if (onCreated != null)
- MultipartyCreatedLocally += onCreated;
- }
-
- internal void OnMultipartyCreatedLocally(object sender, MultipartyCreatedEventArgs e)
- {
- if (MultipartyCreatedLocally != null)
- {
- MultipartyCreatedLocally(sender, e);
-
- MultipartyCreatedLocally -= OnMultipartyCreatedLocally;
- }
- }
- };
-
- /// <summary>
- /// Creates a new multiparty (Group chat)
- /// </summary>
- /// <param name="inviteQueue">Contacts to be invited (don't add yourself)</param>
- /// <param name="onCreated">The handler to be executed when multiparty created (must be provided)</param>
- /// <exception cref="ArgumentNullException">inviteQueue or event handler is null</exception>
- /// <exception cref="InvalidOperationException">At least 2 contacts is required except you and contacts must support multiparty</exception>
- /// <returns>Transaction ID</returns>
- public int CreateMultiparty(List<Contact> inviteQueue, EventHandler<MultipartyCreatedEventArgs> onCreated)
- {
- if (inviteQueue == null || inviteQueue.Count == 0)
- throw new ArgumentNullException("inviteQueue");
-
- if (onCreated == null)
- throw new ArgumentNullException("onCreated");
-
- List<string> newQueue = new List<string>();
-
- foreach (Contact c in inviteQueue)
- {
- if (c != null &&
- !c.IsSibling(Owner) &&
- !newQueue.Contains(c.SiblingString) &&
- c.SupportsMultiparty)
- {
- newQueue.Add(c.SiblingString);
- }
- }
-
- if (newQueue.Count < 2)
- throw new InvalidOperationException("At least 2 contacts is required except you and contacts must support multiparty.");
-
-
- NSMessageProcessor nsmp = (NSMessageProcessor)MessageProcessor;
- int transId = nsmp.IncreaseTransactionID();
-
- lock (multiParties)
- multiParties[transId] = new MultipartyObject(transId, newQueue, null, onCreated);
-
- string to = ((int)IMAddressInfoType.TemporaryGroup).ToString() + ":" + Guid.Empty.ToString("D").ToLowerInvariant() + "@" + Contact.DefaultHostDomain;
- string from = ((int)Owner.ClientType).ToString() + ":" + Owner.Account;
- MultiMimeMessage mmMessage = new MultiMimeMessage(to, from);
- mmMessage.RoutingHeaders[MIMERoutingHeaders.From][MIMERoutingHeaders.EPID] = MachineGuid.ToString("B").ToLowerInvariant();
-
- mmMessage.ContentKey = MIMEContentHeaders.Publication;
- mmMessage.ContentHeaders[MIMEContentHeaders.URI] = "/circle";
- mmMessage.ContentHeaders[MIMEContentHeaders.ContentType] = "application/multiparty+xml";
-
- mmMessage.InnerBody = new byte[0];
-
- NSMessage putPayload = new NSMessage("PUT");
- putPayload.InnerMessage = mmMessage;
- nsmp.SendMessage(putPayload, transId);
-
- return transId;
- }
-
- #endregion
-
- #region GetMultiparty
-
- public Contact GetMultiparty(string tempGroupAddress)
- {
- if (!String.IsNullOrEmpty(tempGroupAddress))
- {
- lock (multiParties)
- {
- foreach (MultipartyObject group in multiParties.Values)
- {
- if (group.MultiParty != null && group.MultiParty.Account == tempGroupAddress)
- return group.MultiParty;
- }
- }
- }
-
- return null;
- }
-
- internal MultipartyObject GetMultipartyObject(string tempGroupAddress)
- {
- if (!String.IsNullOrEmpty(tempGroupAddress))
- {
- lock (multiParties)
- {
- foreach (MultipartyObject group in multiParties.Values)
- {
- if (group.MultiParty != null && group.MultiParty.Account == tempGroupAddress)
- return group;
- }
- }
- }
-
- return null;
- }
-
- #endregion
-
- #region InviteContactToMultiparty
-
- public void InviteContactToMultiparty(Contact contact, Contact group)
- {
- string to = ((int)group.ClientType).ToString() + ":" + group.Account;
- string from = ((int)Owner.ClientType).ToString() + ":" + Owner.Account;
- MultiMimeMessage mmMessage = new MultiMimeMessage(to, from);
- mmMessage.RoutingHeaders[MIMERoutingHeaders.From][MIMERoutingHeaders.EPID] = MachineGuid.ToString("B").ToLowerInvariant();
- mmMessage.RoutingHeaders[MIMERoutingHeaders.To][MIMERoutingHeaders.Path] = "IM";
-
- mmMessage.ContentKey = MIMEContentHeaders.Publication;
- mmMessage.ContentHeaders[MIMEContentHeaders.URI] = "/circle";
- mmMessage.ContentHeaders[MIMEContentHeaders.ContentType] = "application/multiparty+xml";
-
- string xml = "<circle><roster><id>IM</id><user><id>" + ((int)contact.ClientType).ToString() + ":" + contact.Account + "</id></user></roster></circle>";
- mmMessage.InnerBody = Encoding.UTF8.GetBytes(xml);
-
- NSMessage putPayload = new NSMessage("PUT");
- putPayload.InnerMessage = mmMessage;
- MessageProcessor.SendMessage(putPayload);
- }
-
- #region LeaveMultiparty
-
- public void LeaveMultiparty(Contact group)
- {
- string to = ((int)group.ClientType).ToString() + ":" + group.Account;
- string from = ((int)Owner.ClientType).ToString() + ":" + Owner.Account;
-
- MultiMimeMessage mmMessage = new MultiMimeMessage(to, from);
- mmMessage.RoutingHeaders[MIMERoutingHeaders.From][MIMERoutingHeaders.EPID] = MachineGuid.ToString("B").ToLowerInvariant();
-
- mmMessage.ContentKey = MIMEContentHeaders.Publication;
- mmMessage.ContentHeaders[MIMEContentHeaders.URI] = "/circle/roster(IM)/user(" + from + ")";
- mmMessage.ContentHeaders[MIMEContentHeaders.ContentType] = "application/circles+xml";
-
- mmMessage.InnerBody = new byte[0];
-
- NSMessage delPayload = new NSMessage("DEL");
- delPayload.InnerMessage = mmMessage;
- MessageProcessor.SendMessage(delPayload);
-
- lock (multiParties)
- {
- int delTransId = 0;
- foreach (MultipartyObject g in multiParties.Values)
- {
- if (g.MultiParty != null && g.MultiParty.Account == group.Account)
- {
- delTransId = g.TransactionID;
- break;
- }
- }
- if (delTransId != 0)
- multiParties.Remove(delTransId);
- }
- }
-
- #endregion
-
- #endregion
-
- #region JoinMultiparty
-
- internal void JoinMultiparty(Contact group)
- {
- if (group.ClientType == IMAddressInfoType.Circle || group.ClientType == IMAddressInfoType.TemporaryGroup)
- {
- string to = ((int)group.ClientType).ToString() + ":" + group.Account;
- string from = ((int)Owner.ClientType).ToString() + ":" + Owner.Account;
- MultiMimeMessage mmMessage = new MultiMimeMessage(to, from);
- mmMessage.RoutingHeaders[MIMERoutingHeaders.From][MIMERoutingHeaders.EPID] = MachineGuid.ToString("B").ToLowerInvariant();
-
- mmMessage.ContentKey = MIMEContentHeaders.Publication;
- mmMessage.ContentHeaders[MIMEContentHeaders.URI] = "/circle";
- mmMessage.ContentHeaders[MIMEContentHeaders.ContentType] = "application/circles+xml";
-
- string xml = "<circle><roster><id>IM</id><user><id>1:" + Owner.Account + "</id></user></roster></circle>";
-
- mmMessage.InnerBody = Encoding.UTF8.GetBytes(xml);
-
- NSMessage putPayload = new NSMessage("PUT");
- putPayload.InnerMessage = mmMessage;
- MessageProcessor.SendMessage(putPayload);
-
- OnJoinedGroupChat(new GroupChatParticipationEventArgs(Owner, group));
- }
- }
-
- #endregion
-
- #endregion
-
- #region MESSAGING
-
- #region SendTypingMessage
-
- protected internal virtual void SendTypingMessage(Contact remoteContact)
- {
- string to = ((int)remoteContact.ClientType).ToString() + ":" + remoteContact.Account;
- string from = ((int)Owner.ClientType).ToString() + ":" + Owner.Account;
-
- MultiMimeMessage mmMessage = new MultiMimeMessage(to, from);
- mmMessage.RoutingHeaders[MIMERoutingHeaders.From][MIMERoutingHeaders.EPID] = NSMessageHandler.MachineGuid.ToString("B").ToLowerInvariant();
-
- if (remoteContact.ClientType == IMAddressInfoType.Circle)
- {
- mmMessage.RoutingHeaders[MIMERoutingHeaders.To][MIMERoutingHeaders.Path] = "IM";
- }
-
- if (remoteContact.Via != null)
- {
- mmMessage.RoutingHeaders[MIMERoutingHeaders.To]["via"] =
- ((int)remoteContact.Via.ClientType).ToString() + ":" + remoteContact.Via.Account;
- }
-
- mmMessage.ContentKeyVersion = "2.0";
-
- mmMessage.ContentHeaders[MIMEContentHeaders.MessageType] = MessageTypes.ControlTyping;
- mmMessage.InnerBody = new byte[0];
-
- NSMessage sdgPayload = new NSMessage("SDG");
- sdgPayload.InnerMessage = mmMessage;
- MessageProcessor.SendMessage(sdgPayload);
- }
-
- #endregion
-
- #region SendNudge
-
- protected internal virtual void SendNudge(Contact remoteContact)
- {
- string to = ((int)remoteContact.ClientType).ToString() + ":" + remoteContact.Account;
- string from = ((int)Owner.ClientType).ToString() + ":" + Owner.Account;
-
- MultiMimeMessage mmMessage = new MultiMimeMessage(to, from);
- mmMessage.RoutingHeaders[MIMERoutingHeaders.From][MIMERoutingHeaders.EPID] = NSMessageHandler.MachineGuid.ToString("B").ToLowerInvariant();
-
- if (remoteContact.ClientType == IMAddressInfoType.Circle)
- {
- mmMessage.RoutingHeaders[MIMERoutingHeaders.To][MIMERoutingHeaders.Path] = "IM";
- }
-
- if (remoteContact.Via != null)
- {
- mmMessage.RoutingHeaders[MIMERoutingHeaders.To]["via"] =
- ((int)remoteContact.Via.ClientType).ToString() + ":" + remoteContact.Via.Account;
- }
-
- mmMessage.ContentKeyVersion = "2.0";
-
- mmMessage.ContentHeaders[MIMEContentHeaders.MessageType] = MessageTypes.Nudge;
- mmMessage.InnerBody = Encoding.ASCII.GetBytes("\r\n");
-
- NSMessage sdgPayload = new NSMessage("SDG");
- sdgPayload.InnerMessage = mmMessage;
- MessageProcessor.SendMessage(sdgPayload);
- }
-
- #endregion
-
- #region SendTextMessage
-
- protected internal virtual void SendTextMessage(Contact remoteContact, TextMessage textMessage)
- {
- textMessage.PrepareMessage();
-
- string to = ((int)remoteContact.ClientType).ToString() + ":" + remoteContact.Account;
- string from = ((int)Owner.ClientType).ToString() + ":" + Owner.Account;
-
- MultiMimeMessage mmMessage = new MultiMimeMessage(to, from);
- mmMessage.RoutingHeaders[MIMERoutingHeaders.From][MIMERoutingHeaders.EPID] = NSMessageHandler.MachineGuid.ToString("B").ToLowerInvariant();
-
- if (remoteContact.ClientType == IMAddressInfoType.Circle)
- {
- mmMessage.RoutingHeaders[MIMERoutingHeaders.To][MIMERoutingHeaders.Path] = "IM";
- }
- else if (remoteContact.Online)
- {
- mmMessage.RoutingHeaders[MIMERoutingHeaders.ServiceChannel] = "IM/Online";
- }
- else
- {
- mmMessage.RoutingHeaders[MIMERoutingHeaders.ServiceChannel] = "IM/Offline";
- }
-
- if (remoteContact.Via != null)
- {
- mmMessage.RoutingHeaders[MIMERoutingHeaders.To]["via"] =
- ((int)remoteContact.Via.ClientType).ToString() + ":" + remoteContact.Via.Account;
- }
-
-
- mmMessage.ContentKeyVersion = "2.0";
-
- mmMessage.ContentHeaders[MIMEContentHeaders.MessageType] = MessageTypes.Text;
- mmMessage.ContentHeaders[MIMEHeaderStrings.X_MMS_IM_Format] = textMessage.GetStyleString();
- mmMessage.InnerBody = Encoding.UTF8.GetBytes(textMessage.Text);
-
- NSMessage sdgPayload = new NSMessage("SDG");
- sdgPayload.InnerMessage = mmMessage;
- MessageProcessor.SendMessage(sdgPayload);
- }
-
- protected internal virtual void SendOIMMessage(Contact remoteContact, TextMessage textMessage)
- {
- SendTextMessage(remoteContact, textMessage);
- }
-
- #endregion
-
- #region SendMobileMessage
-
- /// <summary>
- /// Sends a mobile message to the specified remote contact. This only works when
- /// the remote contact has it's mobile device enabled and has MSN-direct enabled.
- /// </summary>
- /// <param name="receiver"></param>
- /// <param name="text"></param>
- protected internal virtual void SendMobileMessage(Contact receiver, string text)
- {
- TextMessage txtMsg = new TextMessage(text);
-
- string to = ((int)receiver.ClientType).ToString() + ":" + ((receiver.ClientType == IMAddressInfoType.Telephone) ? "tel:" + receiver.Account : receiver.Account);
- string from = ((int)Owner.ClientType).ToString() + ":" + Owner.Account;
-
- MultiMimeMessage mmMessage = new MultiMimeMessage(to, from);
- mmMessage.RoutingHeaders[MIMERoutingHeaders.From][MIMERoutingHeaders.EPID] = MachineGuid.ToString("B").ToLowerInvariant();
- mmMessage.RoutingHeaders[MIMERoutingHeaders.ServiceChannel] = "IM/Mobile";
-
- mmMessage.ContentKeyVersion = "2.0";
- mmMessage.ContentHeaders[MIMEContentHeaders.MessageType] = MessageTypes.Text;
- mmMessage.ContentHeaders[MIMEContentHeaders.MSIMFormat] = txtMsg.GetStyleString();
-
- mmMessage.InnerBody = Encoding.UTF8.GetBytes(txtMsg.Text);
-
- NSMessage sdgPayload = new NSMessage("SDG");
- sdgPayload.InnerMessage = mmMessage;
- MessageProcessor.SendMessage(sdgPayload);
- }
-
- #endregion
-
- #region SendEmoticonDefinitions
-
- protected internal virtual void SendEmoticonDefinitions(Contact remoteContact, List<Emoticon> emoticons, EmoticonType icontype)
- {
- EmoticonMessage emoticonMessage = new EmoticonMessage(emoticons, icontype);
-
- string to = ((int)remoteContact.ClientType).ToString() + ":" + remoteContact.Account;
- string from = ((int)Owner.ClientType).ToString() + ":" + Owner.Account;
-
- MultiMimeMessage mmMessage = new MultiMimeMessage(to, from);
- mmMessage.RoutingHeaders[MIMERoutingHeaders.From][MIMERoutingHeaders.EPID] = MachineGuid.ToString("B").ToLowerInvariant();
-
- mmMessage.ContentKeyVersion = "2.0";
-
- mmMessage.ContentHeaders[MIMEContentHeaders.MessageType] = MessageTypes.CustomEmoticon;
- mmMessage.ContentHeaders[MIMEContentHeaders.ContentType] = icontype == EmoticonType.AnimEmoticon ? "text/x-mms-animemoticon" : "text/x-mms-emoticon";
- mmMessage.InnerBody = emoticonMessage.GetBytes();
-
- NSMessage sdgPayload = new NSMessage("SDG");
- sdgPayload.InnerMessage = mmMessage;
- MessageProcessor.SendMessage(sdgPayload);
- }
-
- #endregion
-
- #endregion
-
- #region PRESENCE
-
- #region SignoutFrom
-
- internal void SignoutFrom(Guid endPointID)
- {
- string me = ((int)Owner.ClientType).ToString() + ":" + Owner.Account;
-
- MultiMimeMessage mmMessage = new MultiMimeMessage(me, me);
- mmMessage.RoutingHeaders[MIMERoutingHeaders.From][MIMERoutingHeaders.EPID] = MachineGuid.ToString("B").ToLowerInvariant();
-
- mmMessage.ContentKey = MIMEContentHeaders.Publication;
- mmMessage.ContentHeaders[MIMEContentHeaders.URI] = "/user";
- mmMessage.ContentHeaders[MIMEContentHeaders.ContentType] = "application/user+xml";
-
- string xml = "<user><sep n=\"IM\" epid=\"" + endPointID.ToString("B").ToLowerInvariant() + "\"/></user>";
-
- mmMessage.InnerBody = Encoding.UTF8.GetBytes(xml);
-
- NSMessage delPayload = new NSMessage("DEL");
- delPayload.InnerMessage = mmMessage;
- MessageProcessor.SendMessage(delPayload);
-
- // We will receive NFY DEL for normal users
- if (endPointID == MachineGuid && messageProcessor.Connected)
- messageProcessor.Disconnect();
- }
-
- #endregion
-
- #region SetScreenName & SetPersonalMessage
-
- /// <summary>
- /// Sets the contactlist owner's screenname. After receiving confirmation from the server
- /// this will set the Owner object's name which will in turn raise the NameChange event.
- /// </summary>
- internal void SetScreenName(string newName)
- {
- if (Owner == null)
- throw new MSNPSharpException("Not a valid owner");
-
- if (string.IsNullOrEmpty(newName))
- {
- newName = Owner.Account;
- }
-
- PersonalMessage pm = Owner.PersonalMessage;
-
- pm.FriendlyName = newName;
-
- SetPersonalMessage(pm);
- }
-
- /// <summary>
- /// Sets personal message.
- /// </summary>
- internal void SetPersonalMessage(PersonalMessage newPSM)
- {
- if (Owner == null)
- throw new MSNPSharpException("Not a valid owner");
-
- if (Owner.Status != PresenceStatus.Offline)
- {
- SetPresenceStatus(
- Owner.Status,
- Owner.LocalEndPointIMCapabilities, Owner.LocalEndPointIMCapabilitiesEx,
- Owner.LocalEndPointPECapabilities, Owner.LocalEndPointPECapabilitiesEx,
- Owner.EpName, newPSM, true);
- }
- }
-
- /// <summary>
- /// Sets the scene image and scheme context.
- /// </summary>
- internal void SetSceneData(SceneImage scimg, Color sccolor)
- {
- if (Owner == null)
- throw new MSNPSharpException("Not a valid owner");
-
- PersonalMessage pm = Owner.PersonalMessage;
-
- pm.ColorScheme = sccolor;
- pm.Scene = scimg.IsDefaultImage ? String.Empty : scimg.ContextPlain;
-
- SetPresenceStatus(Owner.Status,
- Owner.LocalEndPointIMCapabilities, Owner.LocalEndPointIMCapabilitiesEx,
- Owner.LocalEndPointPECapabilities, Owner.LocalEndPointPECapabilitiesEx,
- Owner.EpName, pm, true);
- }
-
- #endregion
-
- #region SetPresenceStatus
-
- /// <summary>
- /// Set the status of the contact list owner (the client).
- /// </summary>
- /// <remarks>You can only set the status _after_ SignedIn event. Otherwise you won't receive online notifications from other clients or the connection is closed by the server.</remarks>
- internal void SetPresenceStatus(
- PresenceStatus newStatus,
- ClientCapabilities newLocalIMCaps, ClientCapabilitiesEx newLocalIMCapsex,
- ClientCapabilities newLocalPECaps, ClientCapabilitiesEx newLocalPECapsex,
- string newEPName,
- PersonalMessage newPSM,
- bool forcePEservice)
- {
- if (IsSignedIn == false)
- throw new MSNPSharpException("Can't set status. You must wait for the SignedIn event before you can set an initial status.");
-
- if (newStatus == PresenceStatus.Offline)
- {
- SignoutFrom(MachineGuid);
- return;
- }
-
- bool setAll = (Owner.Status == PresenceStatus.Offline);
-
- if (setAll || forcePEservice ||
- newStatus != Owner.Status ||
- newLocalIMCaps != Owner.LocalEndPointIMCapabilities ||
- newLocalIMCapsex != Owner.LocalEndPointIMCapabilitiesEx ||
- newLocalPECaps != Owner.LocalEndPointPECapabilities ||
- newLocalPECapsex != Owner.LocalEndPointPECapabilitiesEx ||
- newEPName != Owner.EpName)
- {
- XmlDocument xmlDoc = new XmlDocument();
- XmlElement userElement = xmlDoc.CreateElement("user");
-
- // s.IM (Status, CurrentMedia)
- if (setAll || forcePEservice ||
- newStatus != Owner.Status)
- {
- XmlElement service = xmlDoc.CreateElement("s");
- service.SetAttribute("n", ServiceShortNames.IM.ToString());
- service.InnerXml =
- "<Status>" + ParseStatus(newStatus) + "</Status>" +
- "<CurrentMedia>" + MSNHttpUtility.XmlEncode(newPSM.CurrentMedia) + "</CurrentMedia>";
-
- userElement.AppendChild(service);
-
- // Don't call Owner.Status = newStatus.
- }
-
- // s.PE (UserTileLocation, FriendlyName, PSM, Scene, ColorScheme)
- if (setAll ||
- forcePEservice)
- {
- XmlElement service = xmlDoc.CreateElement("s");
- service.SetAttribute("n", ServiceShortNames.PE.ToString());
- service.InnerXml = newPSM.Payload;
- userElement.AppendChild(service);
-
- // Don't set owner.PersonalMessage here. It is replaced (with a new reference) when NFY PUT received.
- }
-
- // sep.IM (Capabilities)
- if (setAll ||
- newLocalIMCaps != Owner.LocalEndPointIMCapabilities ||
- newLocalIMCapsex != Owner.LocalEndPointIMCapabilitiesEx)
- {
- ClientCapabilities localIMCaps = setAll ? ClientCapabilities.DefaultIM : newLocalIMCaps;
- ClientCapabilitiesEx localIMCapsEx = setAll ? ClientCapabilitiesEx.DefaultIM : newLocalIMCapsex;
-
- XmlElement sep = xmlDoc.CreateElement("sep");
- sep.SetAttribute("n", ServiceShortNames.IM.ToString());
- XmlElement capabilities = xmlDoc.CreateElement("Capabilities");
- capabilities.InnerText = ((long)localIMCaps).ToString() + ":" + ((long)localIMCapsEx).ToString();
- sep.AppendChild(capabilities);
- userElement.AppendChild(sep);
-
- // Don't call Owner.LocalEndPointIMCapabilities. It is recursive call to this method.
- }
-
- // sep.PE (Capabilities)
- if (setAll ||
- newLocalPECaps != Owner.LocalEndPointPECapabilities ||
- newLocalPECapsex != Owner.LocalEndPointPECapabilitiesEx)
- {
- ClientCapabilities localPECaps = setAll ? ClientCapabilities.DefaultPE : newLocalPECaps;
- ClientCapabilitiesEx localPECapsEx = setAll ? ClientCapabilitiesEx.DefaultPE : newLocalPECapsex;
-
- XmlElement sep = xmlDoc.CreateElement("sep");
- sep.SetAttribute("n", ServiceShortNames.PE.ToString());
- XmlElement VER = xmlDoc.CreateElement("VER");
- VER.InnerText = Credentials.ClientInfo.MessengerClientName + ":" + Credentials.ClientInfo.MessengerClientBuildVer;
- sep.AppendChild(VER);
- XmlElement TYP = xmlDoc.CreateElement("TYP");
- TYP.InnerText = "1";
- sep.AppendChild(TYP);
- XmlElement capabilities = xmlDoc.CreateElement("Capabilities");
- capabilities.InnerText = ((long)localPECaps).ToString() + ":" + ((long)localPECapsEx).ToString();
- sep.AppendChild(capabilities);
- userElement.AppendChild(sep);
-
- // Don't call Owner.LocalEndPointPECapabilities. It is recursive call to this method.
- }
-
- // sep.PD (EpName, State)
- if (setAll ||
- newEPName != Owner.EpName ||
- newStatus != Owner.Status)
- {
- XmlElement sep = xmlDoc.CreateElement("sep");
- sep.SetAttribute("n", ServiceShortNames.PD.ToString());
- XmlElement clientType = xmlDoc.CreateElement("ClientType");
- clientType.InnerText = "1";
- sep.AppendChild(clientType);
- XmlElement epName = xmlDoc.CreateElement("EpName");
- epName.InnerText = MSNHttpUtility.XmlEncode(newEPName);
- sep.AppendChild(epName);
- XmlElement idle = xmlDoc.CreateElement("Idle");
- idle.InnerText = ((newStatus == PresenceStatus.Idle) ? "true" : "false");
- sep.AppendChild(idle);
- XmlElement state = xmlDoc.CreateElement("State");
- state.InnerText = ParseStatus(newStatus);
- sep.AppendChild(state);
- userElement.AppendChild(sep);
-
- // Don't set Owner.EpName. It is recursive call to this method.
- }
-
- if (userElement.HasChildNodes)
- {
- string xml = userElement.OuterXml;
- string me = ((int)Owner.ClientType).ToString() + ":" + Owner.Account;
-
- MultiMimeMessage mmMessage = new MultiMimeMessage(me, me);
- mmMessage.RoutingHeaders[MIMERoutingHeaders.From][MIMERoutingHeaders.EPID] = NSMessageHandler.MachineGuid.ToString("B").ToLowerInvariant();
-
- mmMessage.Stream = 1;
- mmMessage.ReliabilityHeaders[MIMEReliabilityHeaders.Flags] = "ACK";
-
- mmMessage.ContentKey = MIMEContentHeaders.Publication;
- mmMessage.ContentHeaders[MIMEContentHeaders.URI] = "/user";
- mmMessage.ContentHeaders[MIMEContentHeaders.ContentType] = "application/user+xml";
-
- mmMessage.InnerBody = System.Text.Encoding.UTF8.GetBytes(xml);
-
- NSMessage nsMessage = new NSMessage("PUT");
- nsMessage.InnerMessage = mmMessage;
- MessageProcessor.SendMessage(nsMessage);
- }
- }
- }
-
-
- #endregion
-
- #endregion
-
- #region COMMAND HANDLERS (PUT, DEL, NFY, SDG)
-
- #region OnPUTReceived
-
- /// <summary>
- /// Called when a PUT command message has been received.
- /// </summary>
- /// <param name="message"></param>
- protected virtual void OnPUTReceived(NSMessage message)
- {
- bool ok = message.CommandValues.Count > 0 && message.CommandValues[0].ToString() == "OK";
- if (multiParties.ContainsKey(message.TransactionID))
- {
- if (ok == false || message.InnerBody == null || message.InnerBody.Length == 0)
- {
- lock (multiParties)
- multiParties.Remove(message.TransactionID);
-
- return;
- }
-
- MultiMimeMessage mmMessage = new MultiMimeMessage(message.InnerBody);
- string[] tempGroup = mmMessage.From.Value.Split(':');
- IMAddressInfoType addressType = (IMAddressInfoType)int.Parse(tempGroup[0]);
-
- if (addressType == IMAddressInfoType.TemporaryGroup)
- {
- Contact group = new Contact(tempGroup[1].ToLowerInvariant(), IMAddressInfoType.TemporaryGroup, this);
- group.ContactList = new ContactList(new Guid(tempGroup[1].ToLowerInvariant().Split('@')[0]), null, group, this);
-
- MultipartyObject mpo = multiParties[message.TransactionID];
- mpo.TransactionID = message.TransactionID;
- mpo.MultiParty = group;
-
- JoinMultiparty(group);
-
- List<string> copy = new List<string>(mpo.InviteQueueHash);
-
- foreach (string siblingHash in copy)
- {
- string[] addressTypeAndAccount = siblingHash.Split(new char[] { ':' }, 2, StringSplitOptions.RemoveEmptyEntries);
- Contact contact = ContactList.GetContactWithCreate(addressTypeAndAccount[1], (IMAddressInfoType)Enum.Parse(typeof(IMAddressInfoType), addressTypeAndAccount[0].ToString()));
-
- InviteContactToMultiparty(contact, group);
- }
-
- mpo.OnMultipartyCreatedLocally(this, new MultipartyCreatedEventArgs(group));
-
- group.SetStatus(PresenceStatus.Online);
-
- Trace.WriteLineIf(Settings.TraceSwitch.TraceInfo, "MultipartyCreated: " + group.Account);
- }
- else
- {
- lock (multiParties)
- multiParties.Remove(message.TransactionID);
- }
- }
- }
-
- #endregion
-
- #region OnDELReceived
-
- /// <summary>
- /// Called when a DEL command message has been received.
- /// </summary>
- /// <param name="message"></param>
- protected virtual void OnDELReceived(NSMessage message)
- {
- bool ok = message.CommandValues.Count > 0 && message.CommandValues[0].ToString() == "OK";
- if (ok)
- {
- Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose, "DEL command accepted", GetType().Name);
- }
- }
-
- #endregion
-
- #region OnNFYReceived
-
- private void OnNFYPUTReceived(MultiMimeMessage multiMimeMessage, RoutingInfo routingInfo)
- {
- switch (multiMimeMessage.ContentHeaders[MIMEContentHeaders.ContentType].Value)
- {
- #region user xml
- case "application/user+xml":
- {
-
- if (multiMimeMessage.ContentHeaders[MIMEHeaderStrings.NotifType].Value == "Sync")
- {
- if (routingInfo.SenderGateway != null && routingInfo.SenderGateway.ClientType == IMAddressInfoType.Circle)
- {
- JoinMultiparty(routingInfo.SenderGateway);
- }
-
- //Sync the contact in contact list with the contact in gateway.
- // TODO: Set the NSMessagehandler.ContactList contact to the gateway
- // TODO: triger the ContactOnline event for the gateway contact.
-
-
-
- //Just wait for my fix.
- }
-
- if (multiMimeMessage.InnerBody == null || multiMimeMessage.InnerBody.Length == 0)
- return; //No xml content.
-
- if (multiMimeMessage.ContentHeaders[MIMEHeaderStrings.NotifType].Value == "Full")
- {
- //This is an initial NFY
- }
-
-
-
- XmlDocument xmlDoc = new XmlDocument();
- xmlDoc.LoadXml(Encoding.UTF8.GetString(multiMimeMessage.InnerBody));
- XmlNodeList services = xmlDoc.SelectNodes("//user/s");
- XmlNodeList serviceEndPoints = xmlDoc.SelectNodes("//user/sep");
-
- if (services.Count > 0)
- {
- foreach (XmlNode service in services)
- {
- ServiceShortNames serviceEnum = (ServiceShortNames)Enum.Parse(typeof(ServiceShortNames), service.Attributes["n"].Value);
- switch (serviceEnum)
- {
- case ServiceShortNames.IM:
- {
- foreach (XmlNode node in service.ChildNodes)
- {
- switch (node.Name)
- {
- case "Status":
-
- if (routingInfo.FromOwner && IsSignedIn == false)
- {
- // We have already signed in another place, but not here...
- // Don't set status... This place will set the status later.
- return;
- }
-
- PresenceStatus oldStatus = routingInfo.Sender.Status;
- PresenceStatus newStatus = ParseStatus(node.InnerText);
- routingInfo.Sender.SetStatus(newStatus);
-
- OnContactStatusChanged(new ContactStatusChangedEventArgs(routingInfo.Sender, routingInfo.SenderGateway, oldStatus, newStatus));
- OnContactOnline(new ContactStatusChangedEventArgs(routingInfo.Sender, routingInfo.SenderGateway, oldStatus, newStatus));
-
- break;
-
- case "CurrentMedia":
- //MSNP21TODO: UBX implementation
-
- break;
- }
- }
- break;
- }
-
- case ServiceShortNames.PE:
- {
- // Create a new reference to fire PersonalMessageChanged event.
- PersonalMessage personalMessage = new PersonalMessage(service.ChildNodes);
-
- if (!String.IsNullOrEmpty(personalMessage.Payload) &&
- routingInfo.Sender.PersonalMessage != personalMessage)
- {
- // FriendlyName
- if (!String.IsNullOrEmpty(personalMessage.FriendlyName))
- {
- //Only Windows Live Messenger Contact has friendly name.
- routingInfo.Sender.SetName(personalMessage.FriendlyName);
- }
-
- // UserTileLocation
- if (!String.IsNullOrEmpty(personalMessage.UserTileLocation) && routingInfo.Sender.UserTileLocation != personalMessage.UserTileLocation)
- {
- routingInfo.Sender.UserTileLocation = personalMessage.UserTileLocation;
- routingInfo.Sender.FireDisplayImageContextChangedEvent(personalMessage.UserTileLocation);
- }
-
- // Scene
- if (!String.IsNullOrEmpty(personalMessage.Scene))
- {
- if (routingInfo.Sender.SceneContext != personalMessage.Scene)
- {
- routingInfo.Sender.SceneContext = personalMessage.Scene;
- routingInfo.Sender.FireSceneImageContextChangedEvent(personalMessage.Scene);
- }
- }
-
- // ColorScheme
- if (personalMessage.ColorScheme != Color.Empty)
- {
- if (routingInfo.Sender.ColorScheme != personalMessage.ColorScheme)
- {
- routingInfo.Sender.ColorScheme = personalMessage.ColorScheme;
- routingInfo.Sender.OnColorSchemeChanged();
- }
- }
-
- // This must be final...
- routingInfo.Sender.PersonalMessage = personalMessage;
-
- }
- break;
- }
-
- case ServiceShortNames.PF:
- {
- // Profile Annotation, it is AB.Me.annotations/Live.Profile.Expression.LastChanged
- // <user><s n="PF" ts="2011-04-16T06:00:58Z"></s></user>
- if (routingInfo.FromOwner)
- {
- DateTime ts = WebServiceDateTimeConverter.ConvertToDateTime(service.Attributes["ts"].Value);
- }
- break;
- }
- }
- }
- }
-
- if (serviceEndPoints.Count > 0)
- {
- foreach (XmlNode serviceEndPoint in serviceEndPoints)
- {
- ServiceShortNames serviceEnum = (ServiceShortNames)Enum.Parse(typeof(ServiceShortNames), serviceEndPoint.Attributes["n"].Value);
- Guid epid = serviceEndPoint.Attributes["epid"] == null ? Guid.Empty : new Guid…