Exemple #1
0
        object ProcessManageFile(IHttpRequest req, HttpResponseHeader res)
        {
            string str_key = req.Url.AbsolutePath.Substring (8);
            Key key;
            try {
                if (str_key.Length == (DefaultAlgorithm.ECDomainBytes + 1) * 2)
                    key = Key.Parse (str_key);
                else if (str_key.Length == (DefaultAlgorithm.ECDomainBytes + 1) * 4 / 3)
                    key = Key.FromUriSafeBase64String (str_key);
                else
                    throw new HttpException (HttpStatusCode.NotFound);
            } catch {
                throw new HttpException (HttpStatusCode.NotFound);
            }

            MergeableFileHeader header;
            IMergeableFileWebUIHelper header_helper = null;
            if (req.HttpMethod == HttpMethod.POST && req.HasContentBody ()) {
                header = _node.MMLC.GetMergeableFileHeader (key);
                if (header == null)
                    throw new HttpException (HttpStatusCode.NotFound);
                header_helper = (header.Content as IMergeableFile).WebUIHelper;
                NameValueCollection c = HttpUtility.ParseUrlEncodedStringToNameValueCollection (Encoding.ASCII.GetString (req.GetContentBody (MaxRequestBodySize)), Encoding.UTF8);
                AuthServerInfo[] auth_servers = AuthServerInfo.ParseArray (c["auth"]);
                List<Key> list = new List<Key> ();
                string[] keep_array = c.GetValues ("record");
                if (keep_array != null) {
                    for (int i = 0; i < keep_array.Length; i++) {
                        list.Add (Key.FromUriSafeBase64String (keep_array[i]));
                    }
                }
                IHashComputable new_header_content = header_helper.CreateHeaderContent (c);
                string title = c["title"];
                if (title == null || title.Length == 0 || title.Length > 64)
                    throw new HttpException (HttpStatusCode.InternalServerError);
                MergeableFileHeader new_header = new MergeableFileHeader (key, title, header.Flags, header.CreatedTime, new_header_content, auth_servers);
                _node.MMLC.Manage (new_header, list.ToArray (), null);

                res[HttpHeaderNames.Location] = header_helper.ViewUrl + key.ToUriSafeBase64String ();
                throw new HttpException (req.HttpVersion == HttpVersion.Http10 ? HttpStatusCode.Found : HttpStatusCode.SeeOther);
            }

            List<MergeableFileRecord> records = _node.MMLC.GetRecords (key, out header);
            if (header == null || records == null)
                throw new HttpException (HttpStatusCode.NotFound);
            header_helper = (header.Content as IMergeableFile).WebUIHelper;

            XmlDocument doc = XmlHelper.CreateEmptyDocument ();
            doc.DocumentElement.AppendChild (XmlHelper.CreateMergeableFileElement (doc, header, records.ToArray ()));

            return _xslTemplate.Render (req, res, doc, Path.Combine (DefaultTemplatePath, header_helper.ManagePageXslFileName));
        }
