private static LinkedList <SignalMessage> InsertIdentityChangedMessages(string number)
        {
            long now = Util.CurrentTimeMillis();
            LinkedList <SignalMessage> messages = new LinkedList <SignalMessage>();

            using (var ctx = new SignalDBContext())
            {
                SignalContact contact = SignalDBContext.GetSignalContactByThreadId(ctx, number);
                if (contact != null)
                {
                    string        str = $"Your safety numbers with {contact.ThreadDisplayName} have changed.";
                    SignalMessage msg = new SignalMessage()
                    {
                        Author            = contact,
                        ComposedTimestamp = now,
                        ReceivedTimestamp = now,
                        Direction         = SignalMessageDirection.Incoming,
                        Type       = SignalMessageType.IdentityKeyChange,
                        ThreadId   = contact.ThreadId,
                        ThreadGuid = contact.ThreadGuid,
                        Content    = new SignalMessageContent()
                        {
                            Content = str
                        }
                    };
                    contact.LastMessage    = msg;
                    contact.MessagesCount += 1;
                    contact.UnreadCount   += 1;
                    ctx.Messages.Add(msg);
                    messages.AddLast(msg);
                    var groups = ctx.GroupMemberships
                                 .Where(gm => gm.ContactId == contact.Id)
                                 .Include(gm => gm.Group);
                    foreach (var gm in groups)
                    {
                        msg = new SignalMessage()
                        {
                            Author            = contact,
                            ComposedTimestamp = now,
                            ReceivedTimestamp = now,
                            Direction         = SignalMessageDirection.Incoming,
                            Type       = SignalMessageType.IdentityKeyChange,
                            ThreadId   = gm.Group.ThreadId,
                            ThreadGuid = gm.Group.ThreadGuid,
                            Content    = new SignalMessageContent()
                            {
                                Content = str
                            }
                        };
                        gm.Group.LastMessage    = msg;
                        gm.Group.MessagesCount += 1;
                        gm.Group.UnreadCount   += 1;
                        ctx.Messages.Add(msg);
                        messages.AddLast(msg);
                    }
                }
                ctx.SaveChanges();
            }
            return(messages);
        }
Example #2
0
        internal async void AddButton_Click(object sender, RoutedEventArgs e)
        {
            if (UIEnabled)
            {
                UIEnabled = false;
                Debug.WriteLine("creating contact {0} ({1})", ContactName, ContactNumber);
                SignalContact contact = new SignalContact()
                {
                    ThreadDisplayName   = ContactName,
                    ThreadId            = ContactNumber,
                    CanReceive          = true,
                    AvatarFile          = null,
                    LastActiveTimestamp = 0,
                    Draft       = null,
                    Color       = "red",
                    UnreadCount = 0
                };
                ContactName   = "";
                ContactNumber = "";
                await Task.Run(() =>
                {
                    SignalDBContext.InsertOrUpdateContactLocked(contact, MainPageVM);
                });

                UIEnabled = true;
            }
        }
 private void UpdateHeader(SignalConversation thread)
 {
     ThreadDisplayName = thread.ThreadDisplayName;
     ThreadUsername    = thread.ThreadId;
     if (thread is SignalContact)
     {
         SignalContact contact = (SignalContact)thread;
         HeaderBackground = Utils.GetBrushFromColor(contact.Color);
         if (ThreadUsername != ThreadDisplayName)
         {
             ThreadUsernameVisibility = Visibility.Visible;
             SeparatorVisibility      = Visibility.Visible;
         }
         else
         {
             ThreadUsernameVisibility = Visibility.Collapsed;
             SeparatorVisibility      = Visibility.Collapsed;
         }
     }
     else
     {
         HeaderBackground         = Utils.Blue;
         ThreadUsernameVisibility = Visibility.Collapsed;
         SeparatorVisibility      = Visibility.Collapsed;
     }
 }
Example #4
0
        public static SignalContact GetOrCreateContactLocked(string username, long timestamp)
        {
            SignalContact contact;

            lock (DBLock)
            {
                using (var ctx = new SignalDBContext())
                {
                    contact = ctx.Contacts
                              .Where(c => c.ThreadId == username)
                              .SingleOrDefault();
                    if (contact == null)
                    {
                        contact = new SignalContact()
                        {
                            ThreadId            = username,
                            ThreadDisplayName   = username,
                            CanReceive          = true,
                            LastActiveTimestamp = timestamp,
                            Color = null //Utils.CalculateDefaultColor(username)
                        };
                        ctx.Contacts.Add(contact);
                        ctx.SaveChanges();
                    }
                }
            }
            return(contact);
        }
