public static void sendFileTransferCompleted(byte[] sender, string uid) { Friend friend = FriendList.getFriend(sender); if (friend == null) { return; } SpixiMessage spixi_message = new SpixiMessage(SpixiMessageCode.fileFullyReceived, Crypto.stringToHash(uid)); StreamMessage message = new StreamMessage(); message.type = StreamMessageCode.data; message.recipient = friend.walletAddress; message.sender = Node.walletStorage.getPrimaryAddress(); message.transaction = new byte[1]; message.sigdata = new byte[1]; message.data = spixi_message.getBytes(); StreamProcessor.sendMessage(friend, message, true, true, false); }
private void onSend() { string msgId = Crypto.hashToString(requestMsg.id); // send tx details to the request if (!requestMsg.message.StartsWith(":")) { // Create an ixian transaction and send it to the dlt network byte[] to = friend.walletAddress; IxiNumber amounti = new IxiNumber(amount); IxiNumber fee = ConsensusConfig.transactionPrice; byte[] from = Node.walletStorage.getPrimaryAddress(); byte[] pubKey = Node.walletStorage.getPrimaryPublicKey(); Transaction transaction = new Transaction((int)Transaction.Type.Normal, amount, fee, to, from, null, pubKey, IxianHandler.getLastBlockHeight()); NetworkClientManager.broadcastData(new char[] { 'M' }, ProtocolMessageCode.newTransaction, transaction.getBytes(), null); SpixiMessage spixi_message = new SpixiMessage(null, SpixiMessageCode.requestFundsResponse, Encoding.UTF8.GetBytes(msgId + ":" + transaction.id)); requestMsg.message = ":" + transaction.id; StreamMessage message = new StreamMessage(); message.type = StreamMessageCode.info; message.recipient = to; message.sender = Node.walletStorage.getPrimaryAddress(); message.transaction = new byte[1]; message.sigdata = new byte[1]; message.data = spixi_message.getBytes(); StreamProcessor.sendMessage(friend, message); Node.localStorage.writeMessagesFile(friend.walletAddress, friend.messages); } Navigation.PopAsync(Config.defaultXamarinAnimations); }
private void onRequest(string recipient, string amount) { byte[] recipient_bytes = Base58Check.Base58CheckEncoding.DecodePlain(recipient); Friend friend = FriendList.getFriend(recipient_bytes); if (friend != null && (new IxiNumber(amount)) > 0) { FriendMessage friend_message = FriendList.addMessageWithType(null, FriendMessageType.requestFunds, friend.walletAddress, 0, amount, true); SpixiMessage spixi_message = new SpixiMessage(SpixiMessageCode.requestFunds, Encoding.UTF8.GetBytes(amount)); StreamMessage message = new StreamMessage(); message.type = StreamMessageCode.info; message.recipient = Base58Check.Base58CheckEncoding.DecodePlain(recipient); message.sender = IxianHandler.getWalletStorage().getPrimaryAddress(); message.data = spixi_message.getBytes(); message.id = friend_message.id; StreamProcessor.sendMessage(friend, message); Navigation.PopAsync(Config.defaultXamarinAnimations); }// else error? }
private void updateMessageReadStatus(FriendMessage message) { if (!message.read && !message.localSender && App.isInForeground) { Node.shouldRefreshContacts = true; message.read = true; Node.localStorage.writeMessages(friend.walletAddress, friend.messages); if (!friend.bot) { // Send read confirmation StreamMessage msg_received = new StreamMessage(); msg_received.type = StreamMessageCode.info; msg_received.sender = IxianHandler.getWalletStorage().getPrimaryAddress(); msg_received.recipient = friend.walletAddress; msg_received.data = new SpixiMessage(SpixiMessageCode.msgRead, message.id).getBytes(); msg_received.transaction = new byte[1]; msg_received.sigdata = new byte[1]; StreamProcessor.sendMessage(friend, msg_received, true, false, false); } } }
public static void acceptFile(Friend friend, string uid) { using (MemoryStream m = new MemoryStream()) { using (BinaryWriter writer = new BinaryWriter(m)) { writer.Write(uid); } FileTransfer transfer = getIncomingTransfer(uid); if (transfer == null) { return; } Logging.info("Accepting file {0}", transfer.fileName); transfer.lastTimeStamp = Clock.getTimestamp(); transfer.filePath = String.Format("{0}/Downloads/{1}", Config.spixiUserFolder, transfer.fileName); transfer.fileStream = File.Create(transfer.filePath); transfer.fileStream.SetLength((long)transfer.fileSize); SpixiMessage spixi_message = new SpixiMessage(SpixiMessageCode.acceptFile, m.ToArray()); StreamMessage message = new StreamMessage(); message.type = StreamMessageCode.data; message.recipient = friend.walletAddress; message.sender = Node.walletStorage.getPrimaryAddress(); message.transaction = new byte[1]; message.sigdata = new byte[1]; message.data = spixi_message.getBytes(); StreamProcessor.sendMessage(friend, message); } }
public async void onSend(string str) { if (str.Length < 1) { return; } await Task.Run(async() => { // TODOSPIXI /* // Send the message to the S2 nodes * byte[] recipient_address = friend.wallet_address; * byte[] encrypted_message = StreamProcessor.prepareSpixiMessage(SpixiMessageCode.chat, str, friend.pubkey); * // CryptoManager.lib.encryptData(Encoding.UTF8.GetBytes(string_to_send), friend.pubkey); * * // Check the relay ip * string relayip = friend.getRelayIP(); * if (relayip == null) * { * Logging.warn("No relay node to send message to!"); * return; * } * if (relayip.Equals(node_ip, StringComparison.Ordinal) == false) * { * * node_ip = relayip; * // Connect to the contact's S2 relay first * NetworkClientManager.connectToStreamNode(relayip); * * // TODO: optimize this * while (NetworkClientManager.isNodeConnected(relayip) == false) * { * * } * } * * Message message = new Message(); * message.recipientAddress = recipient_address; * message.data = encrypted_message; * * StreamProcessor.sendMessage(message, node_ip);*/ // store the message and display it FriendMessage friend_message = FriendList.addMessageWithType(null, FriendMessageType.standard, friend.walletAddress, str, true); // Finally, clear the input field Utils.sendUiCommand(webView, "clearInput"); // Send the message SpixiMessage spixi_message = new SpixiMessage(SpixiMessageCode.chat, Encoding.UTF8.GetBytes(str)); StreamMessage message = new StreamMessage(); message.type = StreamMessageCode.data; message.recipient = friend.walletAddress; message.sender = Node.walletStorage.getPrimaryAddress(); message.transaction = new byte[1]; message.sigdata = new byte[1]; message.data = spixi_message.getBytes(); message.id = friend_message.id; if (friend.bot) { message.encryptionType = StreamMessageEncryptionCode.none; message.sign(IxianHandler.getWalletStorage().getPrimaryPrivateKey()); } StreamProcessor.sendMessage(friend, message); }); }
public static FriendMessage addMessageWithType(byte[] id, FriendMessageType type, byte[] wallet_address, string message, bool local_sender = false, byte[] sender_address = null) { foreach (Friend friend in friends) { if (!friend.walletAddress.SequenceEqual(wallet_address)) { continue; } Node.shouldRefreshContacts = true; if (!friend.online) { using (MemoryStream mw = new MemoryStream()) { using (BinaryWriter writer = new BinaryWriter(mw)) { writer.Write(wallet_address.Length); writer.Write(wallet_address); CoreProtocolMessage.broadcastProtocolMessage(new char[] { 'M' }, ProtocolMessageCode.getPresence, mw.ToArray(), null); } } } string sender_nick = ""; if (friend.bot) { if (!local_sender) { if (friend.contacts.ContainsKey(sender_address)) { sender_nick = friend.contacts[sender_address].nick; } else { StreamProcessor.requestNickname(friend, sender_address); } } } else { sender_nick = friend.nickname; } // TODO: message date should be fetched, not generated here FriendMessage friend_message = new FriendMessage(id, message, Clock.getTimestamp(), local_sender, type, sender_address, sender_nick); if (friend.bot && local_sender) { friend_message.read = true; } friend.messages.Add(friend_message); // If a chat page is visible, insert the message directly if (friend.chat_page != null) { friend.chat_page.insertMessage(friend_message); } else { //CrossLocalNotifications.Current.Show(string.Format("New message from {0}",friend.nickname), message, 100, DateTime.Now.AddSeconds(1)); } // Write to chat history Node.localStorage.writeMessagesFile(wallet_address, friend.messages); return(friend_message); } // No matching contact found in friendlist // Add the contact, then issue the message again // TODO: need to fetch the stage 1 public key somehow here // Ignoring such messages for now //addFriend(wallet_address, "pubkey", "Unknown"); //addMessage(wallet_address, message); return(null); }
private void onNavigating(object sender, WebNavigatingEventArgs e) { string current_url = HttpUtility.UrlDecode(e.Url); if (onNavigatingGlobal(current_url)) { e.Cancel = true; return; } if (current_url.Equals("ixian:onload", StringComparison.Ordinal)) { onLoaded(); } else if (current_url.Equals("ixian:wallet", StringComparison.Ordinal)) { // Deprecated } else if (current_url.Equals("ixian:quickscan", StringComparison.Ordinal)) { ICustomQRScanner scanner = DependencyService.Get <ICustomQRScanner>(); if (scanner != null && scanner.useCustomQRScanner()) { Logging.error("Custom scanner not implemented"); e.Cancel = true; return; } quickScan(); } else if (current_url.Contains("ixian:qrresult:")) { string[] split = current_url.Split(new string[] { "ixian:qrresult:" }, StringSplitOptions.None); string result = split[1]; processQRResult(result); e.Cancel = true; return; } else if (current_url.Equals("ixian:newchat", StringComparison.Ordinal)) { newChat(); } else if (current_url.Equals("ixian:newcontact", StringComparison.Ordinal)) { Navigation.PushAsync(new ContactNewPage(), Config.defaultXamarinAnimations); } else if (current_url.Equals("ixian:sendixi", StringComparison.Ordinal)) { Navigation.PushAsync(new WalletSendPage(), Config.defaultXamarinAnimations); } else if (current_url.Equals("ixian:receiveixi", StringComparison.Ordinal)) { Navigation.PushAsync(new WalletReceivePage(), Config.defaultXamarinAnimations); } else if (current_url.Equals("ixian:wixi", StringComparison.Ordinal)) { Navigation.PushAsync(new WIXISendPage(), Config.defaultXamarinAnimations); } else if (current_url.Equals("ixian:avatar", StringComparison.Ordinal)) { //onChangeAvatarAsync(sender, e); } else if (current_url.Equals("ixian:settings", StringComparison.Ordinal)) { onSettings(sender, e); } else if (current_url.Equals("ixian:address", StringComparison.Ordinal)) { Navigation.PushAsync(new MyAddressPage(), Config.defaultXamarinAnimations); } else if (current_url.Equals("ixian:lock", StringComparison.Ordinal)) { // prepBackground(); Navigation.PushAsync(new SetLockPage(), Config.defaultXamarinAnimations); } else if (current_url.Equals("ixian:activity", StringComparison.Ordinal)) { // TODO show wallet activity screen } else if (current_url.Equals("ixian:about", StringComparison.Ordinal)) { #pragma warning disable CS0618 // Type or member is obsolete Device.OpenUri(new Uri(Config.aboutUrl)); #pragma warning restore CS0618 // Type or member is obsolete } else if (current_url.Equals("ixian:guide", StringComparison.Ordinal)) { #pragma warning disable CS0618 // Type or member is obsolete Device.OpenUri(new Uri(Config.guideUrl)); #pragma warning restore CS0618 // Type or member is obsolete } else if (current_url.Equals("ixian:backup", StringComparison.Ordinal)) { Navigation.PushAsync(new BackupPage(), Config.defaultXamarinAnimations); } else if (current_url.Equals("ixian:encpass", StringComparison.Ordinal)) { Navigation.PushAsync(new EncryptionPassword(), Config.defaultXamarinAnimations); } else if (current_url.Contains("ixian:chat:")) { string[] split = current_url.Split(new string[] { "ixian:chat:" }, StringSplitOptions.None); string id = split[1]; onChat(id, e); } else if (current_url.Contains("ixian:details:")) { string[] split = current_url.Split(new string[] { "ixian:details:" }, StringSplitOptions.None); string id = split[1]; // TODO: handle exceptions byte[] id_bytes = Base58Check.Base58CheckEncoding.DecodePlain(id); Friend friend = FriendList.getFriend(id_bytes); if (friend == null) { e.Cancel = true; return; } Navigation.PushAsync(new ContactDetails(friend), Config.defaultXamarinAnimations); } else if (current_url.Contains("ixian:txdetails:")) { string[] split = current_url.Split(new string[] { "ixian:txdetails:" }, StringSplitOptions.None); string id = split[1]; byte[] b_txid = Transaction.txIdLegacyToV8(id); Transaction transaction = null; foreach (Transaction tx in TransactionCache.transactions) { if (tx.id.SequenceEqual(b_txid)) { transaction = tx; break; } } if (transaction == null) { foreach (Transaction tx in TransactionCache.unconfirmedTransactions) { if (tx.id.SequenceEqual(b_txid)) { transaction = tx; break; } } if (transaction == null) { e.Cancel = true; return; } } Navigation.PushAsync(new WalletSentPage(transaction), Config.defaultXamarinAnimations); } else if (current_url.Contains("ixian:tab:")) { currentTab = current_url.Split(new string[] { "ixian:tab:" }, StringSplitOptions.None)[1]; } else if (current_url.Equals("ixian:apps", StringComparison.Ordinal)) { // prepBackground(); Navigation.PushAsync(new AppsPage(), Config.defaultXamarinAnimations); } else if (current_url.Equals("ixian:downloads", StringComparison.Ordinal)) { // prepBackground(); Navigation.PushAsync(new DownloadsPage(), Config.defaultXamarinAnimations); } else if (current_url.StartsWith("ixian:viewLog")) { // TODO perhaps move this whole functionality to Logging class and delete spixi.log.zip on start if exists if (File.Exists(Path.Combine(Config.spixiUserFolder, "spixi.log.zip"))) { File.Delete(Path.Combine(Config.spixiUserFolder, "spixi.log.zip")); } if (File.Exists(Path.Combine(Config.spixiUserFolder, "ixian.log.tmp"))) { File.Delete(Path.Combine(Config.spixiUserFolder, "ixian.log.tmp")); } File.Copy(Path.Combine(Config.spixiUserFolder, "ixian.log"), Path.Combine(Config.spixiUserFolder, "ixian.log.tmp")); using (ZipArchive archive = ZipFile.Open(Path.Combine(Config.spixiUserFolder, "spixi.log.zip"), ZipArchiveMode.Create)) { archive.CreateEntryFromFile(Path.Combine(Config.spixiUserFolder, "ixian.log.tmp"), "ixian.log"); if (File.Exists(Path.Combine(Config.spixiUserFolder, "ixian.0.log"))) { archive.CreateEntryFromFile(Path.Combine(Config.spixiUserFolder, "ixian.0.log"), "ixian.0.log"); } } if (File.Exists(Path.Combine(Config.spixiUserFolder, "ixian.log.tmp"))) { File.Delete(Path.Combine(Config.spixiUserFolder, "ixian.log.tmp")); } DependencyService.Get <IFileOperations>().share(Path.Combine(Config.spixiUserFolder, "spixi.log.zip"), "Share Spixi Log File"); } else if (current_url.StartsWith("ixian:onboardingComplete")) { Application.Current.Properties["onboardingComplete"] = true; Application.Current.SavePropertiesAsync(); // Force-save properties for compatibility with WPF SpixiLocalization.addCustomString("OnboardingComplete", "true"); generatePage("index.html"); } else if (current_url.StartsWith("ixian:joinBot")) { Friend friend = FriendList.addFriend(Base58Check.Base58CheckEncoding.DecodePlain("419jmKRKVFcsjmwpDF1XSZ7j1fez6KWaekpiawHvrpyZ8TPVmH1v6bhT2wFc1uddV"), null, "Spixi Group Chat", null, null, 0); if (friend != null) { friend.save(); StreamProcessor.sendContactRequest(friend); } } else { // Otherwise it's just normal navigation e.Cancel = false; return; } e.Cancel = true; }
public static FriendMessage addMessageWithType(byte[] id, FriendMessageType type, byte[] wallet_address, int channel, string message, bool local_sender = false, byte[] sender_address = null, long timestamp = 0, bool fire_local_notification = true, int payable_data_len = 0) { Friend friend = getFriend(wallet_address); if (friend == null) { // No matching contact found in friendlist // Add the contact, then issue the message again? // TODO: need to fetch the stage 1 public key somehow here // Ignoring such messages for now //addFriend(wallet_address, "pubkey", "Unknown"); //addMessage(wallet_address, message); Logging.warn("Received message but contact isn't in our contact list."); return(null); } if (!friend.online) { using (MemoryStream mw = new MemoryStream()) { using (BinaryWriter writer = new BinaryWriter(mw)) { writer.WriteIxiVarInt(wallet_address.Length); writer.Write(wallet_address); CoreProtocolMessage.broadcastProtocolMessage(new char[] { 'M', 'H' }, ProtocolMessageCode.getPresence2, mw.ToArray(), null); } } } bool set_read = false; string sender_nick = ""; if (friend.bot && sender_address != null) { if (IxianHandler.getWalletStorage().isMyAddress(sender_address)) { if (!local_sender) { set_read = true; } local_sender = true; } if (!local_sender) { if (friend.users.hasUser(sender_address) && friend.users.getUser(sender_address).getNick() != "") { sender_nick = friend.users.getUser(sender_address).getNick(); } else { if (!friend.users.hasUser(sender_address) || friend.users.getUser(sender_address).publicKey == null) { StreamProcessor.requestBotUser(friend, sender_address); } } } } else { sender_nick = friend.nickname; } if (timestamp == 0) { timestamp = Clock.getTimestamp(); } FriendMessage friend_message = new FriendMessage(id, message, timestamp, local_sender, type, sender_address, sender_nick); friend_message.payableDataLen = payable_data_len; List <FriendMessage> messages = friend.getMessages(channel); if (messages == null) { Logging.warn("Message with id {0} was sent to invalid channel {1}.", Crypto.hashToString(id), channel); return(null); } lock (messages) { // TODO should be optimized if (id != null) { FriendMessage tmp_msg = messages.Find(x => x.id != null && x.id.SequenceEqual(id)); if (tmp_msg != null) { if (!tmp_msg.localSender) { Logging.warn("Message with id {0} was already in message list.", Crypto.hashToString(id)); } else { friend.setMessageRead(channel, id); } if (messages.Last() == tmp_msg) { friend.metaData.setLastMessage(tmp_msg, channel); friend.metaData.setLastReceivedMessageIds(tmp_msg.id, channel); friend.saveMetaData(); } return(null); } else { friend.metaData.setLastReceivedMessageIds(friend_message.id, channel); } } else if (!local_sender) { Logging.error("Message id sent by {0} is null!", Base58Check.Base58CheckEncoding.EncodePlain(friend.walletAddress)); return(null); } messages.Add(friend_message); } bool old_message = false; // Check if the message was sent before the friend was added to the contact list if (friend.addedTimestamp > friend_message.timestamp) { old_message = true; } if (set_read || old_message) { friend_message.confirmed = true; friend_message.read = true; } friend.metaData.setLastMessage(friend_message, channel); friend.saveMetaData(); // If a chat page is visible, insert the message directly if (friend.chat_page != null) { friend.chat_page.insertMessage(friend_message, channel); } else if (!set_read) { // Increase the unread counter if this is a new message if (!old_message) { friend.metaData.unreadMessageCount++; } friend.saveMetaData(); } UIHelpers.setContactStatus(friend.walletAddress, friend.online, friend.getUnreadMessageCount(), message, timestamp); // Only send alerts if this is a new message if (old_message == false) { // Send a local push notification if Spixi is not in the foreground if (fire_local_notification && !local_sender) { if (App.isInForeground == false || friend.chat_page == null) { // don't fire notification for nickname and avatar if (!friend_message.id.SequenceEqual(new byte[] { 4 }) && !friend_message.id.SequenceEqual(new byte[] { 5 })) { if (friend.bot == false || (friend.metaData.botInfo != null && friend.metaData.botInfo.sendNotification)) { DependencyService.Get <IPushService>().showLocalNotification("Spixi", "New Message", Base58Check.Base58CheckEncoding.EncodePlain(friend.walletAddress)); } } } } ISystemAlert alert = DependencyService.Get <ISystemAlert>(); if (alert != null) { alert.flash(); } } // Write to chat history Node.localStorage.requestWriteMessages(wallet_address, channel); return(friend_message); }
public void onCreateAccount(string nick, string pass) { // Generate the account on a different thread new Thread(() => { Thread.CurrentThread.IsBackground = true; // Aquire the wake lock bool wake_lock_sd = DependencyService.Get <IPowerManager>().AquireLock("screenDim"); bool wake_lock_p = DependencyService.Get <IPowerManager>().AquireLock("partial"); if (Node.generateWallet(pass)) { Node.start(); Node.localStorage.nickname = nick; Node.localStorage.writeAccountFile(); // TODO: encrypt the password Application.Current.Properties["walletpass"] = pass; Application.Current.SavePropertiesAsync(); // Force-save properties for compatibility with WPF // Release the wake lock if (wake_lock_sd) { DependencyService.Get <IPowerManager>().ReleaseLock("screenDim"); } if (wake_lock_p) { DependencyService.Get <IPowerManager>().ReleaseLock("partial"); } Device.BeginInvokeOnMainThread(() => { Navigation.PushAsync(HomePage.Instance(), Config.defaultXamarinAnimations); Navigation.RemovePage(this); }); Friend friend = FriendList.addFriend(Base58Check.Base58CheckEncoding.DecodePlain("419jmKRKVFcsjmwpDF1XSZ7j1fez6KWaekpiawHvrpyZ8TPVmH1v6bhT2wFc1uddV"), null, "Spixi Group Chat", null, null, 0); FriendList.saveToStorage(); StreamProcessor.sendContactRequest(friend); } else { // Release the wake lock if (wake_lock_sd) { DependencyService.Get <IPowerManager>().ReleaseLock("screenDim"); } if (wake_lock_p) { DependencyService.Get <IPowerManager>().ReleaseLock("partial"); } Device.BeginInvokeOnMainThread(() => { displaySpixiAlert("Error", "Cannot generate new wallet. Please try again.", "Ok"); }); return; } }).Start(); }
public void onSend(string str) { if (str.Length < 1) { return; } // TODOSPIXI /* // Send the message to the S2 nodes * byte[] recipient_address = friend.wallet_address; * byte[] encrypted_message = StreamProcessor.prepareSpixiMessage(SpixiMessageCode.chat, str, friend.pubkey); * // CryptoManager.lib.encryptData(Encoding.UTF8.GetBytes(string_to_send), friend.pubkey); * * // Check the relay ip * string relayip = friend.getRelayIP(); * if (relayip == null) * { * Logging.warn("No relay node to send message to!"); * return; * } * if (relayip.Equals(node_ip, StringComparison.Ordinal) == false) * { * * node_ip = relayip; * // Connect to the contact's S2 relay first * NetworkClientManager.connectToStreamNode(relayip); * * // TODO: optimize this * while (NetworkClientManager.isNodeConnected(relayip) == false) * { * * } * } * * Message message = new Message(); * message.recipientAddress = recipient_address; * message.data = encrypted_message; * * StreamProcessor.sendMessage(message, node_ip);*/ SpixiMessage spixi_message = new SpixiMessage(SpixiMessageCode.chat, Encoding.UTF8.GetBytes(str)); StreamMessage message = new StreamMessage(); message.type = StreamMessageCode.data; message.recipient = friend.walletAddress; message.sender = Node.walletStorage.getPrimaryAddress(); message.transaction = new byte[1]; message.sigdata = new byte[1]; message.data = spixi_message.getBytes(); string relayip = friend.searchForRelay(); StreamProcessor.sendMessage(message, relayip); // Finally, add the text bubble visually DateTime dt = DateTime.Now; FriendMessage msg = new FriendMessage(str, String.Format("{0:t}", dt), false); friend.messages.Add(msg); insertMessage(msg); // Finally, clear the input field webView.Eval("clearInput()"); }
public async Task onSendFile() { // Show file picker and send the file try { Stream stream = null; string fileName = null; string filePath = null; // Special case for iOS platform if (Device.RuntimePlatform == Device.iOS) { var picker_service = DependencyService.Get <IPicturePicker>(); SpixiImageData spixi_img_data = await picker_service.PickImageAsync(); stream = spixi_img_data.stream; if (stream == null) { return; } fileName = spixi_img_data.name; filePath = spixi_img_data.path; } else { FileData fileData = await CrossFilePicker.Current.PickFile(); if (fileData == null) { return; // User canceled file picking } stream = fileData.GetStream(); fileName = fileData.FileName; filePath = fileData.FilePath; } FileTransfer transfer = TransferManager.prepareFileTransfer(fileName, stream, filePath); Logging.info("File Transfer uid: " + transfer.uid); SpixiMessage spixi_message = new SpixiMessage(SpixiMessageCode.fileHeader, transfer.getBytes()); StreamMessage message = new StreamMessage(); message.type = StreamMessageCode.data; message.recipient = friend.walletAddress; message.sender = Node.walletStorage.getPrimaryAddress(); message.transaction = new byte[1]; message.sigdata = new byte[1]; message.data = spixi_message.getBytes(); StreamProcessor.sendMessage(friend, message); string message_data = string.Format("{0}:{1}", transfer.uid, transfer.fileName); // store the message and display it FriendMessage friend_message = FriendList.addMessageWithType(message.id, FriendMessageType.fileHeader, friend.walletAddress, message_data, true); friend_message.transferId = transfer.uid; friend_message.filePath = transfer.filePath; Node.localStorage.writeMessages(friend.walletAddress, friend.messages); } catch (Exception ex) { Logging.error("Exception choosing file: " + ex.ToString()); } }
public static bool sendFileData(Friend friend, string uid, ulong packet_number) { FileTransfer transfer = TransferManager.getOutgoingTransfer(uid); if (transfer == null) { return(false); } using (MemoryStream m = new MemoryStream()) { using (BinaryWriter writer = new BinaryWriter(m)) { writer.Write(uid); writer.Write(packet_number); Logging.info("Sending file packet #{0}", packet_number); byte[] data = transfer.getPacketData(packet_number); // Write the data if (data != null) { writer.Write(data.Length); writer.Write(data); } else { writer.Write(0); } } SpixiMessage spixi_message = new SpixiMessage(SpixiMessageCode.fileData, m.ToArray()); StreamMessage message = new StreamMessage(); message.type = StreamMessageCode.data; message.recipient = friend.walletAddress; message.sender = Node.walletStorage.getPrimaryAddress(); message.transaction = new byte[1]; message.sigdata = new byte[1]; message.data = spixi_message.getBytes(); StreamProcessor.sendMessage(friend, message, false, false, false); } if (friend.chat_page != null) { ulong totalPackets = transfer.fileSize / (ulong)Config.packetDataSize; ulong fp = 0; bool complete = false; if (totalPackets == packet_number) { fp = 100; complete = true; } else { fp = 100 / totalPackets * packet_number; } friend.chat_page.updateFile(uid, fp.ToString(), complete); } return(true); }
public static FriendMessage addMessageWithType(byte[] id, FriendMessageType type, byte[] wallet_address, string message, bool local_sender = false, byte[] sender_address = null, long timestamp = 0, bool fire_local_notification = true) { Friend friend = getFriend(wallet_address); if (friend == null) { // No matching contact found in friendlist // Add the contact, then issue the message again? // TODO: need to fetch the stage 1 public key somehow here // Ignoring such messages for now //addFriend(wallet_address, "pubkey", "Unknown"); //addMessage(wallet_address, message); Logging.warn("Received message but contact isn't in our contact list."); return(null); } Node.shouldRefreshContacts = true; if (!friend.online) { using (MemoryStream mw = new MemoryStream()) { using (BinaryWriter writer = new BinaryWriter(mw)) { writer.Write(wallet_address.Length); writer.Write(wallet_address); CoreProtocolMessage.broadcastProtocolMessage(new char[] { 'M' }, ProtocolMessageCode.getPresence, mw.ToArray(), null); } } } string sender_nick = ""; if (friend.bot && sender_address != null) { if (IxianHandler.getWalletStorage().isMyAddress(sender_address)) { local_sender = true; } if (!local_sender) { if (friend.contacts.ContainsKey(sender_address) && friend.contacts[sender_address].nick != "") { sender_nick = friend.contacts[sender_address].nick; } else { if (!friend.contacts.ContainsKey(sender_address) || friend.contacts[sender_address].publicKey == null) { StreamProcessor.requestPubKey(friend, sender_address); } StreamProcessor.requestNickname(friend, sender_address); } } } else { sender_nick = friend.nickname; } if (timestamp == 0) { timestamp = Clock.getTimestamp(); } FriendMessage friend_message = new FriendMessage(id, message, timestamp, local_sender, type, sender_address, sender_nick); if (friend.bot) { if (local_sender) { friend_message.read = true; } else { friend.lastReceivedMessageId = id; saveToStorage(); } } lock (friend.messages) { // TODO should be optimized if (id != null && friend.messages.Find(x => x.id != null && x.id.SequenceEqual(id)) != null) { Logging.warn("Message with id {0} was already in message list.", Crypto.hashToString(id)); return(null); } friend.messages.Add(friend_message); } // If a chat page is visible, insert the message directly if (friend.chat_page != null) { friend.chat_page.insertMessage(friend_message); } // Send a local push notification if Spixi is not in the foreground if (fire_local_notification && !local_sender) { if (App.isInForeground == false || friend.chat_page == null) { // don't fire notification for nickname and avatar if (!friend_message.id.SequenceEqual(new byte[] { 4 }) && !friend_message.id.SequenceEqual(new byte[] { 5 })) { DependencyService.Get <IPushService>().showLocalNotification("Spixi", "New Message", Base58Check.Base58CheckEncoding.EncodePlain(friend.walletAddress)); } } } ISystemAlert alert = DependencyService.Get <ISystemAlert>(); if (alert != null) { alert.flash(); } // Write to chat history Node.localStorage.writeMessages(wallet_address, friend.messages); return(friend_message); }
public void insertMessage(FriendMessage message) { if (friend.approved == false) { if (message.type == FriendMessageType.requestAdd) { // Call webview methods on the main UI thread only Utils.sendUiCommand(webView, "showContactRequest", "1"); message.read = true; return; } } else { // Don't show if the friend is already approved if (message.type == FriendMessageType.requestAdd) { return; } } string prefix = "addMe"; string avatar = "";//Node.localStorage.getOwnAvatarPath(); string address = ""; string nick = ""; if (friend.bot) { if (message.senderAddress != null) { address = Base58Check.Base58CheckEncoding.EncodePlain(message.senderAddress); } nick = message.senderNick; if (nick == "") { nick = address; } } if (!message.localSender) { prefix = "addThem"; avatar = "img/spixiavatar.png"; } if (message.type == FriendMessageType.requestFunds) { string status = "PENDING"; string status_icon = "fa-clock"; string amount = message.message; if (message.message.StartsWith("::")) { status = "DECLINED"; status_icon = "fa-exclamation-circle"; amount = message.message.Substring(2); } else if (message.message.StartsWith(":")) { Transaction transaction = TransactionCache.getTransaction(message.message.Substring(1)); if (transaction == null) { transaction = TransactionCache.getUnconfirmedTransaction(message.message.Substring(1)); } amount = "?"; if (transaction != null) { amount = transaction.amount.ToString(); if (transaction.applied > 0) { status = "CONFIRMED"; status_icon = "fa-check-circle"; } } } if (message.localSender) { Utils.sendUiCommand(webView, "addPaymentRequest", Crypto.hashToString(message.id), address, nick, avatar, "Payment request SENT", amount, status, status_icon, Clock.getRelativeTime(message.timestamp), message.localSender.ToString()); } else { Utils.sendUiCommand(webView, "addPaymentRequest", Crypto.hashToString(message.id), address, nick, avatar, "Payment request RECEIVED", amount, status, status_icon, Clock.getRelativeTime(message.timestamp)); } message.read = true; return; } if (message.type == FriendMessageType.sentFunds) { message.read = true; Transaction transaction = TransactionCache.getTransaction(message.message); if (transaction == null) { transaction = TransactionCache.getUnconfirmedTransaction(message.message); } string status = "PENDING"; string status_icon = "fa-clock"; string amount = "?"; if (transaction != null) { if (transaction.applied > 0) { status = "CONFIRMED"; status_icon = "fa-check-circle"; } amount = transaction.amount.ToString(); } // Call webview methods on the main UI thread only if (message.localSender) { Utils.sendUiCommand(webView, "addPaymentRequest", Crypto.hashToString(message.id), address, nick, avatar, "Payment SENT", amount, status, status_icon, Clock.getRelativeTime(message.timestamp), message.localSender.ToString()); } else { Utils.sendUiCommand(webView, "addPaymentRequest", Crypto.hashToString(message.id), address, nick, avatar, "Payment RECEIVED", amount, status, status_icon, Clock.getRelativeTime(message.timestamp)); } return; } if (message.type == FriendMessageType.fileHeader) { string[] split = message.message.Split(new string[] { ":" }, StringSplitOptions.None); if (split != null && split.Length > 1) { string uid = split[0]; string name = split[1]; Utils.sendUiCommand(webView, "addFile", Crypto.hashToString(message.id), address, nick, avatar, uid, name, Clock.getRelativeTime(message.timestamp), message.localSender.ToString(), message.confirmed.ToString(), message.read.ToString()); } } else { // Normal chat message // Call webview methods on the main UI thread only Utils.sendUiCommand(webView, prefix, Crypto.hashToString(message.id), address, nick, avatar, message.message, Clock.getRelativeTime(message.timestamp), message.confirmed.ToString(), message.read.ToString()); } if (!message.read && !message.localSender) { message.read = true; Node.localStorage.writeMessagesFile(friend.walletAddress, friend.messages); // Send read confirmation StreamMessage msg_received = new StreamMessage(); msg_received.type = StreamMessageCode.info; msg_received.sender = IxianHandler.getWalletStorage().getPrimaryAddress(); msg_received.recipient = friend.walletAddress; msg_received.data = new SpixiMessage(message.id, SpixiMessageCode.msgRead, null).getBytes(); msg_received.transaction = new byte[1]; msg_received.sigdata = new byte[1]; msg_received.encryptionType = StreamMessageEncryptionCode.none; StreamProcessor.sendMessage(friend, msg_received, true); } }
public static bool fetchPushMessages(bool force = false) { if (force == false && lastUpdate + cooldownPeriod > Clock.getTimestamp()) { return(false); } lastUpdate = Clock.getTimestamp(); if (pushNotificationAuthKey == null) { if (!registerWithPushNotificationServer()) { return(false); } } try { string receiver = Base58Check.Base58CheckEncoding.EncodePlain(Node.walletStorage.getPrimaryAddress()); nonce++; byte[] sig = Crypto.sha512(UTF8Encoding.UTF8.GetBytes(nonce + pushNotificationAuthKey)); using (WebClient client = new WebClient()) { string url = String.Format("{0}/fetch.php?tag={1}&nonce={2}&sig={3}", Config.pushServiceUrl, receiver, nonce, Crypto.hashToString(sig)); string htmlCode = client.DownloadString(url); if (htmlCode.StartsWith("ERROR")) { if (htmlCode.StartsWith("ERROR: Nonce too low ")) { nonce = Int32.Parse(htmlCode.Substring("ERROR: Nonce too low ".Length)); } return(false); } if (htmlCode == "UNREGISTERED") { pushNotificationAuthKey = null; registerWithPushNotificationServer(); return(false); } List <string[]> jsonResponse = JsonConvert.DeserializeObject <List <string[]> >(htmlCode); if (jsonResponse != null && jsonResponse.Count > 0) { lastUpdate = 0; // If data was available, fetch it again without cooldown } foreach (string[] str in jsonResponse) { try { byte[] data = Convert.FromBase64String(str[1]); if (str[2] != "") { byte[] pk = Convert.FromBase64String(str[2]); Friend f = FriendList.getFriend(new Address(pk).address); if (f != null && pk != null) { f.setPublicKey(pk); } } StreamProcessor.receiveData(data, null); } catch (Exception e) { Logging.error("Exception occured in fetchPushMessages while parsing the json response: {0}", e); } try { nonce++; sig = Crypto.sha512(UTF8Encoding.UTF8.GetBytes(nonce + pushNotificationAuthKey)); string id = str[0]; url = String.Format("{0}/remove.php?id={1}&nonce={2}&sig={3}", Config.pushServiceUrl, id, nonce, Crypto.hashToString(sig)); htmlCode = client.DownloadString(url); } catch (Exception e) { Logging.error("Exception occured in fetchPushMessages while removing the message from server: {0}", e); } } } } catch (Exception e) { Logging.error("Exception occured in fetchPushMessages: {0}", e); return(false); } return(true); }
public static bool fetchPushMessages(bool force = false) { if (force == false && lastUpdate + cooldownPeriod > Clock.getTimestamp()) { return(false); } lastUpdate = Clock.getTimestamp(); try { string URI = String.Format("{0}/fetch.php", Config.pushServiceUrl); string unique_uri = String.Format("{0}/uniqueid.php", Config.pushServiceUrl); string receiver = Base58Check.Base58CheckEncoding.EncodePlain(Node.walletStorage.getPrimaryAddress()); WebClient uclient = new WebClient(); byte[] checksum = Convert.FromBase64String(uclient.DownloadString(unique_uri)); byte[] sig = CryptoManager.lib.getSignature(checksum, Node.walletStorage.getPrimaryPrivateKey()); using (WebClient client = new WebClient()) { string url = String.Format("{0}?tag={1}&sig={2}", URI, receiver, HttpUtility.UrlEncode(Convert.ToBase64String(sig))); string htmlCode = client.DownloadString(url); Logging.info("fetchPushMessages: {0}", htmlCode); if (htmlCode == "FALSE") { return(false); } lastUpdate = 0; // If data was available, fetch it again without cooldown List <string[]> jsonResponse = JsonConvert.DeserializeObject <List <string[]> >(htmlCode); foreach (string[] str in jsonResponse) { try { byte[] data = Convert.FromBase64String(str[0]); if (str[1] != "") { byte[] pk = Convert.FromBase64String(str[1]); Friend f = FriendList.getFriend(new Address(pk).address); if (f != null) { f.publicKey = pk; } FriendList.saveToStorage(); } StreamProcessor.receiveData(data, null); } catch (Exception e) { Logging.error(string.Format("Exception occured in fetchPushMessages while parsing the json response. {0}", e)); } } } } catch (Exception e) { Logging.error(string.Format("Exception occured in fetchPushMessages. {0}", e)); return(false); } return(true); }