Exemple #2
0
        public static XmlElement CreateMergeableFileElement(XmlDocument doc, MergeableFileHeader header, MergeableFileRecord[] records)
        {
            XmlElement root = doc.CreateElement ("file", new string[][] {
                new[] {"key", header.Key.ToUriSafeBase64String ()},
                new[] {"recordset", header.RecordsetHash.ToUriSafeBase64String ()},
                new[] {"created", header.CreatedTime.ToLocalTime().ToString (DefaultDateFormat)},
                new[] {"lastManaged", header.LastManagedTime.ToLocalTime().ToString (DefaultDateFormat)},
                new[] {"lastModified", header.LastModifiedTime.ToLocalTime().ToString (DefaultDateFormat)},
                new[] {"records", header.NumberOfRecords.ToString ()},
            }, new [] {
                doc.CreateElement ("title", null, new [] {
                    doc.CreateTextNode (header.Title)
                })
            });
            XmlNode authServers = root.AppendChild (doc.CreateElement ("auth-servers"));
            if (header.AuthServers != null && header.AuthServers.Length > 0) {
                for (int i = 0; i < header.AuthServers.Length; i++) {
                    authServers.AppendChild (doc.CreateElement ("auth-server", new string[][] {
                        new[] {"index", i.ToString ()}
                    }, new[]{
                        doc.CreateElement ("public-key", null, new[]{doc.CreateTextNode (header.AuthServers[i].PublicKey.ToBase64String ())}),
                        doc.CreateElement ("serialize", null, new[]{doc.CreateTextNode (header.AuthServers[i].ToParsableString ())})
                    }));
                }
            }

            root.SetAttribute ("type", (header.Content as IMergeableFile).WebUIHelper.ContentType);
            root.AppendChild ((header.Content as IMergeableFile).WebUIHelper.CreateHeaderElement (doc, header));

            if (records == null)
                return root;

            XmlElement records_element = (XmlElement)root.AppendChild (doc.CreateElement ("records"));
            foreach (MergeableFileRecord record in records) {
                XmlElement record_element = (XmlElement)records_element.AppendChild (doc.CreateElement ("record", new string[][] {
                    new[] {"hash", record.Hash.ToUriSafeBase64String ()},
                    new[] {"authidx", record.AuthorityIndex.ToString ()},
                    new[] {"created", record.CreatedTime.ToLocalTime().ToString (DefaultDateFormat)}
                }, null));
                record_element.AppendChild ((header.Content as IMergeableFile).WebUIHelper.CreateRecordElement (doc, record));
            }

            return root;
        }
Exemple #3
0
        object ProcessWikiPage(Node node, IHttpRequest req, HttpResponseHeader res, MergeableFileHeader header, List<MergeableFileRecord> records, string page_title)
        {
            XmlDocument doc = XmlHelper.CreateEmptyDocument ();
            MergeableFileRecord record = null;
            if (req.HttpMethod == HttpMethod.POST && req.HasContentBody ()) {
                Dictionary<string, string> dic = HttpUtility.ParseUrlEncodedStringToDictionary (Encoding.ASCII.GetString (req.GetContentBody (WebApp.MaxRequestBodySize)), Encoding.UTF8);
                record = new MergeableFileRecord (ParseNewPostData (dic),
                        DateTime.UtcNow, header.LastManagedTime, null, null, null, 0, null);
                if (dic.ContainsKey ("preview")) {
                    doc.DocumentElement.SetAttribute ("state", "preview");
                } else {
                    throw new HttpException (HttpStatusCode.Forbidden);
                }
            }

            string xsl = "wiki.xsl";
            bool edit_mode = req.QueryData.ContainsKey ("edit");
            bool history_mode = req.QueryData.ContainsKey ("history") & !edit_mode;
            if (record == null && !history_mode)
                record = GetLatestPage (records, page_title);
            if (!history_mode) {
                if (edit_mode) {
                    xsl = "wiki_edit.xsl";
                    if (req.HttpMethod == HttpMethod.GET && record != null)
                        (record.Content as WikiRecord).Name = "";
                }
                if (record == null)
                    doc.DocumentElement.AppendChild (XmlHelper.CreateMergeableFileElement (doc, header));
                else
                    doc.DocumentElement.AppendChild (XmlHelper.CreateMergeableFileElement (doc, header, new MergeableFileRecord[] { record }));
            } else if (history_mode) {
                records.RemoveAll (delegate (MergeableFileRecord ri) {
                    WikiRecord wr = (WikiRecord)ri.Content;
                    return !wr.PageName.Equals (page_title);
                });
                doc.DocumentElement.AppendChild (XmlHelper.CreateMergeableFileElement (doc, header, records.ToArray ()));
                xsl = "wiki_history.xsl";
            }
            doc.DocumentElement.AppendChild (doc.CreateElement ("page-title", null, new[] { doc.CreateTextNode (page_title) }));
            doc.DocumentElement.AppendChild (doc.CreateElement ("page-title-for-url", null, new[] { doc.CreateTextNode (WikiTitleToUrl (page_title)) }));

            return WebApp.Template.Render (req, res, doc, Path.Combine (WebApp.DefaultTemplatePath, xsl));
        }