Example #5
0
        public void UpdateBlockedContactElement()
        {
            if (Model != null)
            {
                SignalContact contact = (SignalContact)Model;
                FillBrush = contact.Color != null?Utils.GetBrushFromColor((contact.Color)) :
                                Utils.GetBrushFromColor(Utils.CalculateDefaultColor(Model.ThreadDisplayName));

                ConversationDisplayName.Text = Model.ThreadDisplayName;
                Initials    = Utils.GetInitials(Model.ThreadDisplayName);
                LastMessage = null;
            }
        }
 private async Task AddContact(string name, string number)
 {
     Debug.WriteLine("creating contact {0} ({1})", name, number);
     SignalContact contact = new SignalContact()
     {
         ThreadDisplayName   = name,
         ThreadId            = number,
         CanReceive          = true,
         AvatarFile          = null,
         LastActiveTimestamp = 0,
         Draft       = null,
         Color       = Utils.CalculateDefaultColor(name),
         UnreadCount = 0
     };
     await Task.Run(() =>
     {
         SignalDBContext.InsertOrUpdateContactLocked(contact, MainPageVM);
     });
 }
 private async Task AddContact(string name, string number)
 {
     Debug.WriteLine("creating contact {0} ({1})", name, number);
     SignalContact contact = new SignalContact()
     {
         ThreadDisplayName   = name,
         ThreadId            = number,
         CanReceive          = true,
         AvatarFile          = null,
         LastActiveTimestamp = 0,
         Draft       = null,
         Color       = Utils.CalculateDefaultColor(name),
         UnreadCount = 0
     };
     await Task.Run(() =>
     {
         //TODO inform UI
     });
 }
Example #8
0
        public static void InsertOrUpdateContactLocked(SignalContact contact, MainPageViewModel mpvm)
        {
            bool is_new = false;

            lock (DBLock)
            {
                using (var ctx = new SignalDBContext())
                {
                    var c = ctx.Contacts.SingleOrDefault(b => b.ThreadId == contact.ThreadId);
                    if (c == null)
                    {
                        is_new = true;
                        ctx.Contacts.Add(contact);
                    }
                    else
                    {
                        c.Color             = contact.Color;
                        c.ThreadId          = contact.ThreadId;
                        c.ThreadDisplayName = contact.ThreadDisplayName;
                        c.CanReceive        = contact.CanReceive;
                        c.AvatarFile        = contact.AvatarFile;
                        c.Draft             = contact.Draft;
                        c.UnreadCount       = contact.UnreadCount;
                    }
                    ctx.SaveChanges();
                }
                if (is_new)
                {
                    Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
                    {
                        mpvm.AddThread(contact);
                    }).AsTask().Wait();
                }
                else
                {
                    Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
                    {
                        mpvm.UIUpdateThread(contact);
                    }).AsTask().Wait();
                }
            }
        }
 private async Task AddContact(string name, string number, Guid?guid)
 {
     Debug.WriteLine("creating contact {0} ({1})", name, number);
     SignalContact contact = new SignalContact()
     {
         ThreadDisplayName   = name,
         ThreadId            = number,
         ThreadGuid          = guid,
         CanReceive          = true,
         AvatarFile          = null,
         LastActiveTimestamp = 0,
         Draft       = null,
         Color       = Utils.CalculateDefaultColor(name),
         UnreadCount = 0
     };
     await Task.Run(() =>
     {
         App.Handle.SaveAndDispatchSignalConversation(contact, null);
     });
 }
