mirror of
https://github.com/SoftEtherVPN/SoftEtherVPN.git
synced 2025-07-07 00:04:57 +03:00
v4.03-9411-rtm
This commit is contained in:
939
src/BuildUtil/CoreUtil/MultiLang.cs
Normal file
939
src/BuildUtil/CoreUtil/MultiLang.cs
Normal file
@ -0,0 +1,939 @@
|
||||
// CoreUtil
|
||||
//
|
||||
// Copyright (C) 2012-2014 Daiyuu Nobori. All Rights Reserved.
|
||||
// Copyright (C) 2012-2014 SoftEther VPN Project at University of Tsukuba. All Rights Reserved.
|
||||
// Comments: Tetsuo Sugiyama, Ph.D.
|
||||
//
|
||||
//
|
||||
// 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 IT IN OTHER COUNTRIES. IMPORTING THIS
|
||||
// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
|
||||
// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
|
||||
// COUNTRIES MIGHT BE RESTRICTED.
|
||||
//
|
||||
//
|
||||
// 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.
|
||||
|
||||
|
||||
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<KeyValuePair<string, string>> 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<KeyValuePair<string, string>>())
|
||||
{
|
||||
}
|
||||
public MultiLang(Page currentPage, bool fast, string basicHostName, List<KeyValuePair<string, string>> 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("<!-- ml:{0} -->", 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<KeyValuePair<string, CoreLanguageClass>> langKeys = new List<KeyValuePair<string, CoreLanguageClass>>();
|
||||
public readonly List<KeyValuePair<string, string>> ReplaceList = null;
|
||||
public const string TagPure = "<!-- ml:pure -->";
|
||||
public const string TagEndPure = "<!-- ml:endpure -->";
|
||||
public bool DisableFilter = false;
|
||||
public Page Page;
|
||||
|
||||
static MultiLanguageFilterStream()
|
||||
{
|
||||
langKeys.Add(new KeyValuePair<string, CoreLanguageClass>("[j]", CoreLanguageList.Japanese));
|
||||
langKeys.Add(new KeyValuePair<string, CoreLanguageClass>("[e]", CoreLanguageList.English));
|
||||
langKeys.Add(new KeyValuePair<string, CoreLanguageClass>("[/]", null));
|
||||
}
|
||||
|
||||
Stack<CoreLanguageClass> stack = new Stack<CoreLanguageClass>();
|
||||
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<string, string> 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<string, CoreLanguageClass> 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, "<meta http-equiv=\"Content-Language\" content=\"ja\" />",
|
||||
string.Format("<meta http-equiv=\"Content-Language\" content=\"{0}\" />", lang), false);
|
||||
}
|
||||
|
||||
ret = Str.ReplaceStr(ret, "<html>", string.Format("<html lang=\"{0}\">", lang), false);
|
||||
|
||||
next = 0;
|
||||
while (true)
|
||||
{
|
||||
i = Str.SearchStr(ret, "<link rel=\"stylesheet\" href=\"", next, false);
|
||||
if (i == -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
next = i + 1;
|
||||
int j = 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("<link rel=\"stylesheet\" href=\"{0}\" type=\"text/css\" />", 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<KeyValuePair<string, string>> 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
|
||||
// Department of Computer Science has dozens of overly-enthusiastic geeks.
|
||||
// Join us: http://www.tsukuba.ac.jp/english/admission/
|
Reference in New Issue
Block a user