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)); }
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; }
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)); }
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); }
public void Update(IDbTransaction transaction, long id, MergeableFileHeader header) { //SimpleBBSHeader h = (SimpleBBSHeader)header.Content; //DatabaseUtility.ExecuteNonQuery (transaction, UPDATE_HEADER_SQL, h.Title, id); }
public static XmlElement CreateMergeableFileElement(XmlDocument doc, MergeableFileHeader header) { return CreateMergeableFileElement (doc, header, null); }
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 ("&", "&").Replace ("<", "<").Replace (">", ">").Replace ("\"", """) + "</result>"; } }
public XmlElement CreateHeaderElement(XmlDocument doc, MergeableFileHeader header) { WikiHeader content = header.Content as WikiHeader; return doc.CreateElement ("wiki"); }
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")); }
public void Insert(IDbTransaction transaction, long id, MergeableFileHeader header) { SimpleBBSHeader h = (SimpleBBSHeader)header.Content; DatabaseUtility.ExecuteNonQuery (transaction, INSERT_HEADER_SQL, id); }
public Response(MergeableFileHeader[] headers) { _headers = headers; }
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")); }