Exemple #4
0
        public object ProcessGetRequest(Node node, IHttpRequest req, HttpResponseHeader res, MergeableFileHeader header, string url_tail)
        {
            string page_title = HttpUtility.UrlDecode (url_tail.Trim ().Trim ('/'), Encoding.UTF8);
            if (page_title == "StartPage" || page_title == "FrontPage")
                page_title = string.Empty;

            List<MergeableFileRecord> records = node.MMLC.GetRecords (header.Key, out header);
            if (records == null)
                throw new HttpException (HttpStatusCode.NotFound);

            switch (GetSpecialPageType (page_title)) {
                case SpecialPageType.None:
                    return ProcessWikiPage (node, req, res, header, records, page_title);
                case SpecialPageType.TitleIndex:
                    return ProcessWikiPage_TitleIndex (req, res, header, records);
                default:
                    throw new HttpException (HttpStatusCode.InternalServerError);
            }
        }
 public XmlElement CreateHeaderElement(XmlDocument doc, MergeableFileHeader header)
 {
     return doc.CreateElement ("bbs");
 }
 public object ProcessPutRequest(Node node, IHttpRequest req, HttpResponseHeader res, MergeableFileHeader header, string url_tail)
 {
     throw new HttpException (HttpStatusCode.NotFound);
 }
 public object ProcessGetRequest(Node node, IHttpRequest req, HttpResponseHeader res, MergeableFileHeader header, string url_tail)
 {
     return BBS.BBSWebApp.Instance.ProcessGetRequest (node, req, res, header, url_tail);
 }
Exemple #8
0
 public void Update(IDbTransaction transaction, long id, MergeableFileHeader header)
 {
     //SimpleBBSHeader h = (SimpleBBSHeader)header.Content;
     //DatabaseUtility.ExecuteNonQuery (transaction, UPDATE_HEADER_SQL, h.Title, id);
 }
Exemple #9
0
 public static XmlElement CreateMergeableFileElement(XmlDocument doc, MergeableFileHeader header)
 {
     return CreateMergeableFileElement (doc, header, null);
 }
