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)); }
object ProcessNetInitPage(IHttpRequest req, HttpResponseHeader res) { XmlDocument doc = XmlHelper.CreateEmptyDocument (); if (req.HttpMethod == HttpMethod.POST && req.HasContentBody ()) { Dictionary<string, string> dic = HttpUtility.ParseUrlEncodedStringToDictionary (Encoding.ASCII.GetString (req.GetContentBody (MaxRequestBodySize)), Encoding.UTF8); if (dic.ContainsKey ("nodes")) { string[] lines = dic["nodes"].Replace ("\r\n", "\n").Replace ('\r', '\n').Split ('\n'); List<EndPoint> list = new List<EndPoint> (); List<string> raw_list = new List<string> (); for (int i = 0; i < lines.Length; i++) { EndPoint ep; lines[i] = lines[i].Trim (); if (lines[i].StartsWith ("%")) { ep = EndPointObfuscator.Decode (lines[i]); } else { ep = Helpers.Parse (lines[i]); } if (ep != null) { list.Add (ep); raw_list.Add (lines[i]); } } if (list.Count > 0) { p2pncs.Threading.ThreadTracer.CreateThread (delegate () { for (int i = 0; i < list.Count; i++) { if (list[i] is IPEndPoint) { if ((list[i] as IPEndPoint).Address.Equals (_node.GetCurrentPublicIPAddress ())) continue; _node.PortOpenChecker.Join (list[i]); } } for (int i = 0; i < list.Count; i++) { if (list[i] is DnsEndPoint) { IPAddress[] adrs_list = Dns.GetHostAddresses ((list[i] as DnsEndPoint).DNS); for (int k = 0; k < adrs_list.Length; k++) { if (adrs_list[k].AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork && !adrs_list[k].Equals (_node.GetCurrentPublicIPAddress ())) { _node.PortOpenChecker.Join (new IPEndPoint (adrs_list[k], (list[i] as DnsEndPoint).Port)); } } } } }, "WebApp Join Thread").Start (); XmlNode root = doc.DocumentElement.AppendChild (doc.CreateElement ("connected")); for (int i = 0; i < list.Count; i++) { XmlElement element = doc.CreateElement ("endpoint"); element.AppendChild (doc.CreateTextNode (raw_list[i].ToString ())); root.AppendChild (element); } } } else if (dic.ContainsKey ("ip") && dic.ContainsKey ("port")) { string ip_dns = dic["ip"].Trim (); string port = dic["port"].Trim (); try { if (ip_dns.Length == 0) throw new FormatException (); EndPoint ep = Helpers.Parse (ip_dns + ":" + port); if (ep == null) throw new FormatException (); if (ep is IPEndPoint && (IPAddressUtility.IsPrivate ((ep as IPEndPoint).Address) || (ep as IPEndPoint).Address.AddressFamily != System.Net.Sockets.AddressFamily.InterNetwork)) throw new FormatException (); string encoded = EndPointObfuscator.Encode (ep); doc.DocumentElement.AppendChild (doc.CreateElement ("encoded", null, new XmlNode[] { doc.CreateElement ("source", null, new[] { doc.CreateTextNode (ip_dns + ":" + port) }), doc.CreateTextNode (encoded) })); } catch { doc.DocumentElement.AppendChild (doc.CreateElement ("encoded", null, new[] { doc.CreateElement ("source", null, new[] { doc.CreateTextNode (ip_dns + ":" + port) }), doc.CreateElement ("error") })); } } } string pub_ip = ""; XmlNode[] encoded_nodes = null; if (!IPAddressUtility.IsPrivate (_node.GetCurrentPublicIPAddress ())) { pub_ip = _node.GetCurrentPublicIPAddress().ToString (); encoded_nodes = new XmlNode[] { doc.CreateTextNode (EndPointObfuscator.Encode (new IPEndPoint (_node.GetCurrentPublicIPAddress (), _node.BindUdpPort))) }; } doc.DocumentElement.AppendChild (doc.CreateElement ("ipendpoint", new string[][] { new [] {"ip", pub_ip}, new [] {"port", _node.BindUdpPort.ToString ()} }, encoded_nodes)); return _xslTemplate.Render (req, res, doc, Path.Combine (DefaultTemplatePath, "net_init.xsl")); }
object ProcessFileOpen(IHttpRequest req, HttpResponseHeader res) { if (req.HttpMethod == HttpMethod.POST && req.HasContentBody ()) { Dictionary<string, string> dic = HttpUtility.ParseUrlEncodedStringToDictionary (Encoding.ASCII.GetString (req.GetContentBody (MaxRequestBodySize)), Encoding.UTF8); string key; if (dic.TryGetValue ("id", out key)) { res[HttpHeaderNames.Location] = key; throw new HttpException (req.HttpVersion == HttpVersion.Http10 ? HttpStatusCode.Found : HttpStatusCode.SeeOther); } } XmlDocument doc = XmlHelper.CreateEmptyDocument (); return _xslTemplate.Render (req, res, doc, Path.Combine (DefaultTemplatePath, "open.xsl")); }
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)); }
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_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>"; } }