Esempio n. 1
0
        public NanoHttpResponse Handle(NanoHttpRequest request)
        {
            try
            {
                var places = new List<string>(File.ReadAllLines(Strings.Places));
                var place = request.Address.Substring(5);

                bool found = false;

                if (places.Contains(place))
                {
                    found = true;
                    places.RemoveAll(s => s == place);
                }

                File.WriteAllLines(Strings.Places, places.ToArray());
                return new NanoHttpResponse(StatusCode.Ok, (found?"Deleted ":"Not found ") + place);
            }

            catch (Exception e)
            {
                NotificationHandler.Instance.AddNotification("Не удалось обновить places.txt");
                return new ErrorHandler(StatusCode.InternalServerError, e.ToString()).Handle(request);
            }
        }
Esempio n. 2
0
        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
            {
                if (_db.IsHidden(hash))
                {
                    _db.Unhide(hash);
                }

                else
                {
                    _db.Hide(hash);
                }

                return new NanoHttpResponse(StatusCode.Ok, "\n");
            }

            catch (Exception e)
            {
                return new ErrorHandler(StatusCode.InternalServerError, e.ToString().Replace("\n", "<br>")).Handle(request);
            }
        }
Esempio n. 3
0
        private NanoHttpResponse HandleSafe(NanoHttpRequest request)
        {
            int n = int.Parse(request.Address.Split('/').Last());

            var sb = new StringBuilder();
            var p  = _db.GetPost(n);

            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"));
        }
Esempio n. 4
0
        public NanoHttpResponse Handle(NanoHttpRequest request)
        {
            Hash            hash = new Hash(request.Address.Split('/').Last());
            List <NanoPost> all  = new List <NanoPost>(_db.GetExpandedThreadPosts(hash));

            //
            // recursively hide posts
            foreach (NanoPost p in all)
            {
                if (_db.IsHidden(p.GetHash()))
                {
                    var children = _db.GetExpandedThreadPosts(p.GetHash());

                    foreach (var child in children)
                    {
                        _db.Hide(child.GetHash());
                    }
                }
            }

            List <NanoPost> list = new List <NanoPost>(all.Where(p => !_db.IsHidden(p.GetHash())));

            new PngContainerCreator(_db).CreateWithList(list);
            return(new NanoHttpResponse(StatusCode.Ok, "\n"));
        }
Esempio n. 5
0
        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);
            }
        }
Esempio n. 6
0
        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));
            }
        }
Esempio n. 7
0
        public NanoHttpResponse Handle(NanoHttpRequest request)
        {
            try
            {
                var places = new List <string>(File.ReadAllLines(Strings.Places));
                var place  = request.Address.Substring(5);

                bool found = false;

                if (places.Contains(place))
                {
                    found = true;
                    places.RemoveAll(s => s == place);
                }

                File.WriteAllLines(Strings.Places, places.ToArray());
                return(new NanoHttpResponse(StatusCode.Ok, (found?"Deleted ":"Not found ") + place));
            }

            catch (Exception e)
            {
                NotificationHandler.Instance.AddNotification("Не удалось обновить places.txt");
                return(new ErrorHandler(StatusCode.InternalServerError, e.ToString()).Handle(request));
            }
        }
Esempio n. 8
0
        private NanoHttpResponse HandleSafe(NanoHttpRequest request)
        {
            int n = int.Parse(request.Address.Split('/').Last());

            var sb = new StringBuilder();
            var p = _db.GetPost(n);

            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");
        }
Esempio n. 9
0
        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
            {
                if (_db.IsHidden(hash))
                {
                    _db.Unhide(hash);
                }

                else
                {
                    _db.Hide(hash);
                }

                return(new NanoHttpResponse(StatusCode.Ok, "\n"));
            }

            catch (Exception e)
            {
                return(new ErrorHandler(StatusCode.InternalServerError, e.ToString().Replace("\n", "<br>")).Handle(request));
            }
        }
Esempio n. 10
0
        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"));
        }
Esempio n. 11
0
        public NanoHttpResponse Handle(NanoHttpRequest request)
        {
            try
            {
                return new NanoHttpResponse(StatusCode.Ok, _messages.Dequeue() + (_messages.Count > 0 ? "<br>"+_messages.Peek() : ""));
            }

            catch
            {
                return new NanoHttpResponse(StatusCode.NotModified, "\n");
            }
        }