Exemple #10
0
 public void Update(IDbTransaction transaction, long id, MergeableFileHeader header)
 {
     //WikiHeader h = header.Content as WikiHeader;
     //DatabaseUtility.ExecuteNonQuery (transaction, UPDATE_HEADER_SQL, h.Title, h.IsFreeze, id);
 }
        object Process_NewMergeableFilePage(IHttpRequest req, HttpResponseHeader res, IMergeableFileCommonProcess comm)
        {
            XmlDocument doc = XmlHelper.CreateEmptyDocument ();
            if (req.HttpMethod == HttpMethod.POST) {
                Dictionary<string, string> dic = HttpUtility.ParseUrlEncodedStringToDictionary (Encoding.ASCII.GetString (req.GetContentBody (MaxRequestBodySize)), Encoding.UTF8);
                XmlElement validationRoot = (XmlElement)doc.DocumentElement.AppendChild (doc.CreateElement ("validation"));
                string title = Helpers.GetValueSafe (dic, "title").Trim ();
                string auth = Helpers.GetValueSafe (dic, "auth").Trim ();
                string state = Helpers.GetValueSafe (dic, "state").Trim ();
                MergeableFileHeaderFlags flags = MergeableFileHeaderFlags.None;
                bool reedit = Helpers.GetValueSafe (dic, "re-edit").Length > 0;
                bool auth_status = true, header_size_over = false, record_size_over = false, title_check = true;
                try {
                    AuthServerInfo.ParseArray (auth);
                } catch {
                    auth_status = false;
                }
                if (title.Length == 0 || title.Length > 64)
                    title_check = false;

                IHashComputable header_content;
                IHashComputable[] record_contents;
                bool comm_check = comm.ParseNewPagePostData (dic, out header_content, out record_contents);

                if (comm_check && auth_status && title_check && !reedit) {
                    MergeableFileRecord[] records = null;
                    if (record_contents != null && record_contents.Length > 0) {
                        records = new MergeableFileRecord[record_contents.Length];
                        for (int i = 0; i < records.Length; i++)
                            records[i] = new MergeableFileRecord (record_contents[i], DateTime.UtcNow, DateTime.UtcNow, null, null, null, byte.MaxValue, new byte[DefaultAlgorithm.ECDomainBytes + 1]);
                    }
                    AuthServerInfo[] auth_servers = AuthServerInfo.ParseArray (auth);
                    if (state == "confirm") {
                        try {
                            MergeableFileHeader header = new MergeableFileHeader (title, flags, header_content, auth_servers);
                            header = _node.MMLC.CreateNew (header, records);
                            doc.DocumentElement.AppendChild (doc.CreateElement ("created", new string[][] {
                                new[] {"key", header.Key.ToUriSafeBase64String ()}
                            }, null));
                            state = "success";
                        } catch (OutOfMemoryException) {
                            header_size_over = true;
                            record_size_over = true;
                            state = "";
                        }
                    } else {
                        state = "confirm";
                        Key tmp_key = new Key (new byte[DefaultAlgorithm.ECDomainBytes + 1]);
                        MergeableFileHeader header = new MergeableFileHeader (tmp_key, title, flags, DateTime.UtcNow, DateTime.UtcNow, header_content, auth_servers, null, null);
                        if (Serializer.Instance.Serialize (header).Length > MMLC.MergeableFileHeaderMaxSize) {
                            header_size_over = true;
                            state = "";
                        }
                        if (records != null) {
                            for (int i = 0; i < records.Length; i++) {
                                if (Serializer.Instance.Serialize (records[i]).Length > MMLC.MergeableFileRecordMaxSize) {
                                    record_size_over = true;
                                    state = "";
                                    break;
                                }
                            }
                        }
                    }
                } else {
                    state = string.Empty;
                }

                if (header_size_over) {
                    validationRoot.AppendChild (doc.CreateElement ("error", new string[][] {
                        new string[]{"type", "header-size-over"},
                        new string[]{"limit", MMLC.MergeableFileHeaderMaxSize.ToString ()},
                    }, null));
                }
                if (record_size_over) {
                    validationRoot.AppendChild (doc.CreateElement ("error", new string[][] {
                        new string[]{"type", "record-size-over"},
                        new string[]{"limit", MMLC.MergeableFileRecordMaxSize.ToString ()},
                    }, null));
                }

                validationRoot.AppendChild (doc.CreateElement ("data", new string[][] { new[] { "name", "title" }, new[] { "status", title_check ? "ok" : "error" } }, new[] {
                    doc.CreateElement ("value", null, new[]{doc.CreateTextNode (title)}),
                    title_check ? null : doc.CreateElement ("msg", null, new[]{doc.CreateTextNode ("タイトルは1文字~64文字に収まらなければいけません")})
                }));
                validationRoot.AppendChild (doc.CreateElement ("data", new string[][] { new[] { "name", "auth" }, new[] { "status", auth_status ? "ok" : "error" } }, new[] {
                    doc.CreateElement ("value", null, new[]{doc.CreateTextNode (auth)}),
                    auth_status ? null : doc.CreateElement ("msg", null, new[]{doc.CreateTextNode ("認識できません。入力ミスがないか確認してください")})
                }));
                validationRoot.AppendChild (doc.CreateElement ("data", new string[][] { new[] { "name", "state" } }, new[] {
                    doc.CreateElement ("value", null, new[]{doc.CreateTextNode (state)})
                }));
                comm.OutputNewPageData (dic, validationRoot);
            }
            return _xslTemplate.Render (req, res, doc, Path.Combine (DefaultTemplatePath, comm.NewPageXSL));
        }
        object Process_ViewMergeableFilePage(IHttpRequest req, HttpResponseHeader res, Key key, MergeableFileHeader header, string url_tail)
        {
            if (req.HttpMethod == HttpMethod.POST) {
                if (req.QueryData.Count > 0) {
                    return (header.Content as IMergeableFile).WebUIHelper.ProcessPutRequest (_node, req, res, header, url_tail);
                }
                return Process_Post (req, res, header, url_tail);
            }

            if (!_fastView || header == null || header.RecordsetHash.IsZero ()) {
                ManualResetEvent done = new ManualResetEvent (false);
                MergeCometInfo mci = new MergeCometInfo (_node, key, url_tail);
                CometInfo info = new CometInfo (done, req, res, null, DateTime.Now + TimeSpan.FromSeconds (5), mci.CometHandler);
                _node.MMLC.StartMerge (key, delegate (object sender, MergeDoneCallbackArgs args) {
                    if (done.SafeWaitHandle.IsClosed)
                        return;
                    done.Set ();
                }, null);
                return info;
            } else {
                _node.MMLC.StartMerge (header.Key, null, null);
            }

            return (header.Content as IMergeableFile).WebUIHelper.ProcessGetRequest (_node, req, res, header, url_tail);
        }
        object Process_Post(IHttpRequest req, HttpResponseHeader res, MergeableFileHeader header, string url_tail)
        {
            WebApp.IMergeableFileCommonProcess comm = (header.Content as IMergeableFile).WebUIMergeableFileCommon;
            Dictionary<string, string> dic = HttpUtility.ParseUrlEncodedStringToDictionary (req.GetContentBody (WebApp.MaxRequestBodySize));
            res[HttpHeaderNames.ContentType] = "text/xml; charset=UTF-8";
            try {
                string auth = Helpers.GetValueSafe (dic, "auth").Trim ();
                string token = Helpers.GetValueSafe (dic, "token").Trim ();
                string answer = Helpers.GetValueSafe (dic, "answer").Trim ();
                string prev = Helpers.GetValueSafe (dic, "prev").Trim ();
                ECKeyPair privateKey = _node.MMLC.SelectPrivateKey (header.Key);
                if (header.AuthServers == null || header.AuthServers.Length == 0 || privateKey != null) {
                    _node.MMLC.AppendRecord (header.Key, new MergeableFileRecord (comm.ParseNewPostData (dic), DateTime.UtcNow, header.LastManagedTime, null, null, null, 0, null), privateKey);
                    return "<result status=\"OK\" />";
                } else {
                    byte auth_idx = byte.Parse (auth);
                    MergeableFileRecord record;
                    if (token.Length > 0 && answer.Length > 0 && prev.Length > 0) {
                        record = (MergeableFileRecord)Serializer.Instance.Deserialize (Convert.FromBase64String (prev));
                        byte[] sign = _node.MMLC.VerifyCaptchaChallenge (header.AuthServers[auth_idx], record.Hash.GetByteArray (),
                            Convert.FromBase64String (token), Encoding.ASCII.GetBytes (answer));
                        if (sign != null) {
                            record.AuthorityIndex = auth_idx;
                            record.Authentication = sign;
                            if (record.Verify (header)) {
                                _node.MMLC.AppendRecord (header.Key , record, null);
                                return "<result status=\"OK\" />";
                            } else {
                                return "<result status=\"ERROR\" code=\"1\" />";
                            }
                        }
                    }

                    record = new MergeableFileRecord (comm.ParseNewPostData (dic), DateTime.UtcNow, header.LastManagedTime, null, null, null, 0, null);
                    byte[] raw = Serializer.Instance.Serialize (record);
                    if (raw.Length > MMLC.MergeableFileRecordMaxSize)
                        throw new OutOfMemoryException ("データが多すぎます");
                    CaptchaChallengeData captchaData = _node.MMLC.GetCaptchaChallengeData (header.AuthServers[auth_idx], record.Hash.GetByteArray ());
                    return string.Format ("<result status=\"CAPTCHA\"><img>{0}</img><token>{1}</token><prev>{2}</prev></result>",
                        Convert.ToBase64String (captchaData.Data), Convert.ToBase64String (captchaData.Token), Convert.ToBase64String (raw));
                }
            } catch (Exception exception) {
                return "<result status=\"ERROR\" code=\"0\">" +
                    exception.Message.Replace ("&", "&amp;").Replace ("<", "&lt;").Replace (">", "&gt;").Replace ("\"", "&quot;") + "</result>";
            }
        }
