// CoreUtil // // Copyright (C) 2012-2014 Daiyuu Nobori. All Rights Reserved. // Copyright (C) 2012-2014 SoftEther VPN Project at University of Tsukuba. All Rights Reserved. // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // version 2 as published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License version 2 // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // // THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE // AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE. // // // THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN, // UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY, // MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS // SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS // SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER // CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL // DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING, // MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR // SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND // CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO // EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO, // JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION // AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN // THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE. // // USE ONLY IN JAPAN. DO NOT USE THIS SOFTWARE IN ANOTHER COUNTRY UNLESS // YOU HAVE A CONFIRMATION THAT THIS SOFTWARE DOES NOT VIOLATE ANY // CRIMINAL LAWS OR CIVIL RIGHTS IN THAT PARTICULAR COUNTRY. USING THIS // SOFTWARE IN OTHER COUNTRIES IS COMPLETELY AT YOUR OWN RISK. THE // SOFTETHER VPN PROJECT HAS DEVELOPED AND DISTRIBUTED THIS SOFTWARE TO // COMPLY ONLY WITH THE JAPANESE LAWS AND EXISTING CIVIL RIGHTS INCLUDING // PATENTS WHICH ARE SUBJECTS APPLY IN JAPAN. OTHER COUNTRIES' LAWS OR // CIVIL RIGHTS ARE NONE OF OUR CONCERNS NOR RESPONSIBILITIES. WE HAVE // NEVER INVESTIGATED ANY CRIMINAL REGULATIONS, CIVIL LAWS OR // INTELLECTUAL PROPERTY RIGHTS INCLUDING PATENTS IN ANY OF OTHER 200+ // COUNTRIES AND TERRITORIES. BY NATURE, THERE ARE 200+ REGIONS IN THE // WORLD, WITH DIFFERENT LAWS. IT IS IMPOSSIBLE TO VERIFY EVERY // COUNTRIES' LAWS, REGULATIONS AND CIVIL RIGHTS TO MAKE THE SOFTWARE // COMPLY WITH ALL COUNTRIES' LAWS BY THE PROJECT. EVEN IF YOU WILL BE // SUED BY A PRIVATE ENTITY OR BE DAMAGED BY A PUBLIC SERVANT IN YOUR // COUNTRY, THE DEVELOPERS OF THIS SOFTWARE WILL NEVER BE LIABLE TO // RECOVER OR COMPENSATE SUCH DAMAGES, CRIMINAL OR CIVIL // RESPONSIBILITIES. NOTE THAT THIS LINE IS NOT LICENSE RESTRICTION BUT // JUST A STATEMENT FOR WARNING AND DISCLAIMER. // // // SOURCE CODE CONTRIBUTION // ------------------------ // // Your contribution to SoftEther VPN Project is much appreciated. // Please send patches to us through GitHub. // Read the SoftEther VPN Patch Acceptance Policy in advance: // http://www.softether.org/5-download/src/9.patch // // // DEAR SECURITY EXPERTS // --------------------- // // If you find a bug or a security vulnerability please kindly inform us // about the problem immediately so that we can fix the security problem // to protect a lot of users around the world as soon as possible. // // Our e-mail address for security reports is: // softether-vpn-security [at] softether.org // // Please note that the above e-mail address is not a technical support // inquiry address. If you need technical assistance, please visit // http://www.softether.org/ and ask your question on the users forum. // // Thank you for your cooperation. // // // NO MEMORY OR RESOURCE LEAKS // --------------------------- // // The memory-leaks and resource-leaks verification under the stress // test has been passed before release this source code. using System; using System.Data; using System.Data.Sql; using System.Data.SqlClient; using System.Data.SqlTypes; using System.Text; using System.Configuration; using System.Collections; using System.Collections.Generic; using System.Security.Cryptography; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using System.IO; using System.Drawing; using System.Drawing.Imaging; using System.Drawing.Drawing2D; using System.Web.Mail; using System.Threading; using System.Xml; using System.Xml.Schema; using System.Xml.Serialization; using CoreUtil; public static class AspUtil { public static void Redirect(Page page, string url) { Redirect(page, url, true); } public static void Redirect(Page page, string url, bool endSession) { MultiLang ml = new MultiLang(page, true); ml.Redirect(url, true); } public static string GetCurrentRequestUrl(Page page) { string s = (string)page.Request.Headers["SEISAPI_PHYSICAL_URL"]; if (Str.IsEmptyStr(s) == false) { string[] tokens = s.Split('?'); return tokens[0]; } return page.Request.Path; } public static string GetCurrentPhysicalFilePathForUser(Page page) { string s = (string)page.Request.Headers["SEISAPI_ORIGINAL_FILEPATH"]; if (Str.IsEmptyStr(s) == false) { return s; } return page.Request.PhysicalPath; } public static string RemoveDefaultHtml(string url) { string tmp = url.ToLower(); if (tmp.EndsWith("/default.asp") || tmp.EndsWith("/default.aspx") || tmp.EndsWith("/default.htm") || tmp.EndsWith("/default.html")) { return GetUrlDirNameFromPath(url); } else { return url; } } public static string GetUrlDirNameFromPath(string url) { string ret = ""; string[] strs = url.Split('/'); int i; if (strs.Length >= 1) { for (i = 0; i < strs.Length - 1; i++) { ret += strs[i] + "/"; } } return ret; } public static string WebPathToFilePath(System.Web.UI.Page page, string path) { string appRootFilePath = page.Request.PhysicalApplicationPath; string appRootVirtualPath = page.Request.ApplicationPath; string ret; path = RemoveDefaultHtml(path); if (path.ToUpper().StartsWith(appRootVirtualPath.ToUpper()) == false) { return null; } path = path.Substring(appRootVirtualPath.Length).Replace("/", "\\"); if (path.StartsWith("\\")) { path = path.Substring(1); } ret = appRootFilePath + path; if (ret.IndexOf("..") != -1) { return null; } if (ret.EndsWith("\\")) { ret = GetDefaultDocumentIfExists(ret); } return ret; } public static string GetDefaultDocumentIfExists(string dir) { string[] targets = { "default.aspx", "default.asp", "default.html", "default.htm", "index.html", "index.htm", }; foreach (string s in targets) { string name = dir + s; if (IsFileExists(name)) { return name; } } return null; } public static bool IsFileExists(string name) { return File.Exists(name); } } public class MultiLang { public readonly Page Page; public readonly HttpRequest Request; public readonly HttpResponse Response; public readonly bool IsUrlModefied; public readonly string OriginalUrl; public readonly string PhysicalUrl; public readonly bool IsFilenameModified; public readonly string OriginalFileName; public readonly string OriginalFilePath; public readonly string Args; public readonly CoreLanguageClass CurrentLanguage; public readonly CoreLanguageClass ContentsPrintLanguage; public readonly string CurrentLanguageCode; public readonly bool IsCurrentLanguageSupported; public readonly string GoogleTranslateUrl; public readonly string OriginalFullUrl; public readonly bool IsSSL; public readonly string Host; public readonly string BasicHostName; MultiLanguageFilterStream mfs; public readonly List> ReplaceList; public bool DisableFilter { get { return mfs.DisableFilter; } set { mfs.DisableFilter = value; } } public readonly string HtmlBody = ""; public readonly string HtmlFileName = ""; static MultiLang() { CoreLanguageList.RegardsJapanAsJP = true; } public bool IsJapanese { get { if (this.CurrentLanguage == CoreLanguageList.Japanese) { return true; } return false; } } public bool IsJapanesePrinting { get { if (this.ContentsPrintLanguage == CoreLanguageList.Japanese) { return true; } return false; } } public void Redirect(string url, bool endSession) { url = ConvertPath(url); if (url.StartsWith("http://") || url.StartsWith("https://") || url.StartsWith("ftp://") || url.StartsWith("/")) { } else { string originalUrl = OriginalUrl; if (originalUrl.EndsWith("/")) { } else { int i; for (i = originalUrl.Length - 1; i >= 0; i--) { if (originalUrl[i] == '/' || originalUrl[i] == '\\') { originalUrl = originalUrl.Substring(0, i + 1); break; } } } url = originalUrl + url; } Response.Redirect(url, endSession); } public MultiLang(Page currentPage) : this(currentPage, false) { } public MultiLang(Page currentPage, bool fast) : this(currentPage, fast, null) { } public MultiLang(Page currentPage, bool fast, string basicHostName) : this(currentPage, fast, basicHostName, new List>()) { } public MultiLang(Page currentPage, bool fast, string basicHostName, List> replaceList) { this.Page = currentPage; this.Request = Page.Request; this.Response = Page.Response; this.BasicHostName = basicHostName; string tmp = Page.Request.ServerVariables["HTTPS"]; string hostRaw = Page.Request.Headers["Host"]; this.ReplaceList = replaceList; bool isSsl = false; string[] tokens; string host = ""; tokens = hostRaw.Split(':'); if (tokens.Length >= 1) { host = tokens[0]; } host = host.ToLower(); if (tmp != null) { if (tmp.Equals("on", StringComparison.InvariantCultureIgnoreCase)) { isSsl = true; } } this.IsSSL = isSsl; this.Host = host; this.IsUrlModefied = Str.StrToBool((string)Request.Headers["SEISAPI_MODIFIED_URL"]); this.OriginalUrl = (string)Request.Headers["SEISAPI_ORIGINAL_URL"]; int i; i = this.OriginalUrl.IndexOf("?"); if (i != -1) { this.OriginalUrl = this.OriginalUrl.Substring(0, i); } if (Str.IsEmptyStr(this.OriginalUrl) || this.IsUrlModefied == false) { this.OriginalUrl = AspUtil.RemoveDefaultHtml(AspUtil.GetCurrentRequestUrl(Page)); } string s = (string)Request.Headers["SEISAPI_ORIGINAL_FILENAME"]; if (Str.IsEmptyStr(s) == false) { this.IsFilenameModified = true; this.OriginalFileName = s; this.OriginalFilePath = (string)Request.Headers["SEISAPI_ORIGINAL_FILEPATH"]; } string langCode = GetCurrentLangCodeFromPath(this.OriginalUrl); this.CurrentLanguage = CoreLanguageList.GetLanguageClassByName(langCode); this.CurrentLanguageCode = CurrentLanguage.Name; try { HtmlFileName = AspUtil.WebPathToFilePath(currentPage, AspUtil.GetCurrentRequestUrl(currentPage)); } catch { } if (this.IsFilenameModified) { HtmlFileName = Path.Combine(Path.GetDirectoryName(HtmlFileName), Path.GetFileName(OriginalFilePath)); } try { if (fast == false) { HtmlBody = File.ReadAllText(HtmlFileName, Str.Utf8Encoding); } } catch { } PhysicalUrl = AspUtil.RemoveDefaultHtml(AspUtil.GetCurrentRequestUrl((currentPage))); Args = currentPage.Request.ServerVariables["QUERY_STRING"]; if (CurrentLanguage == CoreLanguageList.Japanese) { IsCurrentLanguageSupported = true; } else { IsCurrentLanguageSupported = Str.SearchStr(HtmlBody, string.Format("", CurrentLanguage.Name), 0, false) != -1; } GoogleTranslateUrl = string.Format("http://translate.google.com/translate?js=n&prev=_t&hl=en&ie=UTF-8&layout=2&eotf=1&sl=ja&tl={1}&u={0}", HttpUtility.UrlEncode((isSsl ? "https://" : "http://") + host + this.OriginalUrl, Str.Utf8Encoding), this.CurrentLanguageCode); OriginalFullUrl = (isSsl ? "https://" : "http://") + host + this.OriginalUrl; ContentsPrintLanguage = this.CurrentLanguage; if (IsCurrentLanguageSupported == false) { ContentsPrintLanguage = CoreLanguageList.Japanese; } if (fast == false) { mfs = new MultiLanguageFilterStream(Response.Filter, ContentsPrintLanguage, this.CurrentLanguage, this.BasicHostName, this.ReplaceList); mfs.Page = Page; Response.Filter = mfs; } } public string ConvertPath(string url) { return ConvertPath(url, this.CurrentLanguage); } public string ConvertPath(string url, CoreLanguageClass lang) { string ja = CoreLanguageList.Japanese.Name; if (url.StartsWith("/" + ja, StringComparison.InvariantCultureIgnoreCase)) { url = "/" + lang.Name + url.Substring(ja.Length + 1); } return url; } public string GetPathForLanguage(CoreLanguageClass lang) { string url = PhysicalUrl; return ConvertPath(url, lang); } public string GetFullUrlForLanguage(CoreLanguageClass lang) { string url = (IsSSL ? "https://" : "http://") + Host + GetPathForLanguage(lang); if (Str.IsEmptyStr(Args) == false) { url += "?" + Args; } return url; } public string ProcStr(string str) { return ProcStr(str, ContentsPrintLanguage); } public static string ProcStrDefault(string str) { return ProcStr(str, CoreLanguageClass.CurrentThreadLanguageClass); } public static string ProcStr(string str, CoreLanguageClass lang) { return ProcStr(str, lang, lang); } public static string ProcStr(string str, CoreLanguageClass lang, CoreLanguageClass langPure) { MultiLanguageFilterStream st = new MultiLanguageFilterStream(null, lang, langPure, null, null); return st.FilterString(str); } public static string GetCurrentLangCodeFromPath(string str) { char[] sps = { '/', '?', }; string[] tokens = str.Split(sps, StringSplitOptions.RemoveEmptyEntries); if (tokens.Length >= 1) { return tokens[0].ToLower(); } return CoreLanguageList.Japanese.Name; } } public static class MultiString { public const string ChangeLanguage = "[j]Select Language[e]Select Language[/]"; public const string LanguageNotSupported = "[j]申し訳ございませんが、以下のコンテンツは現在日本語で公開されていません。[e]Unfortunately, following contents are not published in English yet. [/]"; public const string ThisIsTranslatedByMachine = "Following contents are translated automatically by Google Translate."; public const string GoogleTranslate = "[j]Google で翻訳[e]Click here to translate the contents into English by Google Now[/]"; public const string ShowSrc = "Show the original page"; public static string GetStr(string srcStr, CoreLanguageClass lang) { return MultiLang.ProcStr(srcStr, lang); } } public class MultiLanguageFilterStream : Stream { public static readonly List> langKeys = new List>(); public readonly List> ReplaceList = null; public const string TagPure = ""; public const string TagEndPure = ""; public bool DisableFilter = false; public Page Page; static MultiLanguageFilterStream() { langKeys.Add(new KeyValuePair("[j]", CoreLanguageList.Japanese)); langKeys.Add(new KeyValuePair("[e]", CoreLanguageList.English)); langKeys.Add(new KeyValuePair("[/]", null)); } Stack stack = new Stack(); CoreLanguageClass currentBodyLanguage { get { if (stack.Count == 0) { return null; } else { return stack.ToArray()[0]; } } } bool isLang(CoreLanguageClass lang) { CoreLanguageClass[] langList = stack.ToArray(); foreach (CoreLanguageClass c in langList) { if (c != lang) { return false; } } return true; } CoreLanguageClass lastBodyLanguage { get { if (stack.Count == 0) { return null; } else { return stack.Peek(); } } } public string FilterString(string src) { string[] strList = Str.DivideStringMulti(src, true, TagPure, TagEndPure); bool b = false; StringBuilder ret = new StringBuilder(); foreach (string str in strList) { if (str == TagPure) { b = true; } else if (str == TagEndPure) { b = false; } ret.Append(filterStringInner(str, b ? this.currentLanguagePure : this.currentLanguage, this.currentLanguagePure)); } return ret.ToString(); } string filterStringInner(string src, CoreLanguageClass useLang, CoreLanguageClass useLangPure) { int i; string ret = src; if (Str.IsEmptyStr(basicHostName) == false) { ret = Str.ReplaceStr(ret, "=\"/\"", "=\"http://" + basicHostName + "/\"", false); ret = Str.ReplaceStr(ret, "=\'/\'", "=\'http://" + basicHostName + "/\'", false); ret = Str.ReplaceStr(ret, "=\"/" + CoreLanguageList.Japanese.Name + "/\"", "=\"http://" + basicHostName + "/" + useLangPure.Name + "/\"", false); ret = Str.ReplaceStr(ret, "=\'/" + CoreLanguageList.Japanese.Name + "/\'", "=\'http://" + basicHostName + "/" + useLangPure.Name + "/\'", false); } ret = Str.ReplaceStr(ret, "=\"/" + CoreLanguageList.Japanese.Name + "/", "=\"/" + useLangPure.Name + "/", false); ret = Str.ReplaceStr(ret, "=\'/" + CoreLanguageList.Japanese.Name + "/", "=\'/" + useLangPure.Name + "/", false); ret = Str.ReplaceStr(ret, "_lm_" + CoreLanguageList.Japanese.Name, "_lm_" + useLang.Name, false); if (this.ReplaceList != null) { foreach (KeyValuePair p in this.ReplaceList) { ret = Str.ReplaceStr(ret, p.Key, p.Value, false); } } StringBuilder ret2 = new StringBuilder(); int next = 0; while (true) { int min = int.MaxValue; int j = -1; for (i = 0; i < langKeys.Count; i++) { int r = Str.SearchStr(ret, langKeys[i].Key, next, false); if (r != -1) { if (r < min) { j = i; min = r; } } } if (j != -1) { KeyValuePair v = langKeys[j]; if (currentBodyLanguage == null || isLang(useLang)) { ret2.Append(ret.Substring(next, min - next)); } if (v.Value != null) { if (lastBodyLanguage == null || v.Value.Id <= lastBodyLanguage.Id) { stack.Push(v.Value); } else { stack.Pop(); stack.Push(v.Value); } } else { stack.Pop(); } next = min + v.Key.Length; } else { if (currentBodyLanguage == null || isLang(useLang)) { ret2.Append(ret.Substring(next, ret.Length - next)); } break; } } ret = ret2.ToString(); string lang = useLangPure != CoreLanguageList.Japanese ? useLangPure.Name : "ja"; if (useLangPure != CoreLanguageList.Japanese) { ret = Str.ReplaceStr(ret, "", string.Format("", lang), false); } ret = Str.ReplaceStr(ret, "", string.Format("", lang), false); next = 0; while (true) { i = Str.SearchStr(ret, "", next, false); if (j == -1) { break; } string linkStr = ret.Substring(i, j - i + 2 - 1); int k = Str.SearchStr(linkStr, "href=\"", 0, false); if (k != -1) { int m = Str.SearchStr(linkStr, "\"", k + 6, false); if (m != -1) { string fileName = linkStr.Substring(k + 6, m - k - 6); fileName = Str.ReplaceStr(fileName, ".css", "_" + lang + ".css", false); string linkStr2 = string.Format("", fileName); ret = ret.Substring(0, j + 2) + linkStr2 + ret.Substring(j + 2); next = j + 2 + linkStr2.Length; } } } return ret; } Stream baseStream; long position; CoreLanguageClass currentLanguage; CoreLanguageClass currentLanguagePure; string basicHostName; public override bool CanRead { get { return true; } } public override bool CanSeek { get { return true; } } public override bool CanWrite { get { return true; } } public override void Flush() { baseStream.Flush(); } public override long Length { get { return 0; } } public override long Position { get { return position; } set { position = value; } } public override long Seek(long offset, SeekOrigin origin) { return baseStream.Seek(offset, origin); } public override void SetLength(long value) { baseStream.SetLength(value); } public MultiLanguageFilterStream(Stream baseStream, CoreLanguageClass currentLanguage, CoreLanguageClass currentLanguagePure, string basicHostName, List> replaceList) { this.baseStream = baseStream; this.currentLanguage = currentLanguage; this.currentLanguagePure = currentLanguagePure; this.basicHostName = basicHostName; this.ReplaceList = replaceList; } public override int Read(byte[] buffer, int offset, int count) { return baseStream.Read(buffer, offset, count); } string savedString = ""; public override void Write(byte[] buffer, int offset, int count) { if (DisableFilter) { baseStream.Write(buffer, offset, count); return; } byte[] data = new byte[count]; Buffer.BlockCopy(buffer, offset, data, 0, count); string inSrc = savedString + ByteDataToString(data);// Str.Utf8Encoding.GetString(data); savedString = ""; if (inSrc.Length >= 2) { int len = inSrc.Length; string last2 = inSrc.Substring(len - 2, 2); string last1 = inSrc.Substring(len - 1, 1); if (last1 == "[") { inSrc = inSrc.Substring(0, len - 1); savedString = last1; } else if (Str.InStr(last2, "[")) { inSrc = inSrc.Substring(0, len - 2); savedString = last2; } } string inStr = FilterString(inSrc); data = StringToByteData(inStr);// Str.Utf8Encoding.GetBytes(inStr); if (data.Length >= 1) { baseStream.Write(data, 0, data.Length); //byte[] t = Str.Utf8Encoding.GetBytes("" + count.ToString() + ""); //baseStream.Write(t, 0, t.Length); } } public static string ByteDataToString(byte[] data) { StringBuilder sb = new StringBuilder(); foreach (byte b in data) { if (b <= 0x7f && b != (byte)('\\')) { sb.Append((char)b); } else { sb.Append("\\" + ((uint)b).ToString("X2")); } } return sb.ToString(); } public byte[] StringToByteData(string str) { int i, len; len = str.Length; Buf b = new Buf(); for (i = 0; i < len; i++) { char c = str[i]; if (c == '\\') { string tmp = ""; //try { tmp = "" + str[i + 1] + str[i + 2]; } /*catch (Exception ex) { tmp += "|err=" + ex.Message + ",len=" + len + ",i=" + i + "|src=" + str + "|"; byte[] aa = Str.Utf8Encoding.GetBytes(tmp); b.Write(aa); }*/ i += 2; //try { b.WriteByte(byte.Parse(tmp, System.Globalization.NumberStyles.HexNumber)); } //catch { } } else { b.WriteByte((byte)c); } } return b.ByteData; } }