Esempio n. 12
0
        public NanoHttpResponse Handle(NanoHttpRequest request)
        {
            try
            {
                return HandleSafe(request);
            }

            catch (Exception e)
            {
                return new ErrorHandler(StatusCode.InternalServerError, e.ToString().Replace("\n", "<br>")).Handle(request);
            }
        }
Esempio n. 13
0
        public NanoHttpResponse Handle(NanoHttpRequest request)
        {
            try
            {
                return(new NanoHttpResponse(StatusCode.Ok, _messages.Dequeue() + (_messages.Count > 0 ? "<br>" + _messages.Peek() : "")));
            }

            catch
            {
                return(new NanoHttpResponse(StatusCode.NotModified, "\n"));
            }
        }
Esempio n. 14
0
        public NanoHttpResponse Handle(NanoHttpRequest request)
        {
            if (string.IsNullOrEmpty(request.Content))
            {
                return(new ErrorHandler(StatusCode.BadRequest, "Empty message").Handle(request));
            }

            Hash thread = new Hash(request.Address.Split('/').Last());

            if (thread.Invalid)
            {
                return(new ErrorHandler(StatusCode.BadRequest, "Invalid hash").Handle(request));
            }

            var str = Encoding.UTF8.GetString(request.Connection.Raw);

            str = str.Substring(str.IndexOf("\r\n\r\n") + 4);
            NanoPost post = null;

            if (thread.Value != NanoDB.CategoriesHashValue)
            {
                post = new NanoPost(thread, "[g]" + GetPostHeader() + "[/g]\n" + str);
            }

            else
            {
                post = new NanoPost(thread, str);
            }

            if (post.Invalid)
            {
                NotificationHandler.Instance.AddNotification("Превышен максимальный размер поста.");
                return(new NanoHttpResponse(StatusCode.BadRequest, ""));
            }

            if (SpamDetector.IsSpam(post.Message))
            {
                NotificationHandler.Instance.AddNotification("Ваш пост из-за своего содержания будет считаться спамом.");
                return(new NanoHttpResponse(StatusCode.BadRequest, ""));
            }
            else
            {
                NotificationHandler.Instance.AddNotification(
                    "Сообщение добавлено, " + post.SerializedBytes().Length + " байт (" + post.SerializedString().Length + " симв.)");

                if (_db.AddPost(post))
                {
                    _db.WriteNewPosts(false);
                }

                return(new NanoHttpResponse(StatusCode.Ok, post.GetHash().Value));
            }
        }
Esempio n. 15
0
        public NanoHttpResponse Handle(NanoHttpRequest request)
        {
            try
            {
                return(HandleSafe(request));
            }

            catch (Exception e)
            {
                return(new ErrorHandler(StatusCode.InternalServerError, e.ToString().Replace("\n", "<br>")).Handle(request));
            }
        }
Esempio n. 16
0
        public NanoHttpResponse Handle(NanoHttpRequest request)
        {
            if (string.IsNullOrEmpty(request.Content))
            {
                return new ErrorHandler(StatusCode.BadRequest, "Empty message").Handle(request);
            }

            Hash thread = new Hash(request.Address.Split('/').Last());

            if (thread.Invalid)
            {
                return new ErrorHandler(StatusCode.BadRequest, "Invalid hash").Handle(request);
            }

            var str = Encoding.UTF8.GetString(request.Connection.Raw);
            str = str.Substring(str.IndexOf("\r\n\r\n") + 4);
            NanoPost post = null;

            if (thread.Value != NanoDB.CategoriesHashValue)
            {
                post = new NanoPost(thread, "[g]" + GetPostHeader() + "[/g]\n" + str);
            }

            else
            {
                post = new NanoPost(thread, str);
            }

            if (post.Invalid)
            {
                NotificationHandler.Instance.AddNotification("Превышен максимальный размер поста.");
                return new NanoHttpResponse(StatusCode.BadRequest, "");
            }

            if (SpamDetector.IsSpam(post.Message))
            {
                NotificationHandler.Instance.AddNotification("Ваш пост из-за своего содержания будет считаться спамом.");
                return new NanoHttpResponse(StatusCode.BadRequest, "");
            }
            else
            {
                NotificationHandler.Instance.AddNotification(
                    "Сообщение добавлено, " + post.SerializedBytes().Length + " байт ("+post.SerializedString().Length+" симв.)");

                if (_db.AddPost(post))
                {
                    _db.WriteNewPosts(false);
                }

                return new NanoHttpResponse(StatusCode.Ok, post.GetHash().Value);
            }
        }
