public NanoHttpResponse Handle(NanoHttpRequest request) { Hash hash = new Hash(request.Address.Split('/').Last()); if (hash.Invalid) { return(new ErrorHandler(StatusCode.BadRequest, "Invalid hash").Handle(request)); } try { var tag = _db.Get(hash).ContainerTag; for (int i = 0; i < _db.GetPostCount(); i++) { var p = _db.GetPost(i); if (p.ContainerTag != null && p.ContainerTag.Equals(tag)) { _db.HideOnce(p.GetHash()); } } return(new NanoHttpResponse(StatusCode.Ok, "\n")); } catch (Exception e) { return(new ErrorHandler(StatusCode.InternalServerError, e.ToString().Replace("\n", "<br>")).Handle(request)); } }
private NanoHttpResponse HandleSafe(NanoHttpRequest request) { Hash thread = new Hash(request.Address.Split('/').Last()); if (thread.Invalid) { return(new ErrorHandler(StatusCode.BadRequest, "Wrong hash format.").Handle(request)); } var sb = new StringBuilder(); var p = _db.Get(thread); sb.Append("{\n \"hash\" : \""); sb.Append(p.GetHash().Value); sb.Append("\", \n \"isHidden\" : \""); sb.Append(_db.IsHidden(p.GetHash()) ? "1" : "0"); sb.Append("\", \n \"replyTo\" : \""); sb.Append(p.ReplyTo.Value); sb.Append("\", \n \"message\" : \""); string s = p.SerializedString().Substring(32); s = s.Replace("\\", "\\\\"); s = s.Replace("\n", "\\n"); s = s.Replace("\"", "\\\""); s = s.Replace("\t", "\\t"); s = s.Replace("\r", "\\r"); sb.Append(s); sb.Append("\"\n}"); return(new NanoHttpResponse(StatusCode.Ok, sb.ToString(), "application/json; charset=utf-8")); }
private NanoHttpResponse HandleSafe(NanoHttpRequest request) { Hash thread = new Hash(request.Address.Split('/').Last()); if (thread.Invalid) { return(new ErrorHandler(StatusCode.BadRequest, "Wrong hash format.").Handle(request)); } var sb = new StringBuilder(); ThreadViewHandler.AddHeader(sb); var p = _db.Get(thread); bool corePost = false; if (p.GetHash().Value == NanoDB.CategoriesHashValue || // создал категорию - не разворачивать все категории p.ReplyTo.Value == NanoDB.CategoriesHashValue) // создал тред в одной из категорий - не разворачивать все треды { corePost = true; } sb.Append( ( p.Message.Strip(true).Replace("\n", "<br/>").ToDiv("postinner", p.GetHash().Value) ).ToDiv("post", "")); sb.Append(((/*">" + p.Message.StripInput().Replace("\n", "\n>") + "\n"*/ "").ToTextArea("", "reply").AddBreak() + ("Отправить".ToButton("", "sendbtn", @" document.getElementById('sendbtn').disabled = true; var x = new XMLHttpRequest(); x.open('POST', '../write/" + p.GetHash().Value + @"', true); x.send(document.getElementById('reply').value); x.onreadystatechange = function(){ onAdd(x.responseText, function(){ location.replace('/" + (corePost?"thread":"expand") + "/" + p.GetHash().Value + @"'); }); } "))).ToDiv("post", "")); return(new NanoHttpResponse(StatusCode.Ok, sb.ToString().ToHtmlBody(ThreadViewHandler.JQueryMinJs + ThreadViewHandler.Base64Js + ThreadViewHandler.BitSendJs))); }
private NanoHttpResponse HandleSafe(NanoHttpRequest request) { _places = HtmlStringExtensions.UpdatePlaces().ToArray(); _allowed = HtmlStringExtensions.UpdateAllowed(); var sw = new System.Diagnostics.Stopwatch(); sw.Start(); Hash thread = null; if (request.Address != "/") { thread = new Hash(request.Address.Split('/').Last()); if (thread.Invalid) { return(new ErrorHandler(StatusCode.BadRequest, "Wrong hash format.").Handle(request)); } } else { thread = new Hash(NanoDB.CategoriesHashValue); } var sb = new StringBuilder(); AddHeader(sb); string s1 = ""; if (thread.Value != NanoDB.CategoriesHashValue) { s1 = "<a href='#' onclick='history.go(-1)'>[Назад]</a>"; s1 += "<a href='#' onclick='location.reload()'>[Обновить]</a>"; if (!_expand) { s1 += "<a href='#' onclick='window.location.href=window.location.toString().replace(\"thread\",\"expand\")'>[Развернуть]</a>"; } else { s1 += "<a href='#' onclick='window.location.href=window.location.toString().replace(\"expand\",\"thread\")'>[Свернуть]</a>"; } } else { s1 = "<a href='#' onclick='location.reload()'>[Обновить]</a>"; } sb.Append(s1.ToDiv("", "")); NanoPost[] posts = null; /* * if (!_expand) * posts = _db.GetThreadPosts(thread).ExceptHidden(_db); * else * posts = _db.GetExpandedThreadPosts(thread).ExceptHidden(_db); */ if (!_expand) { posts = _db.GetThreadPosts(thread); } else { posts = _db.GetExpandedThreadPosts(thread); } bool first = true; if (!_expand) { posts = posts.OrderByDescending(p => p.NumberTag).ToArray(); } string postScript = ""; foreach (var sp in posts) { var p = sp; //string pMessage = p.Message; string pMessage = p.Message.Strip(true); var fmPattern = "\\[fm=.*\\]"; var music = Regex.Matches(pMessage, fmPattern); int musicNum = 0; foreach (var m in music) { musicNum += 1; var value = (m as Match).Value; var formula = value.Substring(4).TrimEnd(']').Replace(">", ">").Replace("<", "<").Replace("<grn>", "").Replace("</grn>", "").Replace(" ", " "). Replace("’", "'").Replace("“", "\"").Replace(";", ""); var strictFmPattern = "()t *0123456789abcdefxABCDEF|><!%:^&.-+/?=~"; bool invalid = formula.Length > 8192; if (!invalid) { foreach (var ch in formula) { if (!strictFmPattern.Contains(ch)) { invalid = true; break; } } } if (invalid) { continue; } var replacement = string.Format(@"<b>Фрактальная музыка:</b> <small><pre>{1}</pre></small><button id='mb{0}'>Сгенерировать</button> <audio style='visibility:hidden;' controls='false' id='au{0}'></audio>", sp.GetHash().Value + musicNum, formula); postScript += "document.getElementById('mb" + sp.GetHash().Value + musicNum + "').onclick = function() { addFractalMusic(function(t){return " + formula + ";}, 210*8000, 'au" + sp.GetHash().Value + musicNum + "');" + "this.parentNode.removeChild(this);" + "}\n"; pMessage = pMessage.Replace(value, replacement); } string numTag = (p.NumberTag == int.MaxValue ? "" : "<grn><sup>#" + p.GetHash().Value.ShortenHash() + "</sup></grn> "); bool hidden = false; if (_db.IsHidden(p.GetHash())) { hidden = true; } string handler = "/expand/"; bool corePost = false; if (p.GetHash().Value == NanoDB.RootHashValue || // root p.ReplyTo.Value == NanoDB.RootHashValue || // root p.GetHash().Value == NanoDB.CategoriesHashValue || // categories p.ReplyTo.Value == NanoDB.CategoriesHashValue) // categories { handler = "/thread/"; corePost = true; } if (_db.Get(p.ReplyTo) != null && (_db.Get(p.ReplyTo).ReplyTo.Value == NanoDB.CategoriesHashValue || _db.Get(p.ReplyTo).ReplyTo.Value == NanoDB.RootHashValue)) { corePost = true; } Func <NanoPost, string> addRefs = pst => { var children = _db.GetThreadPosts(pst.GetHash(), eraseDepth: false); var refs1 = "<br/><div><small>"; int line = 0; foreach (var ch in children) { if (ch.GetHash().Value != pst.GetHash().Value) { line += 1; refs1 += "<a href='#" + ch.GetHash().Value + "'><i>>>" + ch.GetHash().Value.ShortenHash() + "</i></a>"; if (line > 5) { line = 0; refs1 += "</br>"; } } } refs1 += "</small></div>"; return(refs1); }; if (_expand && first && !p.GetHash().Zero&& !p.ReplyTo.Zero) { string refs = ""; if (p.ReplyTo.Value != NanoDB.CategoriesHashValue && p.ReplyTo.Value != NanoDB.RootHashValue && _expand) { refs = addRefs(p); } sb.Append( ( (numTag + pMessage + refs).Replace("\n", "<br/>").ToDiv("postinner", p.GetHash().Value) + ("[Вверх]".ToRef((corePost ? "/thread/" : "/expand/") + p.ReplyTo.Value) + //("[В закладки]").ToRef("/bookmark/" + p.GetHash().Value) + ("<a onclick='show_reply(\"" + p.GetHash().Value + "\")'>[Быстрый ответ]</a>") + ("[Ответить]").ToRef("/reply/" + p.GetHash().Value)).ToDiv("", "") ).ToDiv("post", "")); first = false; continue; } first = false; int answers = _db.CountAnswers(p.GetHash()); string ans = "ответ"; int a = answers % 100; if (a == 0 || a % 10 == 0 || (a > 10 && a < 20)) { ans += "ов"; } else if (a % 10 >= 2 && a % 10 <= 4) { ans += "а"; } else if (a % 10 >= 5 && a % 10 <= 9) { ans += "ов"; } if (p.GetHash().Value == _db.RootHash.Value) { sb.Append( ( (@" Добро пожаловать на Наноборду! Это корневой нанопост. В целях тестирования на него можно было отвечать в предыдущих версиях. Это немного засорило Главную. Рекомендуется почистить её у себя вручную. Негласное правило: отвечать нужно на конкретное сообщение, а не просто ""в тред"", полагаясь на то, что сообщение выше вашего будет таким же и у других - порядок попадания нанопостов к другим участникам сложно предсказать. Создавать тред желательно в соответствующей категории." ).Strip().Replace("\n", "<br/>").ToDiv("postinner", p.GetHash().Value) + //(("[Ответить]").ToRef("/reply/" + p.GetHash().Value)).ToDiv("", "") + ("[Развернуть всё (осторожно!)]").ToRef("/expand/f682830a470200d738d32c69e6c2b8a4").ToDiv("", "") + ("[Категории]").ToRef("/thread/bdd4b5fc1b3a933367bc6830fef72a35").ToDiv("", "") ).ToDiv("post main", "")); } else { string refs = ""; if (p.ReplyTo.Value != NanoDB.CategoriesHashValue && p.ReplyTo.Value != NanoDB.RootHashValue && _expand) { refs = addRefs(p); } sb.Append( ( ((_expand?("<a href='#" + p.ReplyTo.Value + "'><i>>>" + p.ReplyTo.Value.ShortenHash() + "</i></a><br/>"):"") + numTag + pMessage + refs).Replace("\n", "<br/>").ToStyledDiv("postinner", p.GetHash().Value, hidden?"visibility:hidden;height:0px;":"") + ((answers > MinAnswers ? ("[" + answers + " " + ans + "]").ToRef(handler + p.GetHash().Value) : "") + (p.GetHash().Value != "bdd4b5fc1b3a933367bc6830fef72a35" ? ( (hidden?"[Вернуть]":"[Удалить]").ToButton("", "", @"var x = new XMLHttpRequest(); x.open('POST', '../hide/" + p.GetHash().Value + @"', true); x.send(''); var elem = document.getElementById('" + p.GetHash().Value + @"'); if (elem.style.visibility != 'hidden') { elem.style.visibility='hidden'; elem.style.height = '0px'; innerHTML = '[Вернуть]'; } else { elem.style.visibility='visible'; elem.style.height = '100%'; innerHTML = '[Удалить]'; } ")) : "") + //("[В закладки]").ToRef("/bookmark/" + p.GetHash().Value) + ("[Дамп]".ToPostRef("/dump/" + p.GetHash().Value)) + ("<a onclick='show_reply(\"" + p.GetHash().Value + "\")'>[Быстрый ответ]</a>") + ("[Ответить]").ToRef("/reply/" + p.GetHash().Value)).ToDiv("", "") ).ToStyledDiv("post", "", "position:relative;left:" + p.DepthTag * 20 + "px;")); } } sb.Append(s1.ToDiv("", "")); sw.Stop(); sb.Append("<div><br>места:"); var places = _places.Where(l => !l.StartsWith("#")).ToList(); places.ForEach(p => sb.Append(string.Format("<br><a target='_blank' href='{0}'>{0}</a>" + "<a target='_blank' href='/del/{0}'>[-]</a>", p))); sb.Append("</div>"); AddFooter(sb, sw.ElapsedMilliseconds, _db); var result = sb.ToString(); /* * if (!_expand) * sb.Append("Развернуть".ToButton("", "", "window.location.href=window.location.toString().replace('thread','expand')").ToDiv("","")); * else * sb.Append("Обновить".ToButton("", "", "location.reload()").ToDiv("","")); */ return(new NanoHttpResponse(StatusCode.Ok, result.AddVideo().AddReply().ToHtmlBody(JQueryMinJs + JQueryUiMinJs + Base64Js + FractalMusicScript + BitSendJs + PostScript(postScript)))); }
private NanoHttpResponse HandleSafe(NanoHttpRequest request) { var sw = new System.Diagnostics.Stopwatch(); sw.Start(); var sb = new StringBuilder(); ThreadViewHandler.AddHeader(sb); sb.Append(string.Format("<div>Количество правил игнорирования постов: {0}. Настройте spamfilter.txt под себя.</div>", SpamDetector.RuleCount)); sb.Append("[Очистить список]".ToButton("", "", @" var x = new XMLHttpRequest(); x.open('POST', '../save/', true); x.send(''); location.reload(); ").ToDiv("", "")); var posts = _db.GetNewPosts();//.ExceptHidden(_db); posts = posts.Reverse().ToArray(); foreach (var p in posts) { int answers = _db.CountAnswers(p.GetHash()); string ans = "ответ"; if (answers != 11 && answers % 10 == 1) { // } else if (answers != 11 && answers % 10 == 5) { ans += "ов"; } else { ans += "а"; } bool corePost = false; if (_db.Get(p.ReplyTo) != null && (_db.Get(p.ReplyTo).ReplyTo.Value == NanoDB.CategoriesHashValue || _db.Get(p.ReplyTo).ReplyTo.Value == NanoDB.RootHashValue)) { corePost = true; } bool hidden = _db.IsHidden(p.GetHash()); sb.Append( ( p.Message.Strip(true).Replace("\n", "<br/>").ToStyledDiv("postinner", p.GetHash().Value, hidden?"visibility:hidden;height:0px;":"") + ((answers > ThreadViewHandler.MinAnswers ? ("[" + answers + " " + ans + "]").ToRef("/expand/" + p.GetHash().Value):"") + (hidden?"[Вернуть]":"[Удалить]").ToButton("", "", @"var x = new XMLHttpRequest(); x.open('POST', '../hide/" + p.GetHash().Value + @"', true); x.send(''); var elem = document.getElementById('" + p.GetHash().Value + @"'); if (elem.style.visibility != 'hidden') { elem.style.visibility='hidden'; elem.style.height = '0px'; innerHTML = '[Вернуть]'; } else { elem.style.visibility='visible'; elem.style.height = '100%'; innerHTML = '[Удалить]'; } ") + (p.ContainerTag != null ? "[Отклонить контейнер]".ToButton("", "", @"var x = new XMLHttpRequest(); x.open('POST', '../hideall/" + p.GetHash().Value + @"', true); x.send('');location.reload();") : "") + //("[В закладки]").ToRef("/bookmark/" + p.GetHash().Value) + ("[В тред]").ToRef((corePost?"/thread/":"/expand/") + p.ReplyTo.Value) + ("[Ответить]").ToRef("/reply/" + p.GetHash().Value)).ToDiv("", "") ).ToDiv("post", "")); } string s1 = "<a href='#' onclick='location.reload()'>[Обновить]</a>"; sb.Append(s1.ToDiv("", "")); sw.Stop(); ThreadViewHandler.AddFooter(sb, sw.ElapsedMilliseconds, _db); return(new NanoHttpResponse(StatusCode.Ok, sb.ToString().ToHtmlBody(ThreadViewHandler.NotifierScript))); }
public void SaveToPngContainer(NanoDB db) { db.RewriteDbExceptHidden(); db.ClearDb(); db.ReadPosts(); string[] ext = new[] { ".png", ".jpg", ".jpeg" }; var files = new DirectoryInfo(Strings.Containers).GetFiles().Where(f => ext.Contains(f.Extension.ToLower())).ToArray(); if (files.Length == 0) { NotificationHandler.Instance.AddNotification("Не найдены PNG файлы в папке containers."); return; } else if (files.Length <= 5) { if (!_smaller) { NotificationHandler.Instance.AddNotification("Предупреждение: у вас мало контейнеров."); } } FileInfo file = files[random.Next(files.Length - 1)]; var bmp = new Bitmap(file.FullName); int capacity = (int)(bmp.Width * bmp.Height * 3 / 8) - 32; string sessionPrefix = random.Next().ToString("x8"); sessionPrefix += random.Next().ToString("x8"); var packed = new byte[0]; var posts = new List <NanoPost>(); int i = db.GetPostCount() - 1; while (i >= 0 && posts.Count < FreshPosts) { var p = db.GetPost(i--); if (!db.IsHidden(p.GetHash())) { posts.Add(p); } } var parr = posts.ToArray(); var parents = new List <NanoPost>(); foreach (var post in parr) { var p = db.Get(post.ReplyTo); if (p != null && !db.IsHidden(p.GetHash())) { parents.Add(p); } } foreach (var post in parents) { posts.Add(post); var p = db.Get(post.ReplyTo); if (p != null && !db.IsHidden(p.GetHash())) { posts.Add(p); } } var slice0 = posts.GetRange(0, Math.Max(posts.Count, FreshPostsNotLimitedTo16384Allowed)); var slice1 = posts.GetRange(slice0.Count, posts.Count - slice0.Count); posts.Clear(); posts.AddRange(slice0); posts.AddRange(slice1.ToArray().FilterBySize(16384)); posts.AddRange(db.GetNRandomPosts(RandomPostsLimitedTo8192ALlowed).ExceptHidden(db).FilterBySize(8192)); posts.AddRange(db.GetNRandomPosts(RandomPostsLimitedTo16384Allowed).ExceptHidden(db).FilterBySize(16384)); posts = posts.Distinct().ToList(); packed = NanoPostPackUtil.Pack(posts.ToArray()); float scale = 1; if (packed.Length > capacity) { scale = (packed.Length / (float)capacity); scale = (float)Math.Sqrt(scale); if (scale > 2 && !_smaller) { new PngContainerCreatorNew(4).SaveToPngContainer(db); return; } bmp = new Bitmap(bmp, (int)(bmp.Width * scale + 1), (int)(bmp.Height * scale + 1)); } new PngStegoUtil().HideBytesInPng( bmp, Strings.Upload + Path.DirectorySeparatorChar + sessionPrefix + Strings.PngExt, packed); Console.WriteLine( string.Format( "PNG capacity:{0}, posts amount:{1}, packed size:{2}, image scaling: {3:n2}x", capacity, posts.Count, packed.Length, scale)); Console.WriteLine("Total posts in db: {0}, post length limit (bytes): {1}", db.GetPostCount(), NanoPost.MaxPostByteLength); NotificationHandler.Instance.AddNotification("Контейнер сохранён: " + Strings.Upload + Path.DirectorySeparatorChar + sessionPrefix + Strings.PngExt); }
public void SaveToPngContainer(NanoDB db) { db.RewriteDbExceptHidden(); db.ClearDb(); db.ReadPosts(); string[] ext = new[] { ".png", ".jpg", ".jpeg" }; var files = new DirectoryInfo(Strings.Containers).GetFiles().Where(f => ext.Contains(f.Extension.ToLower())).ToArray(); if (files.Length == 0) { NotificationHandler.Instance.AddNotification("Не найдены PNG файлы в папке containers."); return; } else if (files.Length <= 5) { if (!_smaller) { NotificationHandler.Instance.AddNotification("Предупреждение: у вас мало контейнеров."); } } FileInfo file = files[random.Next(files.Length - 1)]; var bmp = new Bitmap(file.FullName); int capacity = (int)(bmp.Width * bmp.Height * 3 / 8) - 32; string sessionPrefix = random.Next().ToString("x8"); sessionPrefix += random.Next().ToString("x8"); var packed = new byte[0]; var posts = new List<NanoPost>(); int i = db.GetPostCount() - 1; while (i >= 0 && posts.Count < FreshPosts) { var p = db.GetPost(i--); if (!db.IsHidden(p.GetHash())) { posts.Add(p); } } var parr = posts.ToArray(); var parents = new List<NanoPost>(); foreach (var post in parr) { var p = db.Get(post.ReplyTo); if (p != null && !db.IsHidden(p.GetHash())) { parents.Add(p); } } foreach (var post in parents) { posts.Add(post); var p = db.Get(post.ReplyTo); if (p != null && !db.IsHidden(p.GetHash())) { posts.Add(p); } } var slice0 = posts.GetRange(0, Math.Max(posts.Count, FreshPostsNotLimitedTo16384Allowed)); var slice1 = posts.GetRange(slice0.Count, posts.Count - slice0.Count); posts.Clear(); posts.AddRange(slice0); posts.AddRange(slice1.ToArray().FilterBySize(16384)); posts.AddRange(db.GetNRandomPosts(RandomPostsLimitedTo8192ALlowed).ExceptHidden(db).FilterBySize(8192)); posts.AddRange(db.GetNRandomPosts(RandomPostsLimitedTo16384Allowed).ExceptHidden(db).FilterBySize(16384)); posts = posts.Distinct().ToList(); packed = NanoPostPackUtil.Pack(posts.ToArray()); float scale = 1; if (packed.Length > capacity) { scale = (packed.Length / (float)capacity); scale = (float)Math.Sqrt(scale); if (scale > 2 && !_smaller) { new PngContainerCreatorNew(4).SaveToPngContainer(db); return; } bmp = new Bitmap(bmp, (int) (bmp.Width * scale + 1), (int) (bmp.Height * scale + 1)); } new PngStegoUtil().HideBytesInPng( bmp, Strings.Upload + Path.DirectorySeparatorChar + sessionPrefix + Strings.PngExt, packed); Console.WriteLine( string.Format( "PNG capacity:{0}, posts amount:{1}, packed size:{2}, image scaling: {3:n2}x", capacity, posts.Count, packed.Length, scale)); Console.WriteLine("Total posts in db: {0}, post length limit (bytes): {1}", db.GetPostCount(), NanoPost.MaxPostByteLength); NotificationHandler.Instance.AddNotification("Контейнер сохранён: " + Strings.Upload + Path.DirectorySeparatorChar + sessionPrefix + Strings.PngExt); }