Exemple #14
0
 public XmlElement CreateHeaderElement(XmlDocument doc, MergeableFileHeader header)
 {
     WikiHeader content = header.Content as WikiHeader;
     return doc.CreateElement ("wiki");
 }
Exemple #15
0
        object ProcessWikiPage_TitleIndex(IHttpRequest req, HttpResponseHeader res, MergeableFileHeader header, List<MergeableFileRecord> records)
        {
            XmlDocument doc = XmlHelper.CreateEmptyDocument ();
            Dictionary<string, MergeableFileRecord> dic = new Dictionary<string, MergeableFileRecord> ();
            for (int i = 0; i < records.Count; i++) {
                WikiRecord wr = records[i].Content as WikiRecord;
                MergeableFileRecord r;
                if (!dic.TryGetValue (wr.PageName, out r) || r.CreatedTime < records[i].CreatedTime)
                    dic[wr.PageName] = records[i];
            }

            List<MergeableFileRecord> list = new List<MergeableFileRecord> (dic.Values);
            doc.DocumentElement.AppendChild (XmlHelper.CreateMergeableFileElement (doc, header, list.ToArray ()));
            return WebApp.Template.Render (req, res, doc, Path.Combine (WebApp.DefaultTemplatePath, "wiki_titleindex.xsl"));
        }
