private void CachePost(SignedData signedHeader, PostHeader header) { if (Core.InvokeRequired) Debug.Assert(false); if (header.ParentID == 0 && header.SourceID != header.TargetID) { Network.UpdateLog("Board", "Post made to board other than source's"); return; } if (!File.Exists(GetPostPath(header))) { DownloadPost(signedHeader, header); return; } // check if current version loaded OpPost post = GetPost(header); if (post != null && post.Header.Version >= header.Version ) { UpdateGui(post); return; } // put into map OpBoard board = GetBoard(header.TargetID); if (board == null) { board = new OpBoard(header.Target); BoardMap.SafeAdd(header.TargetID, board); } PostUID uid = new PostUID(header); post = new OpPost(); post.Header = header; post.SignedHeader = signedHeader.Encode(Network.Protocol); post.Ident = header.TargetID.GetHashCode() ^ uid.GetHashCode(); post.Unique = Loading; // remove previous version of file, if its different OpPost prevPost = board.GetPost(uid); if (prevPost != null && GetPostPath(prevPost.Header) != GetPostPath(header)) try { File.Delete(GetPostPath(prevPost.Header)); } catch { } board.Posts.SafeAdd(uid, post); // update replies if (post.Header.ParentID == 0) board.UpdateReplies(post); else { PostUID parentUid = new PostUID(board.UserID, post.Header.ProjectID, post.Header.ParentID); OpPost parentPost = board.GetPost(parentUid); if (parentPost != null) { board.UpdateReplies(parentPost); UpdateGui(post); } } lock (SaveHeaders) if (!SaveHeaders.Contains(header.TargetID)) SaveHeaders.Add(header.TargetID); ushort replies = 0; if (SavedReplyCount.SafeTryGetValue(post.Ident, out replies)) { post.Replies = replies; SavedReplyCount.SafeRemove(post.Ident); } UpdateGui(post); if (Core.NewsWorthy(header.TargetID, header.ProjectID, true)) Core.MakeNews(ServiceIDs.Board, "Board updated by " + Core.GetName(header.SourceID), header.SourceID, 0, false); }
public void PostMessage(ulong user, uint project, uint parent, ScopeType scope, string subject, string message, TextFormat format, string quip, List<AttachedFile> files, OpPost edit) { // post header PostHeader header = new PostHeader(); header.Source = Core.User.Settings.KeyPublic; header.SourceID = Core.UserID; header.Target = Core.KeyMap[user]; header.TargetID = user; header.ParentID = parent; header.ProjectID = project; header.Scope = scope; if (edit == null) { header.Time = Core.TimeNow.ToUniversalTime(); byte[] rnd = new byte[4]; Core.RndGen.NextBytes(rnd); header.PostID = BitConverter.ToUInt32(rnd, 0); } else { header.PostID = edit.Header.PostID; header.Version = (ushort) (edit.Header.Version + 1); header.Time = edit.Header.Time; header.EditTime = Core.TimeNow.ToUniversalTime(); } header.FileKey = Utilities.GenerateKey(Core.StrongRndGen, 256); // setup temp file string tempPath = Core.GetTempPath(); using (IVCryptoStream stream = IVCryptoStream.Save(tempPath, header.FileKey)) { int written = 0; // write post file written += Protocol.WriteToFile(new PostInfo(subject, format, quip, Core.RndGen), stream); byte[] msgBytes = UTF8Encoding.UTF8.GetBytes(message); written += Protocol.WriteToFile(new PostFile("body", msgBytes.Length), stream); foreach (AttachedFile attached in files) written += Protocol.WriteToFile(new PostFile(attached.Name, attached.Size), stream); stream.WriteByte(0); // end packets header.FileStart = (long)written + 1; // write files stream.Write(msgBytes, 0, msgBytes.Length); if (files != null) { int buffSize = 4096; byte[] buffer = new byte[buffSize]; foreach (AttachedFile attached in files) using (FileStream embed = File.OpenRead(attached.FilePath)) { int read = buffSize; while (read == buffSize) { read = embed.Read(buffer, 0, buffSize); stream.Write(buffer, 0, read); } } } stream.WriteByte(0); // signal last packet stream.FlushFinalBlock(); } // finish building header Utilities.HashTagFile(tempPath, Network.Protocol, ref header.FileHash, ref header.FileSize); string finalPath = GetPostPath(header); File.Move(tempPath, finalPath); FinishPost(header); }
public void UpdateGui(OpPost post) { if (PostUpdate != null) Core.RunInGuiThread(PostUpdate, post); }
public void LoadThread(OpPost parent) { OpBoard board = GetBoard(parent.Header.TargetID); if (board == null) return; // have all replies fire an update board.Posts.LockReading(delegate() { foreach (OpPost post in board.Posts.Values) if (post.Header.ProjectID == parent.Header.ProjectID && post.Header.ParentID == parent.Header.PostID) UpdateGui(post); }); // do search for thread ThreadSearch(board.UserID, parent.Header.ProjectID, parent.Header.PostID); }
public void PostEdit(OpPost edit) { // used for archive/restore PostHeader copy = edit.Header.Copy(); copy.Version++; copy.EditTime = Core.TimeNow.ToUniversalTime(); FinishPost(copy); }
public string GetPostTitle(OpPost post) { // loads info when first demanded, cached afterwards if (post.Info == null) try { string path = GetPostPath(post.Header); if (!File.Exists(path)) return ""; post.Attached = new List<PostFile>(); using (TaggedStream file = new TaggedStream(path, Network.Protocol)) using (IVCryptoStream crypto = IVCryptoStream.Load(file, post.Header.FileKey)) { PacketStream stream = new PacketStream(crypto, Network.Protocol, FileAccess.Read); G2Header root = null; while (stream.ReadPacket(ref root)) { if (root.Name == BoardPacket.PostInfo) post.Info = PostInfo.Decode(root); else if (root.Name == BoardPacket.PostFile) post.Attached.Add(PostFile.Decode(root)); } } } catch (Exception ex) { Network.UpdateLog("Board", "Could not load post " + post.Header.SourceID.ToString() + ": " + ex.Message); } if (post.Info == null) return ""; if (post.Header.ParentID == 0) return post.Info.Subject; else return post.Info.Quip; }
// cant delete post because we dont control them with any master header // future - local board file that consists of deleted post ids public void Archive(OpPost post, bool state) { post.Header.Archived = state; PostEdit(post); UpdateGui(null); }
public void UpdateReplies(OpPost parent) { // count replies to post, if greater than variable set, overwrite ushort replies = 0; Posts.LockReading(delegate() { foreach (OpPost post in Posts.Values) if (post.Header.ParentID == parent.Header.PostID) replies++; }); if (replies > parent.Replies) parent.Replies = replies; }
public void PostReply(OpPost parent) { Reply = true; ParentPost = parent; ParentID = parent.Header.PostID ; SubjectTextBox.Text = parent.Info.Subject; SubjectTextBox.Enabled = false; SubjectTextBox.BackColor = Color.WhiteSmoke; SetScopeInvisible(); PostButton.Text = "Reply"; }
public void PostEdit(OpPost post, uint parentID, string rtf, bool plain) { EditPost = post; ParentID = parentID; SubjectTextBox.Text = post.Info.Subject; MessageBody.InputBox.Rtf = rtf; MessageBody.PlainTextMode = plain; if (post.Header.Scope == ScopeType.All) ScopeAll.Checked = true; else if (post.Header.Scope == ScopeType.High) ScopeHigh.Checked = true; else if (post.Header.Scope == ScopeType.Low) ScopeLow.Checked = true; if (parentID != 0) { SubjectTextBox.Text = post.Info.Subject; SubjectTextBox.Enabled = false; SetScopeInvisible(); } PostButton.Text = "Edit"; }