Esempio n. 17
0
        private void OnConnectionAdded(HttpConnection connection)
        {
            var request = new NanoHttpRequest(connection, connection.Request);

            if (request.Method == "GET" || request.Method == "POST")
            {
                Process(connection, request);
            }
            else if (request.Method != null)
            {
                connection.Response(new ErrorHandler(StatusCode.MethodNotAllowed, "Server only supports GET and POST").Handle(request));
            }
        }
Esempio n. 18
0
        public NanoHttpResponse Handle(NanoHttpRequest request)
        {
            try
            {
                var sb = new StringBuilder();

                int offset = Encoding.ASCII.GetString(request.Connection.Raw).IndexOf("\r\n\r\n");
                offset = Encoding.ASCII.GetString(request.Connection.Raw).IndexOf("\r\n\r\n", offset + 4);
                int length = request.Connection.Raw.Length;

                int stepBack = 2; // multipart ending
                int dashes   = 0;

                for (int i = request.Connection.Raw.Length - 1; i > 0; i--)
                {
                    stepBack += 1;
                    byte b = request.Connection.Raw[i];
                    char c = (char)b;

                    if (c == '-')
                    {
                        dashes += 1;

                        if (dashes == 31)
                        {
                            break;
                        }
                    }
                }

                sb.Append("[img=");
                sb.Append(Convert.ToBase64String(request.Connection.Raw, offset + 4, length - offset - 4 - stepBack));
                sb.Append("]");
                string prep = "";
                if (sb.Length > 16384)
                {
                    prep = "Превышен лимит в 16384 символа. Такой нанопост будет хуже ретранслироваться другими.\n";
                }
                if (sb.Length > 32768)
                {
                    prep = "Превышен лимит в 32768 символов. Такая картинка не отобразится.\n";
                }
                return(new NanoHttpResponse(StatusCode.Ok, prep + sb.ToString(), "text/plain; charset=utf-8"));
            }

            catch
            {
                return(new NanoHttpResponse(StatusCode.Ok, "Error"));
            }
        }
Esempio n. 19
0
        public NanoHttpResponse Handle(NanoHttpRequest request)
        {
            if (_messages.Count > 0)
            {
                try
                {
                    return(new NanoHttpResponse(StatusCode.Ok, _messages.Dequeue()));
                }
                catch
                {
                }
            }

            return(new NanoHttpResponse(StatusCode.NotModified, "\n"));
        }
Esempio n. 20
0
        public NanoHttpResponse Handle(NanoHttpRequest request)
        {
            if (_agg.InProgress <= 0)
            {
                NotificationHandler.Instance.AddNotification("Начат поиск сообщений.");
                _agg.Aggregate();
            }

            else
            {
                NotificationHandler.Instance.AddNotification("Повторно начат поиск сообщений.");
                _agg.Aggregate();
            }

            return(new NanoHttpResponse(StatusCode.Ok, "<html><body onload='history.back()'></body></html>"));
        }