Example #10
0
        public static SignalContact GetOrCreateContactLocked(string username, long timestamp, MainPageViewModel mpvm)
        {
            SignalContact contact;
            bool          is_new = false;

            lock (DBLock)
            {
                using (var ctx = new SignalDBContext())
                {
                    contact = ctx.Contacts
                              .Where(c => c.ThreadId == username)
                              .SingleOrDefault();
                    if (contact == null)
                    {
                        is_new  = true;
                        contact = new SignalContact()
                        {
                            ThreadId            = username,
                            ThreadDisplayName   = username,
                            CanReceive          = true,
                            LastActiveTimestamp = timestamp,
                            Color = Utils.Colors[Utils.CalculateDefaultColorIndex(username)]
                        };
                        ctx.Contacts.Add(contact);
                        ctx.SaveChanges();
                    }
                }
                if (is_new)
                {
                    Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
                    {
                        mpvm.AddThread(contact);
                    }).AsTask().Wait();
                }
            }
            return(contact);
        }
Example #11
0
        public static LinkedList <SignalMessage> InsertIdentityChangedMessages(string number)
        {
            long now = Util.CurrentTimeMillis();
            LinkedList <SignalMessage> messages = new LinkedList <SignalMessage>();

            lock (DBLock)
            {
                using (var ctx = new SignalDBContext())
                {
                    SignalContact contact = ctx.Contacts
                                            .Where(c => c.ThreadId == number)
                                            .SingleOrDefault();
                    if (contact != null)
                    {
                        string        str = $"Your safety numbers with {contact.ThreadDisplayName} have changed.";
                        SignalMessage msg = new SignalMessage()
                        {
                            Author            = contact,
                            ComposedTimestamp = now,
                            ReceivedTimestamp = now,
                            Direction         = SignalMessageDirection.Incoming,
                            Type     = SignalMessageType.IdentityKeyChange,
                            ThreadId = contact.ThreadId,
                            Content  = new SignalMessageContent()
                            {
                                Content = str
                            }
                        };
                        contact.LastMessage    = msg;
                        contact.MessagesCount += 1;
                        ctx.Messages.Add(msg);
                        messages.AddLast(msg);
                        var groups = ctx.GroupMemberships
                                     .Where(gm => gm.ContactId == contact.Id)
                                     .Include(gm => gm.Group);
                        foreach (var gm in groups)
                        {
                            msg = new SignalMessage()
                            {
                                Author            = contact,
                                ComposedTimestamp = now,
                                ReceivedTimestamp = now,
                                Direction         = SignalMessageDirection.Incoming,
                                Type     = SignalMessageType.IdentityKeyChange,
                                ThreadId = gm.Group.ThreadId,
                                Content  = new SignalMessageContent()
                                {
                                    Content = str
                                }
                            };
                            gm.Group.LastMessage    = msg;
                            gm.Group.MessagesCount += 1;
                            ctx.Messages.Add(msg);
                            messages.AddLast(msg);
                        }
                    }
                    else
                    {
                        Debug.WriteLine("InsertIdentityChangedMessages for non-existing contact!");
                    }
                    ctx.SaveChanges();
                }
            }
            return(messages);
        }
Example #12
0
        private async Task HandleGroupLeaveMessage(SignalServiceEnvelope envelope, SignalServiceContent content, SignalServiceDataMessage dataMessage, bool isSync, long timestamp)
        {
            SignalServiceGroup sentGroup = dataMessage.Group;

            if (sentGroup != null)
            {
                string      groupid = Base64.EncodeBytes(sentGroup.GroupId);
                SignalGroup group   = await SignalDBContext.GetOrCreateGroupLocked(groupid, 0);

                if (isSync)
                {
                    SignalContact author = await SignalDBContext.GetOrCreateContactLocked(envelope.GetSource(), 0);

                    SignalMessage sm = new SignalMessage()
                    {
                        Direction = SignalMessageDirection.Incoming,
                        Type      = SignalMessageType.GroupLeave,
                        Status    = SignalMessageStatus.Received,
                        Author    = author,
                        Content   = new SignalMessageContent()
                        {
                            Content = $"You have left the group."
                        },
                        ThreadId          = groupid,
                        DeviceId          = (uint)envelope.GetSourceDevice(),
                        Receipts          = 0,
                        ComposedTimestamp = envelope.GetTimestamp(),
                        ReceivedTimestamp = timestamp,
                    };
                    SignalConversation updatedConversation = SignalDBContext.RemoveMemberFromGroup(groupid, author, sm);
                    await SignalLibHandle.Instance.DispatchAddOrUpdateConversation(updatedConversation, sm);
                }
                else
                {
                    SignalContact author = await SignalDBContext.GetOrCreateContactLocked(envelope.GetSource(), 0);

                    SignalMessage sm = new SignalMessage()
                    {
                        Direction = SignalMessageDirection.Incoming,
                        Type      = SignalMessageType.GroupLeave,
                        Status    = SignalMessageStatus.Received,
                        Author    = author,
                        Content   = new SignalMessageContent()
                        {
                            Content = $"{author.ThreadDisplayName} has left the group."
                        },
                        ThreadId          = groupid,
                        DeviceId          = (uint)envelope.GetSourceDevice(),
                        Receipts          = 0,
                        ComposedTimestamp = envelope.GetTimestamp(),
                        ReceivedTimestamp = timestamp,
                    };
                    SignalConversation updatedConversation = SignalDBContext.RemoveMemberFromGroup(groupid, author, sm);
                    await SignalLibHandle.Instance.DispatchAddOrUpdateConversation(updatedConversation, sm);
                }
            }
            else
            {
                Logger.LogError("HandleGroupLeaveMessage() received group update without group info");
            }
        }
