Exemple #1
0
        void PrintGroupChatPresence(XmppGroupChatModel chat, PersonModel person, Presence pres)
        {
            Jid jid = pres.From;

            var msg = CreatePresenceUpdateMessage(person.ID, person, pres);
            Session.AddMessageToChat(chat, msg);
            // clone directly to muc person chat
            // don't care about real jid, that has its own presence packets
            var personChat = Session.GetChat(jid, ChatType.Person, this);
            if (personChat != null) {
                Session.AddMessageToChat(personChat, msg);
            }
        }
Exemple #2
0
        void OnGroupChatPresence(XmppGroupChatModel chat, Presence pres)
        {
            Jid jid = pres.From;
            var person = new PersonModel(jid, pres.From.Resource ?? pres.From, NetworkID, Protocol, this);
            PrintGroupChatPresence(chat, person, pres);
            switch (pres.Type) {
                case PresenceType.available:
                    // don't do anything if the contact already exists
                    if (chat.UnsafePersons.ContainsKey(person.ID)) {
                        return;
                    }
                    // is the chat synced? add the new contact the regular way
                    if (chat.IsSynced) {
                        Session.AddPersonToGroupChat(chat, person);
                        return;
                    }

                    chat.UnsafePersons.Add(person.ID, person);

                    // did I join? then the chat roster is fully received
                    if (pres.From.Resource == chat.OwnNickname ||
                        pres.MucUser.StatusCodes.Exists(x => x.Code == StatusCode.SelfPresence)) {
                        if (pres.MucUser.StatusCodes.Exists(x => x.Code == StatusCode.ModifiedNick)) {
                            // as per XEP-0045 7.2.3 Example 24 the server is
                            // allowed to give us a different nick than we requested
                            chat.OwnNickname = pres.From.Resource;
                        }
                        chat.IsJoining = false;
                        // HACK: lower probability of sync race condition swallowing messages
                        ThreadPool.QueueUserWorkItem(delegate {
                            Thread.Sleep(1000);
                            lock (this) {
                                if (IsDisposed) {
                                    return;
                                }
                                chat.IsSynced = true;
                                Session.SyncChat(chat);
                                Session.EnableChat(chat);
                            }
                        });
                    }
                    break;
                case PresenceType.unavailable:
                    Session.RemovePersonFromGroupChat(chat, person);
                    // did I leave? then I "probably" left the room
                    if (pres.From.Resource == chat.OwnNickname) {
                        Session.RemoveChat(chat);
                    }
                    break;
                case PresenceType.error:
                    OnGroupChatPresenceError(chat, pres);
                    break;
            }
        }
Exemple #3
0
        void OnGroupChatPresenceError(XmppGroupChatModel chat, Presence pres)
        {
            if (pres.Error != null &&
                pres.Error.Type == ErrorType.cancel &&
                pres.Error.Condition == ErrorCondition.Conflict) {
                // nickname already in use; autorejoin with _ appended
                JoinRoom(chat.ID, chat.OwnNickname + "_", chat.Password);
                return;
            }

            var msg = CreateGroupChatPresenceErrorMessage(pres);
            Session.AddMessageToChat(NetworkChat, msg);
            Session.RemoveChat(chat);
        }
Exemple #4
0
        MessageModel CreateGroupChatMessage(XmppGroupChatModel groupChat, PersonModel person, Message msg)
        {
            var builder = CreateMessageBuilder();
            string msgstring;
            if (msg.Html != null) {
                msgstring = msg.Html.ToString();
            } else {
                msgstring = msg.Body.Trim();
            }

            if (msgstring.StartsWith("/me ")) {
                // leave the " " intact
                msgstring = msgstring.Substring(3);
                builder.AppendActionPrefix();
                builder.AppendIdendityName(person);
            } else {
                builder.AppendSenderPrefix(person);
            }

            if (msg.Html != null) {
                builder.AppendHtmlMessage(msgstring);
            } else {
                builder.AppendMessage(msgstring);
            }
            // mark hilights only for OwnNickname, too
            builder.Me = new PersonModel(
                groupChat.OwnNickname,
                groupChat.OwnNickname,
                NetworkID, Protocol, this);
            builder.MarkHighlights();

            if (msg.XDelay != null) {
                builder.TimeStamp = msg.XDelay.Stamp;
            }
            return builder.ToMessage();
        }