Esempio n. 21
0
        public NanoHttpResponse Handle(NanoHttpRequest request)
        {
            if (_agg.InProgress <= 0)
            {
                NotificationHandler.Instance.AddNotification("Начат поиск сообщений.");
                _agg.Aggregate();
            }

            else
            {
                NotificationHandler.Instance.AddNotification("Повторно начат поиск сообщений.");
                _agg.Aggregate();
            }

            return new NanoHttpResponse(StatusCode.Ok, "<html><body onload='history.back()'></body></html>");
        }
        public NanoHttpResponse Handle(NanoHttpRequest request)
        {
            var sb = new StringBuilder();
            //ThreadViewHandler.AddHeader(sb);

            sb.Append("<br>Картинка -&gt; Base64:</br>");

            // Changes form's action on change of select
            sb.Append(@"<script>function change_action(select){
                var selected = select.options[select.selectedIndex].id;
                var form = document.getElementById(""upload-form"");
                if(selected == ""No""){
                    form.action = ""convert"";
                } else {
                    form.action = ""compress/"" + selected;
                }
            }</script>");

            // Default - "Умеренно". To change default: change action in form and change selected option
            sb.Append(@"<form id=""upload-form"" action=""compress/-70-80"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <label for=""compression-level"">Степень сжатия: </label>
                <select id=""compression-level"" onchange=""change_action(this);"" >
                    <option id=""No"">Без сжатия</option>
                    <option id=""-90-90"">Незримо</option>
                    <option id=""-80-85"">Слегка</option>
                    <option id=""-70-80"" selected>Умеренно</option>
                    <option id=""-60-75"">Весьма</option>
                    <option id=""-50-70"">Нехило</option>
                    <option id=""-45-65"">Ощутимо</option>
                    <option id=""-40-60"">Основательно</option>
                    <option id=""-35-55"">Конкретно</option>
                    <option id=""-30-50"">Строго</option>
                    <option id=""-25-45"">Безжалостно</option>
                    <option id=""-20-40"">Бескомпромиссно</option>
                    <option id=""-20-30"">Сильно</option>
                    <option id=""-15-25"">Неистово</option>
                    <option id=""-15-20"">Безумно</option>
                    <option id=""-10-15"">Кошмарно</option>
                    <option id=""-10-10"">Чудовищно</option>
                    <option id=""-5-10"">Бессмысленно</option>
                </select>
                <input type=""submit"" value=""convert"" />
            </form>");

            return new NanoHttpResponse(StatusCode.Ok, sb.ToString().ToNoStyleHtmlBody());
        }
Esempio n. 23
0
        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();

            sb.Append("{ \n    \"posts\" : [\n");

            var posts = _expanded ? _db.GetExpandedThreadPosts(thread) : _db.GetThreadPosts(thread);

            for (int i = 0; i < posts.Length; i++)
            {
                var  p    = posts[i];
                bool last = i == posts.Length - 1;
                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    }");
                if (!last)
                {
                    sb.Append(",\n");
                }
            }

            sb.Append("\n    ]\n}");

            return(new NanoHttpResponse(StatusCode.Ok, sb.ToString(), "application/json; charset=utf-8"));
        }
Esempio n. 24
0
        public NanoHttpResponse Handle(NanoHttpRequest request)
        {
            try
            {
                var sb = new StringBuilder();

                int offset = Encoding.ASCII.GetString(request.Connection.Raw).IndexOf("\r\n\r\n");
                offset = Encoding.ASCII.GetString(request.Connection.Raw).IndexOf("\r\n\r\n", offset + 4);
                int length = request.Connection.Raw.Length;

                int stepBack = 2; // multipart ending
                int dashes = 0;

                for (int i = request.Connection.Raw.Length - 1; i > 0; i--)
                {
                    stepBack += 1;
                    byte b = request.Connection.Raw[i];
                    char c = (char)b;

                    if (c == '-')
                    {
                        dashes += 1;

                        if (dashes == 31)
                        {
                            break;
                        }
                    }
                }

                sb.Append("[img=");
                sb.Append(Convert.ToBase64String(request.Connection.Raw, offset + 4, length - offset - 4 - stepBack));
                sb.Append("]");
                string prep = "";
                if (sb.Length > 16384) prep = "Превышен лимит в 16384 символа. Такой нанопост будет хуже ретранслироваться другими.\n";
                if (sb.Length > 32768) prep = "Превышен лимит в 32768 символов. Такая картинка не отобразится.\n";
                return new NanoHttpResponse(StatusCode.Ok, prep + sb.ToString(), "text/plain; charset=utf-8");
            }

            catch
            {
                return new NanoHttpResponse(StatusCode.Ok, "Error");
            }
        }
Esempio n. 25
0
        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();

            sb.Append("{ \n    \"posts\" : [\n");

            var posts = _expanded ? _db.GetExpandedThreadPosts(thread) : _db.GetThreadPosts(thread);

            for (int i = 0; i < posts.Length; i++)
            {
                var p = posts[i];
                bool last = i == posts.Length - 1;
                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    }");
                if (!last) sb.Append(",\n");
            }

            sb.Append("\n    ]\n}");

            return new NanoHttpResponse(StatusCode.Ok, sb.ToString(), "application/json; charset=utf-8");
        }
Esempio n. 26
0
        public NanoHttpResponse Handle(NanoHttpRequest request)
        {
            var name = request.Content;

            if (name != " ")
            {
                try
                {
                    var filename = "styles/" + name.Replace(".css", "") + ".css";
                    var style    = File.ReadAllText(filename);
                    HtmlStringExtensions.Style = style;
                    File.WriteAllText("setstyle.txt", filename);
                }
                catch
                {
                }
            }

            return(new NanoHttpResponse(StatusCode.Ok, ""));
        }