Example #13
0
        private async Task HandleMessage(SignalServiceEnvelope envelope)
        {
            var  cipher    = new SignalServiceCipher(new SignalServiceAddress(SignalLibHandle.Instance.Store.Username), new Store());
            var  content   = cipher.Decrypt(envelope);
            long timestamp = Util.CurrentTimeMillis();

            if (content.Message != null)
            {
                SignalServiceDataMessage message = content.Message;
                if (message.EndSession)
                {
                    await HandleSessionResetMessage(envelope, content, message, false, timestamp);
                }
                else if (message.IsGroupUpdate())
                {
                    if (message.Group.Type == SignalServiceGroup.GroupType.UPDATE)
                    {
                        await HandleGroupUpdateMessage(envelope, content, message, false, timestamp);
                    }
                    else if (message.Group.Type == SignalServiceGroup.GroupType.QUIT)
                    {
                        await HandleGroupLeaveMessage(envelope, content, message, false, timestamp);
                    }
                    else if (message.Group.Type == SignalServiceGroup.GroupType.REQUEST_INFO)
                    {
                        Logger.LogWarning("Received REQUEST_INFO request");
                    }
                }
                else if (message.ExpirationUpdate)
                {
                    await HandleExpirationUpdateMessage(envelope, content, message, false, timestamp);
                }
                else
                {
                    await HandleSignalMessage(envelope, content, message, false, timestamp);
                }
            }
            else if (content.SynchronizeMessage != null)
            {
                if (content.SynchronizeMessage.Sent != null)
                {
                    var syncMessage = content.SynchronizeMessage.Sent;
                    var dataMessage = syncMessage.Message;

                    if (dataMessage.EndSession)
                    {
                        await HandleSessionResetMessage(envelope, content, dataMessage, true, timestamp);
                    }
                    else if (dataMessage.IsGroupUpdate())
                    {
                        if (dataMessage.Group.Type == SignalServiceGroup.GroupType.UPDATE)
                        {
                            await HandleGroupUpdateMessage(envelope, content, dataMessage, true, timestamp);
                        }
                        else if (dataMessage.Group.Type == SignalServiceGroup.GroupType.QUIT)
                        {
                            await HandleGroupLeaveMessage(envelope, content, dataMessage, true, timestamp);
                        }
                        else if (dataMessage.Group.Type == SignalServiceGroup.GroupType.REQUEST_INFO)
                        {
                            Logger.LogWarning("Received synced REQUEST_INFO request");
                        }
                    }
                    else if (dataMessage.ExpirationUpdate)
                    {
                        await HandleExpirationUpdateMessage(envelope, content, dataMessage, true, timestamp);
                    }
                    else
                    {
                        await HandleSignalMessage(envelope, content, dataMessage, true, timestamp);
                    }
                }
                else if (content.SynchronizeMessage.Reads != null)
                {
                    var readMessages = content.SynchronizeMessage.Reads;
                    foreach (var readMessage in readMessages)
                    {
                        try
                        {
                            await HandleSyncedReadMessage(readMessage);
                        }
                        catch (Exception e)
                        {
                            Logger.LogError("HandleReadMessage failed: {0}\n{1}", e.Message, e.StackTrace);
                        }
                    }
                }
                else if (content.SynchronizeMessage.BlockedList != null)
                {
                    List <string> blockedNumbers = content.SynchronizeMessage.BlockedList.Numbers;
                    await HandleBlockedNumbers(blockedNumbers);
                }
                else if (content.SynchronizeMessage.Groups != null)
                {
                    Logger.LogInformation("HandleMessage() handling groups sync message from device {0}", envelope.GetSourceDevice());
                    int read;
                    var avatarBuffer = new byte[4096];
                    var groups       = content.SynchronizeMessage.Groups;
                    using (var tmpFile = LibUtils.CreateTmpFile("groups_sync"))
                    {
                        var plaintextStream = await MessageReceiver.RetrieveAttachment(Token, groups.AsPointer(), tmpFile, 10000, null);

                        var         deviceGroupsStream = new DeviceGroupsInputStream(plaintextStream);
                        var         groupsList         = new List <(SignalGroup, IList <string>)>();
                        DeviceGroup g;
                        while ((g = deviceGroupsStream.Read()) != null)
                        {
                            if (g.Avatar != null)
                            {
                                SignalServiceAttachmentStream ssas = g.Avatar.AsStream();
                                while ((read = ssas.InputStream.Read(avatarBuffer, 0, avatarBuffer.Length)) > 0)
                                {
                                }
                            }
                            var group = new SignalGroup()
                            {
                                ThreadDisplayName = g.Name,
                                ThreadId          = Base64.EncodeBytes(g.Id),
                                GroupMemberships  = new List <GroupMembership>(),
                                CanReceive        = true,
                                ExpiresInSeconds  = g.ExpirationTimer != null ? g.ExpirationTimer.Value : 0
                            };
                            groupsList.Add((group, g.Members));
                        }
                        List <SignalConversation> dbGroups = await SignalDBContext.InsertOrUpdateGroups(groupsList);

                        await SignalLibHandle.Instance.DispatchAddOrUpdateConversations(dbGroups);
                    }
                }
                else if (content.SynchronizeMessage.Contacts != null && content.SynchronizeMessage.Contacts.Complete) //TODO incomplete updates
                {
                    Logger.LogInformation("HandleMessage() handling contacts sync message from device {0}", envelope.GetSourceDevice());
                    int             read;
                    var             avatarBuffer = new byte[4096];
                    ContactsMessage contacts     = content.SynchronizeMessage.Contacts;
                    using (var tmpFile = LibUtils.CreateTmpFile("contacts_sync"))
                    {
                        var plaintextStream = await MessageReceiver.RetrieveAttachment(Token, contacts.Contacts.AsPointer(), tmpFile, 10000, null);

                        var deviceContactsStream          = new DeviceContactsInputStream(plaintextStream);
                        List <SignalContact> contactsList = new List <SignalContact>();
                        DeviceContact        c;
                        while ((c = deviceContactsStream.Read()) != null)
                        {
                            if (c.Avatar != null)
                            {
                                SignalServiceAttachmentStream ssas = c.Avatar.AsStream();
                                while ((read = ssas.InputStream.Read(avatarBuffer, 0, avatarBuffer.Length)) > 0)
                                {
                                }
                            }
                            SignalContact contact = new SignalContact()
                            {
                                ThreadDisplayName = c.Name,
                                ThreadId          = c.Number,
                                Color             = c.Color,
                                CanReceive        = true,
                                ExpiresInSeconds  = c.ExpirationTimer != null ? c.ExpirationTimer.Value : 0
                            };
                            contactsList.Add(contact);
                        }
                        var dbContacts = SignalDBContext.InsertOrUpdateContacts(contactsList);
                        await SignalLibHandle.Instance.DispatchAddOrUpdateConversations(dbContacts);
                    }
                }
            }
            else if (content.ReadMessage != null)
            {
                SignalServiceReceiptMessage receiptMessage = content.ReadMessage;
                Logger.LogTrace("HandleMessage() received ReceiptMessage (type={0}, when={1})", receiptMessage.ReceiptType, receiptMessage.When);
            }
            else
            {
                //TODO callmessages
                Logger.LogWarning("HandleMessage() received unrecognized message");
            }
        }