Exemple #5
0
 void OnGroupChatMessageError(Message msg, XmppGroupChatModel chat)
 {
     var builder = CreateMessageBuilder();
     // TODO: nicer formatting
     if (msg.Error.ErrorText != null) {
         builder.AppendErrorText(msg.Error.ErrorText);
     } else {
         builder.AppendErrorText(msg.Error.ToString());
     }
     Session.AddMessageToChat(chat, builder.ToMessage());
 }
Exemple #6
0
        private void _OnMessage(object sender, Message xmppMsg)
        {
            if (xmppMsg.Body == null) {
                return;
            }

            var delay = xmppMsg["delay"];
            string stamp = null;
            if (delay != null) {
                stamp = delay.Attributes["stamp"].Value;
            }
            bool display = true;

            ChatModel chat = null;
            PersonModel person = null;
            if (xmppMsg.Type != XmppMessageType.groupchat) {
                string jid = xmppMsg.From.Bare;
                var contact = _RosterManager[jid];
                string nickname = jid;
                if (contact != null && contact.Nickname != null) {
                    nickname = contact.Nickname.Replace(" ", "_");
                }
                PersonChatModel personChat = (PersonChatModel) Session.GetChat(jid, ChatType.Person, this);
                if (personChat == null) {
                    person = new PersonModel(jid, nickname, NetworkID,
                                             Protocol, this);
                    personChat = new PersonChatModel(person, jid, nickname, this);
                    Session.AddChat(personChat);
                    Session.SyncChat(personChat);
                } else {
                    person = personChat.Person;
                }
                chat = personChat;
            } else {
                string group_jid = xmppMsg.From.Bare;
                string group_name = group_jid;
                string sender_jid = xmppMsg.From.ToString();
                XmppGroupChatModel groupChat = (XmppGroupChatModel) Session.GetChat(group_jid, ChatType.Group, this);
                if (groupChat == null) {
                    // FIXME shouldn't happen?
                    groupChat = new XmppGroupChatModel(group_jid, group_name, this);
                    Session.AddChat(groupChat);
                    Session.SyncChat(groupChat);
                }
                person = groupChat.GetPerson(xmppMsg.From.Resource);
                if (person == null) {
                    // happens in case of a delayed message if the participant has left meanwhile
                    person = new PersonModel(xmppMsg.From.Resource, xmppMsg.From.Resource,
                                             NetworkID, Protocol, this);
                }

                // XXX maybe only a Google Talk bug requires this:
                if (stamp != null) {
                    // XXX can't use > because of seconds precision :-(
                    if (stamp.CompareTo(groupChat.LatestSeenStamp) >= 0) {
                        groupChat.LatestSeenStamp = stamp;
                    } else {
                        display = false; // already seen newer delayed message
                    }
                    if (groupChat.SeenNewMessages) {
                        display = false; // already seen newer messages
                    }
                } else {
                    groupChat.SeenNewMessages = true;
                }

                chat = groupChat;
            }

            if (display) {
                var builder = CreateMessageBuilder();
                if (xmppMsg.Type != XmppMessageType.error) {
                    builder.AppendMessage(person, xmppMsg.Body);
                } else {
                    // TODO: nicer formatting
                    builder.AppendMessage(xmppMsg.Error.ToString());
                }
                var msg = builder.ToMessage();
                if (stamp != null) {
                    string format = DateTimeFormatInfo.InvariantInfo.UniversalSortableDateTimePattern.Replace(" ", "T");
                    msg.TimeStamp = DateTime.ParseExact(stamp, format, null);
                }
                Session.AddMessageToChat(chat, msg);
            }
        }
        void OnGroupChatPresenceError(XmppGroupChatModel chat, Presence pres)
        {
            var msg = CreateGroupChatPresenceErrorMessage(pres);
            if (pres.Error == null) {
                Session.AddMessageToChat(NetworkChat, msg);
                Session.RemoveChat(chat);
            }
            // is there an action we can do silently?
            switch (pres.Error.Type) {
                case ErrorType.cancel:
                    switch (pres.Error.Condition) {
                        case ErrorCondition.Conflict:
                            // nickname already in use
                            // autorejoin with _ appended to nickname
                            JoinRoom(chat.ID, chat.OwnNickname + "_", chat.Password);
                            return;
                    }
                    break;
            }

            Session.AddMessageToChat(NetworkChat, msg);
            Session.RemoveChat(chat);
        }