Esempio n. 27
0
        private void Process(HttpConnection connection, NanoHttpRequest request)
        {
            if (request.Address == "/")
            {
                connection.Response(_root.Handle(request));
                return;
            }

            var endpoint = request.Address.Split(new char[]{'/'}, StringSplitOptions.RemoveEmptyEntries)[0];

            if (_handlers.ContainsKey(endpoint))
            {
                connection.Response(_handlers[endpoint].Handle(request));
            }

            else
            {
                connection.Response(new ErrorHandler(StatusCode.BadRequest, "Unknown endpoint: " + endpoint).Handle(request));
            }
        }
Esempio n. 28
0
        private void Process(HttpConnection connection, NanoHttpRequest request)
        {
            if (request.Address == "/")
            {
                connection.Response(_root.Handle(request));
                return;
            }

            var endpoint = request.Address.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries)[0];

            if (_handlers.ContainsKey(endpoint))
            {
                connection.Response(_handlers[endpoint].Handle(request));
            }

            else
            {
                connection.Response(new ErrorHandler(StatusCode.BadRequest, "Unknown endpoint: " + endpoint).Handle(request));
            }
        }
Esempio n. 29
0
        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)));
        }
Esempio n. 30
0
        public NanoHttpResponse Handle(NanoHttpRequest request)
        {
            var name = request.Content;

            if (name != " ")
            {

                try
                {
                    var filename = "styles/" + name.Replace(".css", "") + ".css";
                    var style = File.ReadAllText(filename);
                    HtmlStringExtensions.Style = style;
                    File.WriteAllText("setstyle.txt", filename);
                }
                catch
                {
                }
            }

            return new NanoHttpResponse(StatusCode.Ok, "");
        }
Esempio n. 31
0
        private NanoHttpResponse HandleSafe(NanoHttpRequest request)
        {
            int count = int.Parse(request.Address.Split('/').Last());

            var sb = new StringBuilder();

            sb.Append("{ \n    \"posts\" : [\n");

            var posts = _db.GetNLastPosts(count);

            for (int i = 0; i < posts.Length; i++)
            {
                var  p    = posts[i];
                bool last = i == posts.Length - 1;
                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    }");
                if (!last)
                {
                    sb.Append(",\n");
                }
            }

            sb.Append("\n    ]\n}");

            return(new NanoHttpResponse(StatusCode.Ok, sb.ToString(), "application/json; charset=utf-8"));
        }
Esempio n. 32
0
        private NanoHttpResponse HandleSafe(NanoHttpRequest request)
        {
            int count = int.Parse(request.Address.Split('/').Last());

            var sb = new StringBuilder();

            sb.Append("{ \n    \"posts\" : [\n");

            var posts = _db.GetNLastPosts(count);

            for (int i = 0; i < posts.Length; i++)
            {
                var p = posts[i];
                bool last = i == posts.Length - 1;
                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    }");
                if (!last) sb.Append(",\n");
            }

            sb.Append("\n    ]\n}");

            return new NanoHttpResponse(StatusCode.Ok, sb.ToString(), "application/json; charset=utf-8");
        }
Esempio n. 33
0
        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", @"
                    var x = new XMLHttpRequest();
                    x.open('POST', '../write/"+p.GetHash().Value+@"', true);
                    x.send(document.getElementById('reply').value);
                    x.onreadystatechange = function(){
                    location.replace('/"+(corePost?"thread":"expand")+"/" + p.GetHash().Value + @"');}
                "))).ToDiv("post", ""));

            return new NanoHttpResponse(StatusCode.Ok, sb.ToString().ToHtmlBody());
        }
Esempio n. 34
0
        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("&gt;", ">").Replace("&lt;", "<").Replace("<grn>", "").Replace("</grn>", "").Replace("&nbsp;", " ").
                                  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>&gt;&gt;" + 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>&gt;&gt;" + 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))));
        }
Esempio n. 35
0
 public NanoHttpResponse Handle(NanoHttpRequest request)
 {
     return new NanoHttpResponse(StatusCode.Ok, _stub);
 }