Exemple #16
0
 public void Insert(IDbTransaction transaction, long id, MergeableFileHeader header)
 {
     SimpleBBSHeader h = (SimpleBBSHeader)header.Content;
     DatabaseUtility.ExecuteNonQuery (transaction, INSERT_HEADER_SQL, id);
 }
Exemple #17
0
 public Response(MergeableFileHeader[] headers)
 {
     _headers = headers;
 }
Exemple #18
0
        public object ProcessGetRequest(Node node, IHttpRequest req, HttpResponseHeader res, MergeableFileHeader header, string tail_url)
        {
            List<MergeableFileRecord> records = node.MMLC.GetRecords (header.Key, out header);
            if (records == null)
                throw new HttpException (HttpStatusCode.NotFound);

            using (ISessionTransaction transaction = req.Session.BeginTransaction (System.Data.IsolationLevel.Serializable)) {
                string session_state_key = header.Key.ToBase64String () + "/read";
                Key[] keys = transaction.ReadState (session_state_key) as Key[];
                HashSet<Key> readSet = (keys == null ? new HashSet<Key> () : new HashSet<Key> (keys));
                List<Key> currentSet = new List<Key> (records.Count);
                for (int i = 0; i < records.Count; i ++) {
                    SimpleBBSRecord content = records[i].Content as SimpleBBSRecord;
                    if (content == null) continue;
                    content.IsNew = readSet.Add (records[i].Hash);
                    currentSet.Add (records[i].Hash);
                }
                readSet.IntersectWith (currentSet);
                keys = new Key[readSet.Count];
                readSet.CopyTo (keys);
                transaction.UpdateState (session_state_key, keys);
                transaction.Commit ();
            }

            XmlDocument doc = XmlHelper.CreateEmptyDocument ();
            doc.DocumentElement.AppendChild (XmlHelper.CreateMergeableFileElement (doc, header, records.ToArray ()));
            return WebApp.Template.Render (req, res, doc, Path.Combine (WebApp.DefaultTemplatePath, "bbs_view.xsl"));
        }