Exemple #8
0
        private void AddPersonToGroup(Room room, string nickname)
        {
            string jid = room.JID.Bare;
            var chat = (GroupChatModel) Session.GetChat(jid, ChatType.Group, this);
            // first notice we're joining a group chat is the participant info:
            if (chat == null) {
                chat = new XmppGroupChatModel(jid, jid, this);
                Session.AddChat(chat);
                Session.SyncChat(chat);
            }

            PersonModel person;
            lock(chat.UnsafePersons) {
                person = chat.GetPerson(nickname);
                if (person != null) {
                    return;
                }

                person = new PersonModel(nickname, nickname,
                                         NetworkID, Protocol, this);
                chat.UnsafePersons.Add(nickname, person);
                Session.AddPersonToGroupChat(chat, person);
            }
        }
 void OnGroupChatPresenceError(XmppGroupChatModel chat, Presence pres)
 {
     var builder = CreateMessageBuilder();
     if (pres.Error == null) {
         builder.AppendErrorText(_("An unknown groupchat error occurred: {0}"), pres);
         Session.AddMessageToChat(NetworkChat, builder.ToMessage());
         return;
     }
     switch (pres.Error.Type) {
         case ErrorType.cancel:
             switch (pres.Error.Condition) {
                 case ErrorCondition.Conflict:
                     // nickname already in use
                     // autorejoin with _ appended to nickname
                     JoinRoom(chat.ID, chat.OwnNickname + "_", chat.Password);
                     return;
             }
             break;
     }
     if (String.IsNullOrEmpty(pres.Error.ErrorText)) {
         builder.AppendErrorText(_("An unhandled groupchat error occurred: {0}"), pres);
     } else {
         builder.AppendErrorText(_("Error in Groupchat {0}: {1}"), chat.ID, pres.Error.ErrorText);
     }
     Session.AddMessageToChat(NetworkChat, builder.ToMessage());
     Session.RemoveChat(chat);
 }
Exemple #10
0
        private void OnMessage(object sender, Message msg)
        {
            if (msg.Body == null)
            {
                return;
            }

            var    delay = msg["delay"];
            string stamp = null;

            if (delay != null)
            {
                stamp = delay.Attributes["stamp"].Value;
            }
            bool display = true;

            ChatModel   chat   = null;
            PersonModel person = null;

            if (msg.Type != XmppMessageType.groupchat)
            {
                string jid      = msg.From.Bare;
                var    contact  = _RosterManager[jid];
                string nickname = null;
                if (contact == null || String.IsNullOrEmpty(contact.Nickname))
                {
                    nickname = jid;
                }
                else
                {
                    nickname = contact.Nickname;
                }
                PersonChatModel personChat = (PersonChatModel)Session.GetChat(jid, ChatType.Person, this);
                if (personChat == null)
                {
                    person = new PersonModel(jid, nickname, NetworkID,
                                             Protocol, this);
                    personChat = Session.CreatePersonChat(
                        person, jid, nickname, this
                        );
                    Session.AddChat(personChat);
                    Session.SyncChat(personChat);
                }
                else
                {
                    person = personChat.Person;
                }
                chat = personChat;
            }
            else
            {
                string             group_jid  = msg.From.Bare;
                string             group_name = group_jid;
                string             sender_jid = msg.From.ToString();
                XmppGroupChatModel groupChat  = (XmppGroupChatModel)Session.GetChat(group_jid, ChatType.Group, this);
                if (groupChat == null)
                {
                    // FIXME shouldn't happen?
                    groupChat = Session.CreateChat <XmppGroupChatModel>(
                        group_jid, group_name, this
                        );
                    Session.AddChat(groupChat);
                    Session.SyncChat(groupChat);
                }
                person = groupChat.GetPerson(msg.From.Resource);
                if (person == null)
                {
                    // happens in case of a delayed message if the participant has left meanwhile
                    person = new PersonModel(msg.From.Resource,
                                             msg.From.Resource,
                                             NetworkID, Protocol, this);
                }

                // XXX maybe only a Google Talk bug requires this:
                if (stamp != null)
                {
                    // XXX can't use > because of seconds precision :-(
                    if (stamp.CompareTo(groupChat.LatestSeenStamp) >= 0)
                    {
                        groupChat.LatestSeenStamp = stamp;
                    }
                    else
                    {
                        display = false; // already seen newer delayed message
                    }
                    if (groupChat.SeenNewMessages)
                    {
                        display = false; // already seen newer messages
                    }
                }
                else
                {
                    groupChat.SeenNewMessages = true;
                }

                chat = groupChat;
            }

            if (display)
            {
                var builder = CreateMessageBuilder();
                if (msg.Type != XmppMessageType.error)
                {
                    builder.AppendMessage(person, msg.Body);
                }
                else
                {
                    // TODO: nicer formatting
                    builder.AppendMessage(msg.Error.ToString());
                }
                if (stamp != null)
                {
                    string format = DateTimeFormatInfo.InvariantInfo.UniversalSortableDateTimePattern.Replace(" ", "T");
                    builder.TimeStamp = DateTime.ParseExact(stamp, format, null);
                }
                Session.AddMessageToChat(chat, builder.ToMessage());
            }
        }