Esempio n. 36
0
 public NanoHttpResponse Handle(NanoHttpRequest request)
 {
     return(new NanoHttpResponse(StatusCode.Ok, _db.GetPostCount().ToString()));
 }
Esempio n. 37
0
        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)));
        }
Esempio n. 38
0
 public NanoHttpResponse Handle(NanoHttpRequest request)
 {
     return new NanoHttpResponse(
         _statusLine,
         (_statusLine.ToHeader(2) + _description.ToPar()).ToNoStyleHtmlBody());
 }
Esempio n. 39
0
 public NanoHttpResponse Handle(NanoHttpRequest request)
 {
     _db.WriteNewPosts(true);
     //NotificationHandler.Instance.AddNotification("База сообщений сохранена на диск.");
     return(new NanoHttpResponse(StatusCode.Ok, "\n"));
 }
Esempio n. 40
0
 public NanoHttpResponse Handle(NanoHttpRequest request)
 {
     _db.RewriteDbExceptHidden();
     _server.Stop();
     return(new ErrorHandler(StatusCode.Ok, "Сервер выключен, данные автоматически сохранены, посты, помеченные на удаление навсегда удалены из базы.").Handle(request));
 }
Esempio n. 41
0
        public NanoHttpResponse Handle(NanoHttpRequest request)
        {
            try
            {
                var @params = request.Address.Split('-');
                int q       = int.Parse(@params[1]);
                int s       = int.Parse(@params[2]);

                var sb = new StringBuilder();

                int offset = Encoding.ASCII.GetString(request.Connection.Raw).IndexOf("\r\n\r\n");
                offset = Encoding.ASCII.GetString(request.Connection.Raw).IndexOf("\r\n\r\n", offset + 4);
                int length = request.Connection.Raw.Length;

                int stepBack = 2; // multipart ending
                int dashes   = 0;

                for (int i = request.Connection.Raw.Length - 1; i > 0; i--)
                {
                    stepBack += 1;
                    byte b = request.Connection.Raw[i];
                    char c = (char)b;

                    if (c == '-')
                    {
                        dashes += 1;

                        if (dashes == 31)
                        {
                            break;
                        }
                    }
                }

                byte[] slice = new byte[length - offset - 4];

                for (int i = 0; i < length - offset - 4; i++)
                {
                    slice[i] = request.Connection.Raw[i + offset + 4];
                }

                slice = ImageCompressor.Compress(slice, q, s / 100.0f);
                sb.Append("<img src='data:image/jpg;base64,");
                sb.Append(Convert.ToBase64String(slice, 0, slice.Length));
                sb.Append("' >");
                string prep   = "";
                bool   tooBig = sb.Length > 64512;
                if (sb.Length > 16384)
                {
                    prep = "Превышен лимит в 16384 символа. Такой нанопост будет хуже ретранслироваться другими.\n";
                }
                if (tooBig)
                {
                    prep = "Превышен лимит в 64512 символов. Такая картикна не отобразится.\n";
                }
                prep += string.Format("Размер: {0}, base64: {1}", slice.Length, sb.Length);
                prep += "<br>";

                sb.Append("<br><br>Triple-click, Cmd/Ctrl+C<br><div style='font-size:25%'>[img=");
                sb.Append(Convert.ToBase64String(slice, 0, slice.Length));
                sb.Append("]");
                sb.Append("</div><br>");

                if (tooBig)
                {
                    sb.Clear();         // show nothing if it's invalid anyway
                }
                return(new NanoHttpResponse(StatusCode.Ok, prep + sb.ToString(), "text/html; charset=utf-8"));
            }

            catch (Exception e)
            {
                return(new NanoHttpResponse(StatusCode.Ok, "Error" + e.ToString()));
            }
        }
Esempio n. 42
0
 public NanoHttpResponse Handle(NanoHttpRequest request)
 {
     new PngMailer().FillOutbox(_db);
     return new NanoHttpResponse(StatusCode.Ok, "\n");
 }
Esempio n. 43
0
 public NanoHttpResponse Handle(NanoHttpRequest request)
 {
     return(new NanoHttpResponse(StatusCode.Ok, _stub));
 }
Esempio n. 44
0
 public NanoHttpResponse Handle(NanoHttpRequest request)
 {
     new PngMailer().FillOutbox(_db);
     return(new NanoHttpResponse(StatusCode.Ok, "\n"));
 }