Exemple #11
0
        void PrintGroupChatPresence(XmppGroupChatModel chat, XmppPersonModel person, Presence pres)
        {
            Jid jid = pres.From;
            XmppResourceModel resource;
            if (person.MucResources.TryGetValue(jid.Resource??"", out resource)) {
                if (resource.Presence.Show == pres.Show
                    && resource.Presence.Status == pres.Status
                    && resource.Presence.Last == pres.Last
                    && resource.Presence.XDelay == pres.XDelay
                    && resource.Presence.Priority == pres.Priority
                    && resource.Presence.Nickname == pres.Nickname
                    && resource.Presence.Type == pres.Type
                    ) {
                    // presence didn't change enough to warrent a display message -> abort
                    return;
                }
            }

            var msg = CreatePresenceUpdateMessage(person.Jid, person, pres);
            Session.AddMessageToChat(chat, msg);
            // clone directly to muc person chat
            // don't care about real jid, that has its own presence packets
            var personChat = Session.GetChat(jid, ChatType.Person, this);
            if (personChat != null) {
                Session.AddMessageToChat(personChat, msg);
            }
        }
Exemple #12
0
        void OnGroupChatPresence(XmppGroupChatModel chat, Presence pres)
        {
            Jid jid = pres.From;
            XmppPersonModel person;
            // check whether we know the real jid of this muc user
            if (pres.MucUser != null &&
                pres.MucUser.Item != null &&
                pres.MucUser.Item.Jid != null ) {
                string nick = pres.From.Resource;
                if (!string.IsNullOrEmpty(pres.MucUser.Item.Nickname)) {
                    nick = pres.MucUser.Item.Nickname;
                }
                person = GetOrCreateContact(pres.MucUser.Item.Jid.Bare, nick);
            } else {
                // we do not know the real jid of this user, don't add it to our local roster
                // BUG? pres.From.Resource can be null?
                person = new XmppPersonModel(jid, pres.From.Resource, this);
            }
            person.GetOrCreateMucResource(jid).Presence = pres;
            PrintGroupChatPresence(chat, person, pres);
            switch (pres.Type) {
                case PresenceType.available:
                    // don't do anything if the contact already exists
                    if (chat.UnsafePersons.ContainsKey(person.ID)) {
                        return;
                    }
                    // is the chat synced? add the new contact the regular way
                    if (chat.IsSynced) {
                        Session.AddPersonToGroupChat(chat, person.ToPersonModel());
                        return;
                    }

                    chat.UnsafePersons.Add(person.ID, person.ToPersonModel());

                    // did I join? then the chat roster is fully received
                    if (pres.From.Resource == chat.OwnNickname) {
                        // HACK: lower probability of sync race condition swallowing messages
                        ThreadPool.QueueUserWorkItem(delegate {
                            Thread.Sleep(1000);
                            lock (this) {
                                if (IsDisposed) {
                                    return;
                                }
                                chat.IsSynced = true;
                                Session.SyncChat(chat);
                                Session.EnableChat(chat);
                            }
                        });
                    }
                    break;
                case PresenceType.unavailable:
                    Session.RemovePersonFromGroupChat(chat, person.ToPersonModel());
                    // did I leave? then I "probably" left the room
                    if (pres.From.Resource == chat.OwnNickname) {
                        Session.RemoveChat(chat);
                    }
                    break;
                case PresenceType.error:
                    if (pres.Error == null) break;
                    switch (pres.Error.Type) {
                        case ErrorType.cancel:
                            switch (pres.Error.Condition) {
                                case ErrorCondition.Conflict:
                                    // nickname already in use
                                    // autorejoin with _ appended to nickname
                                    JoinRoom(chat.ID, chat.OwnNickname + "_", chat.Password);
                                    break;
                            }
                            break;
                    }
                    break;
            }
        }