Esempio n. 45
0
 public NanoHttpResponse Handle(NanoHttpRequest request)
 {
     _db.RewriteDbExceptHidden();
     _server.Stop();
     return new ErrorHandler(StatusCode.Ok, "Сервер выключен, данные автоматически сохранены, посты, помеченные на удаление навсегда удалены из базы.").Handle(request);
 }
        public NanoHttpResponse Handle(NanoHttpRequest request)
        {
            var sb = new StringBuilder();
            //ThreadViewHandler.AddHeader(sb);

            sb.Append("<br>Не применять сжатие:</br>");

            sb.Append(@"<form action=""convert"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать незримо:</br>");
            sb.Append(@"<form action=""compress/-90-90"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать слегка:</br>");
            sb.Append(@"<form action=""compress/-80-85"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать умеренно:</br>");
            sb.Append(@"<form action=""compress/-70-80"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать весьма:</br>");
            sb.Append(@"<form action=""compress/-60-75"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать нехило:</br>");
            sb.Append(@"<form action=""compress/-50-70"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать ощутимо:</br>");
            sb.Append(@"<form action=""compress/-45-65"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать основательно:</br>");
            sb.Append(@"<form action=""compress/-40-60"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать конкретно:</br>");
            sb.Append(@"<form action=""compress/-35-55"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать строго:</br>");
            sb.Append(@"<form action=""compress/-30-50"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать безжалостно:</br>");
            sb.Append(@"<form action=""compress/-25-45"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать бескомпромиссно:</br>");
            sb.Append(@"<form action=""compress/-20-40"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать сильно:</br>");
            sb.Append(@"<form action=""compress/-20-30"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать неистово:</br>");
            sb.Append(@"<form action=""compress/-15-25"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать безумно:</br>");
            sb.Append(@"<form action=""compress/-15-20"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать кошмарно:</br>");
            sb.Append(@"<form action=""compress/-10-15"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать чудовищно:</br>");
            sb.Append(@"<form action=""compress/-10-10"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать бессмысленно:</br>");
            sb.Append(@"<form action=""compress/-5-10"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            return new NanoHttpResponse(StatusCode.Ok, sb.ToString().ToNoStyleHtmlBody());
        }
Esempio n. 47
0
 private void OnConnectionAdded(HttpConnection connection)
 {
     var request = new NanoHttpRequest(connection, connection.Request);
     if (request.Method == "GET" || request.Method == "POST") Process(connection, request);
     else if (request.Method!=null) connection.Response(new ErrorHandler(StatusCode.MethodNotAllowed, "Server only supports GET and POST").Handle(request));
 }
Esempio n. 48
0
 public NanoHttpResponse Handle(NanoHttpRequest request)
 {
     return(new NanoHttpResponse(
                _statusLine,
                (_statusLine.ToHeader(2) + _description.ToPar()).ToNoStyleHtmlBody()));
 }
Esempio n. 49
0
        public NanoHttpResponse Handle(NanoHttpRequest request)
        {
            try
            {
                var @params = request.Address.Split('-');
                int q = int.Parse(@params[1]);
                int s = int.Parse(@params[2]);

                var sb = new StringBuilder();

                int offset = Encoding.ASCII.GetString(request.Connection.Raw).IndexOf("\r\n\r\n");
                offset = Encoding.ASCII.GetString(request.Connection.Raw).IndexOf("\r\n\r\n", offset + 4);
                int length = request.Connection.Raw.Length;

                int stepBack = 2; // multipart ending
                int dashes = 0;

                for (int i = request.Connection.Raw.Length - 1; i > 0; i--)
                {
                    stepBack += 1;
                    byte b = request.Connection.Raw[i];
                    char c = (char)b;

                    if (c == '-')
                    {
                        dashes += 1;

                        if (dashes == 31)
                        {
                            break;
                        }
                    }
                }

                byte[] slice = new byte[length - offset - 4];

                for (int i = 0; i < length - offset - 4; i++)
                {
                    slice[i] = request.Connection.Raw[i + offset + 4];
                }

                slice = ImageCompressor.Compress(slice, q, s/100.0f);
                sb.Append("<img src='data:image/jpg;base64,");
                sb.Append(Convert.ToBase64String(slice, 0, slice.Length));
                sb.Append("' >");
                string prep = "";
                bool tooBig = sb.Length > 64512;
                if (sb.Length > 16384) prep = "Превышен лимит в 16384 символа. Такой нанопост будет хуже ретранслироваться другими.\n";
                if (tooBig) prep = "Превышен лимит в 64512 символов. Такая картикна не отобразится.\n";
                prep += string.Format("Размер: {0}, base64: {1}", slice.Length, sb.Length);
                prep += "<br>";

                sb.Append("<br><br>Triple-click, Cmd/Ctrl+C<br><div style='font-size:25%'>[img=");
                sb.Append(Convert.ToBase64String(slice, 0, slice.Length));
                sb.Append("]");
                sb.Append("</div><br>");

                if (tooBig) sb.Clear(); // show nothing if it's invalid anyway

                return new NanoHttpResponse(StatusCode.Ok, prep + sb.ToString(), "text/html; charset=utf-8");
            }

            catch (Exception e)
            {
                return new NanoHttpResponse(StatusCode.Ok, "Error" + e.ToString(), "text/html; charset=utf-8");
            }
        }
Esempio n. 50
0
        public NanoHttpResponse Handle(NanoHttpRequest request)
        {
            var sb = new StringBuilder();

            //ThreadViewHandler.AddHeader(sb);

            sb.Append("<br>Не применять сжатие:</br>");

            sb.Append(@"<form action=""convert"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать незримо:</br>");
            sb.Append(@"<form action=""compress/-90-90"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать слегка:</br>");
            sb.Append(@"<form action=""compress/-80-85"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать умеренно:</br>");
            sb.Append(@"<form action=""compress/-70-80"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать весьма:</br>");
            sb.Append(@"<form action=""compress/-60-75"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать нехило:</br>");
            sb.Append(@"<form action=""compress/-50-70"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать ощутимо:</br>");
            sb.Append(@"<form action=""compress/-45-65"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать основательно:</br>");
            sb.Append(@"<form action=""compress/-40-60"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать конкретно:</br>");
            sb.Append(@"<form action=""compress/-35-55"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать строго:</br>");
            sb.Append(@"<form action=""compress/-30-50"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать безжалостно:</br>");
            sb.Append(@"<form action=""compress/-25-45"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать бескомпромиссно:</br>");
            sb.Append(@"<form action=""compress/-20-40"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать сильно:</br>");
            sb.Append(@"<form action=""compress/-20-30"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать неистово:</br>");
            sb.Append(@"<form action=""compress/-15-25"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать безумно:</br>");
            sb.Append(@"<form action=""compress/-15-20"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать кошмарно:</br>");
            sb.Append(@"<form action=""compress/-10-15"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать чудовищно:</br>");
            sb.Append(@"<form action=""compress/-10-10"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            sb.Append("<br>Пожать бессмысленно:</br>");
            sb.Append(@"<form action=""compress/-5-10"" method=""post"" enctype=""multipart/form-data"">
                <input type=""file"" name=""file"" />
                <input type=""submit"" value=""convert"" />
            </form>");

            return(new NanoHttpResponse(StatusCode.Ok, sb.ToString().ToNoStyleHtmlBody()));
        }
Esempio n. 51
0
        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));
        }
Esempio n. 52
0
 public NanoHttpResponse Handle(NanoHttpRequest request)
 {
     _db.WriteNewPosts(true);
     //NotificationHandler.Instance.AddNotification("База сообщений сохранена на диск.");
     return new NanoHttpResponse(StatusCode.Ok, "\n");
 }
Esempio n. 53
0
 public NanoHttpResponse Handle(NanoHttpRequest request)
 {
     return new NanoHttpResponse(StatusCode.Ok, _db.GetPostCount().ToString());
 }
 public NanoHttpResponse Handle(NanoHttpRequest request)
 {
     return(new NanoHttpResponse(StatusCode.Ok, GeneratePage()));
 }
Esempio n. 55
0
        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 = _db.RootHash;
            }

            var sb = new StringBuilder();
            AddHeader(sb);
            string s1 = "";

            if (thread.Value != _db.RootHash.Value)
            {
                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("&gt;", ">").Replace("&lt;", "<").Replace("<grn>", "").Replace("</grn>", "").Replace("&nbsp;", " ").
                        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>&gt;&gt;" + 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>&gt;&gt;"+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) +
                     ("<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(FractalMusicScript + PostScript(postScript)));
        }