diff --git a/shadowsocks-csharp/Controller/UpdateChecker.cs b/shadowsocks-csharp/Controller/UpdateChecker.cs index 3df0c817..69263c8f 100755 --- a/shadowsocks-csharp/Controller/UpdateChecker.cs +++ b/shadowsocks-csharp/Controller/UpdateChecker.cs @@ -21,7 +21,7 @@ public class UpdateChecker public const string Name = "ShadowsocksR"; public const string Copyright = "Copyright © BreakWa11 2017. Fork from Shadowsocks by clowwindy"; - public const string Version = "4.8.1"; + public const string Version = "4.9.0"; #if !_DOTNET_4_0 public const string NetVer = "2.0"; #elif !_CONSOLE @@ -50,7 +50,7 @@ public void CheckUpdate(Configuration config) http.Headers.Add("User-Agent", String.IsNullOrEmpty(config.proxyUserAgent) ? "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.3319.102 Safari/537.36" - : config.proxyUserAgent); + : config.proxyUserAgent); if (UseProxy) { WebProxy proxy = new WebProxy(IPAddress.Loopback.ToString(), config.localPort); diff --git a/shadowsocks-csharp/Controller/UpdateFreeNode.cs b/shadowsocks-csharp/Controller/UpdateFreeNode.cs index 5e0011cf..7084011a 100644 --- a/shadowsocks-csharp/Controller/UpdateFreeNode.cs +++ b/shadowsocks-csharp/Controller/UpdateFreeNode.cs @@ -17,10 +17,11 @@ public class UpdateFreeNode public event EventHandler NewFreeNodeFound; public string FreeNodeResult; + public ServerSubscribe subscribeTask; public const string Name = "ShadowsocksR"; - public void CheckUpdate(Configuration config, string URL, bool use_proxy) + public void CheckUpdate(Configuration config, ServerSubscribe subscribeTask, bool use_proxy) { FreeNodeResult = null; try @@ -45,6 +46,8 @@ public void CheckUpdate(Configuration config, string URL, bool use_proxy) http.Proxy = null; } //UseProxy = !UseProxy; + this.subscribeTask = subscribeTask; + string URL = subscribeTask.URL; http.DownloadStringCompleted += http_DownloadStringCompleted; http.DownloadStringAsync(new Uri(URL != null ? URL : UpdateURL)); } @@ -124,7 +127,7 @@ public bool Next() else { _URL = _serverSubscribes[0].URL; - _updater.CheckUpdate(_config, _URL, _use_proxy); + _updater.CheckUpdate(_config, _serverSubscribes[0], _use_proxy); _serverSubscribes.RemoveAt(0); return true; } diff --git a/shadowsocks-csharp/Data/cn.txt b/shadowsocks-csharp/Data/cn.txt index a9643f86..ffac358f 100644 --- a/shadowsocks-csharp/Data/cn.txt +++ b/shadowsocks-csharp/Data/cn.txt @@ -207,6 +207,7 @@ Proxy With Rule=规则代理 Subscribe Settings=订阅设置 URL=网址 Group name=组名 +Last Update=最近更新 Auto update=自动更新 # Messages @@ -238,6 +239,6 @@ Failed to update registry=无法修改注册表 System Proxy On: =系统代理已启用: Running: Port {0}=正在运行:端口 {0} Password NOT match=密码不匹配 -Update subscribe SSR node success=SSR服务器订阅更新成功 -Update subscribe SSR node failure=SSR服务器订阅更新失败 +Update subscribe {0} success=服务器订阅 {0} 更新成功 +Update subscribe {0} failure=服务器订阅 {0} 更新失败 Success=成功 diff --git a/shadowsocks-csharp/Data/zh-tw.txt b/shadowsocks-csharp/Data/zh-tw.txt index ef4b9c40..562d6622 100644 --- a/shadowsocks-csharp/Data/zh-tw.txt +++ b/shadowsocks-csharp/Data/zh-tw.txt @@ -195,6 +195,7 @@ Proxy With Rule=規則代理 Subscribe Settings=訂閱設置 URL=網址 Group name=組名 +Last Update=最近更新 Auto update=自動更新 # Messages @@ -226,6 +227,6 @@ Failed to update registry=無法修改註冊表 System Proxy On: =系統代理已啟用: Running: Port {0}=正在運行:連接埠 {0} Password NOT match=密碼不匹配 -Update subscribe SSR node success=SSR伺服器訂閱更新成功 -Update subscribe SSR node failure=SSR伺服器訂閱更新失敗 +Update subscribe {0} success=伺服器訂閱 {0} 更新成功 +Update subscribe {0} failure=伺服器訂閱 {0} 更新失敗 Success=成功 diff --git a/shadowsocks-csharp/Model/Configuration.cs b/shadowsocks-csharp/Model/Configuration.cs index e79bf58e..2fbcb0d2 100755 --- a/shadowsocks-csharp/Model/Configuration.cs +++ b/shadowsocks-csharp/Model/Configuration.cs @@ -71,6 +71,7 @@ public class ServerSubscribe public string URL = DEFAULT_FEED_URL; public string Group; + public UInt64 LastUpdateTime; } public class GlobalConfiguration diff --git a/shadowsocks-csharp/Obfs/AuthChain.cs b/shadowsocks-csharp/Obfs/AuthChain.cs index 7a4ab9a2..87ec15e0 100644 --- a/shadowsocks-csharp/Obfs/AuthChain.cs +++ b/shadowsocks-csharp/Obfs/AuthChain.cs @@ -10,10 +10,12 @@ namespace Shadowsocks.Obfs class xorshift128plus { protected UInt64 v0, v1; + protected int init_loop; - public xorshift128plus() + public xorshift128plus(int init_loop_ = 4) { v0 = v1 = 0; + init_loop = init_loop_; } public UInt64 next() @@ -42,7 +44,7 @@ public void init_from_bin(byte[] bytes, int datalength) BitConverter.GetBytes((ushort)datalength).CopyTo(fill_bytes, 0); v0 = BitConverter.ToUInt64(fill_bytes, 0); v1 = BitConverter.ToUInt64(fill_bytes, 8); - for (int i = 0; i < 4; ++i) + for (int i = 0; i < init_loop; ++i) { next(); } @@ -202,6 +204,11 @@ public void PackData(byte[] data, int datalength, byte[] outdata, out int outlen } } + public virtual void OnInitAuthData(UInt64 unixTimestamp) + { + + } + public void PackAuthData(byte[] data, int datalength, byte[] outdata, out int outlength) { const int authhead_len = 4 + 8 + 4 + 16 + 4; @@ -234,6 +241,7 @@ public void PackAuthData(byte[] data, int datalength, byte[] outdata, out int ou UInt64 utc_time_second = (UInt64)Math.Floor(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds); UInt32 utc_time = (UInt32)(utc_time_second); Array.Copy(BitConverter.GetBytes(utc_time), 0, encrypt, 0, 4); + OnInitAuthData(utc_time_second); encrypt[12] = (byte)(Server.overhead); encrypt[13] = (byte)(Server.overhead >> 8); @@ -572,7 +580,7 @@ public override Dictionary GetObfs() return _obfs; } - protected void InitDataSizeList() + protected virtual void InitDataSizeList() { xorshift128plus random = new xorshift128plus(); random.init_from_bin(Server.key); @@ -683,7 +691,7 @@ public override Dictionary GetObfs() return _obfs; } - protected new void InitDataSizeList() + protected override void InitDataSizeList() { xorshift128plus random = new xorshift128plus(); random.init_from_bin(Server.key); @@ -760,7 +768,7 @@ protected void CheckAndPatchDataSize(List data_list, xorshift128plus random } } - protected new void InitDataSizeList() + protected override void InitDataSizeList() { xorshift128plus random = new xorshift128plus(); random.init_from_bin(Server.key); @@ -866,7 +874,7 @@ public override Dictionary GetObfs() protected UInt64 key_change_datetime_key; protected List key_change_datetime_key_bytes = new List(); - protected new void InitDataSizeList() + protected override void InitDataSizeList() { xorshift128plus random = new xorshift128plus(); byte[] newKey = new byte[Server.key.Length]; @@ -908,8 +916,10 @@ public override void SetServerInfo(ServerInfo serverInfo) key_change_interval = interval; } } - // https://stackoverflow.com/a/17632585/3548568 - UInt64 unixTimestamp = (UInt64)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds); + } + + public override void OnInitAuthData(UInt64 unixTimestamp) + { key_change_datetime_key = unixTimestamp / key_change_interval; for (int i = 7; i > -1; --i) { diff --git a/shadowsocks-csharp/View/MenuViewController.cs b/shadowsocks-csharp/View/MenuViewController.cs index 6170940a..3961394a 100755 --- a/shadowsocks-csharp/View/MenuViewController.cs +++ b/shadowsocks-csharp/View/MenuViewController.cs @@ -335,6 +335,7 @@ void controller_UpdatePACFromGFWListCompleted(object sender, GFWListUpdater.Resu void updateFreeNodeChecker_NewFreeNodeFound(object sender, EventArgs e) { + string lastGroup = null; int count = 0; if (!String.IsNullOrEmpty(updateFreeNodeChecker.FreeNodeResult)) { @@ -389,7 +390,6 @@ void updateFreeNodeChecker_NewFreeNodeFound(object sender, EventArgs e) if (!config.isDefaultConfig()) keep_selected_server = true; } - string lastGroup = null; string curGroup = null; foreach (string url in urls) { @@ -556,19 +556,28 @@ void updateFreeNodeChecker_NewFreeNodeFound(object sender, EventArgs e) { config.index = config.configs.Count - 1; } + if (count > 0) + { + for (int i = 0; i < config.serverSubscribes.Count; ++i) + { + if (config.serverSubscribes[i].URL == updateFreeNodeChecker.subscribeTask.URL) + { + config.serverSubscribes[i].LastUpdateTime = (UInt64)Math.Floor(DateTime.Now.Subtract(new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds); + } + } + } controller.SaveServersConfig(config); - } } if (count > 0) { ShowBalloonTip(I18N.GetString("Success"), - I18N.GetString("Update subscribe SSR node success"), ToolTipIcon.Info, 10000); + String.Format(I18N.GetString("Update subscribe {0} success"), lastGroup), ToolTipIcon.Info, 10000); } else { ShowBalloonTip(I18N.GetString("Error"), - I18N.GetString("Update subscribe SSR node failure"), ToolTipIcon.Info, 10000); + String.Format(I18N.GetString("Update subscribe {0} failure"), lastGroup), ToolTipIcon.Info, 10000); } if (updateSubscribeManager.Next()) { diff --git a/shadowsocks-csharp/View/SubscribeForm.Designer.cs b/shadowsocks-csharp/View/SubscribeForm.Designer.cs index 97e70715..815eaef3 100644 --- a/shadowsocks-csharp/View/SubscribeForm.Designer.cs +++ b/shadowsocks-csharp/View/SubscribeForm.Designer.cs @@ -29,11 +29,11 @@ protected override void Dispose(bool disposing) private void InitializeComponent() { this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); - this.checkBoxAutoUpdate = new System.Windows.Forms.CheckBox(); this.label1 = new System.Windows.Forms.Label(); this.label2 = new System.Windows.Forms.Label(); this.textBoxURL = new System.Windows.Forms.TextBox(); this.textBoxGroup = new System.Windows.Forms.TextBox(); + this.checkBoxAutoUpdate = new System.Windows.Forms.CheckBox(); this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel(); this.buttonOK = new System.Windows.Forms.Button(); this.buttonCancel = new System.Windows.Forms.Button(); @@ -42,6 +42,8 @@ private void InitializeComponent() this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel(); this.buttonAdd = new System.Windows.Forms.Button(); this.buttonDel = new System.Windows.Forms.Button(); + this.label3 = new System.Windows.Forms.Label(); + this.textUpdate = new System.Windows.Forms.TextBox(); this.tableLayoutPanel1.SuspendLayout(); this.tableLayoutPanel2.SuspendLayout(); this.tableLayoutPanel3.SuspendLayout(); @@ -58,30 +60,22 @@ private void InitializeComponent() this.tableLayoutPanel1.Controls.Add(this.label2, 0, 1); this.tableLayoutPanel1.Controls.Add(this.textBoxURL, 1, 0); this.tableLayoutPanel1.Controls.Add(this.textBoxGroup, 1, 1); - this.tableLayoutPanel1.Location = new System.Drawing.Point(352, 3); + this.tableLayoutPanel1.Controls.Add(this.label3, 0, 2); + this.tableLayoutPanel1.Controls.Add(this.textUpdate, 1, 2); + this.tableLayoutPanel1.Location = new System.Drawing.Point(353, 3); this.tableLayoutPanel1.Name = "tableLayoutPanel1"; this.tableLayoutPanel1.RowCount = 3; this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); - this.tableLayoutPanel1.Size = new System.Drawing.Size(263, 74); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.Size = new System.Drawing.Size(269, 81); this.tableLayoutPanel1.TabIndex = 0; // - // checkBoxAutoUpdate - // - this.checkBoxAutoUpdate.AutoSize = true; - this.checkBoxAutoUpdate.Location = new System.Drawing.Point(3, 35); - this.checkBoxAutoUpdate.Name = "checkBoxAutoUpdate"; - this.checkBoxAutoUpdate.Size = new System.Drawing.Size(90, 16); - this.checkBoxAutoUpdate.TabIndex = 3; - this.checkBoxAutoUpdate.Text = "Auto update"; - this.checkBoxAutoUpdate.UseVisualStyleBackColor = true; - // // label1 // this.label1.Anchor = System.Windows.Forms.AnchorStyles.Right; this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(45, 7); + this.label1.Location = new System.Drawing.Point(51, 7); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(23, 12); this.label1.TabIndex = 0; @@ -91,7 +85,7 @@ private void InitializeComponent() // this.label2.Anchor = System.Windows.Forms.AnchorStyles.Right; this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(3, 34); + this.label2.Location = new System.Drawing.Point(9, 34); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(65, 12); this.label2.TabIndex = 0; @@ -99,20 +93,29 @@ private void InitializeComponent() // // textBoxURL // - this.textBoxURL.Location = new System.Drawing.Point(74, 3); + this.textBoxURL.Location = new System.Drawing.Point(80, 3); this.textBoxURL.Name = "textBoxURL"; this.textBoxURL.Size = new System.Drawing.Size(186, 21); this.textBoxURL.TabIndex = 1; - this.textBoxURL.TextChanged += new System.EventHandler(this.textBoxURL_TextChanged); // // textBoxGroup // - this.textBoxGroup.Location = new System.Drawing.Point(74, 30); + this.textBoxGroup.Location = new System.Drawing.Point(80, 30); this.textBoxGroup.Name = "textBoxGroup"; this.textBoxGroup.ReadOnly = true; this.textBoxGroup.Size = new System.Drawing.Size(186, 21); this.textBoxGroup.TabIndex = 1; // + // checkBoxAutoUpdate + // + this.checkBoxAutoUpdate.AutoSize = true; + this.checkBoxAutoUpdate.Location = new System.Drawing.Point(3, 35); + this.checkBoxAutoUpdate.Name = "checkBoxAutoUpdate"; + this.checkBoxAutoUpdate.Size = new System.Drawing.Size(90, 16); + this.checkBoxAutoUpdate.TabIndex = 3; + this.checkBoxAutoUpdate.Text = "Auto update"; + this.checkBoxAutoUpdate.UseVisualStyleBackColor = true; + // // tableLayoutPanel2 // this.tableLayoutPanel2.Anchor = System.Windows.Forms.AnchorStyles.Bottom; @@ -121,11 +124,11 @@ private void InitializeComponent() this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); this.tableLayoutPanel2.Controls.Add(this.buttonOK, 0, 0); this.tableLayoutPanel2.Controls.Add(this.buttonCancel, 1, 0); - this.tableLayoutPanel2.Location = new System.Drawing.Point(352, 264); + this.tableLayoutPanel2.Location = new System.Drawing.Point(353, 264); this.tableLayoutPanel2.Name = "tableLayoutPanel2"; this.tableLayoutPanel2.RowCount = 1; this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); - this.tableLayoutPanel2.Size = new System.Drawing.Size(291, 60); + this.tableLayoutPanel2.Size = new System.Drawing.Size(290, 60); this.tableLayoutPanel2.TabIndex = 2; // // buttonOK @@ -142,7 +145,7 @@ private void InitializeComponent() // buttonCancel // this.buttonCancel.Anchor = System.Windows.Forms.AnchorStyles.None; - this.buttonCancel.Location = new System.Drawing.Point(167, 10); + this.buttonCancel.Location = new System.Drawing.Point(166, 10); this.buttonCancel.Name = "buttonCancel"; this.buttonCancel.Size = new System.Drawing.Size(102, 39); this.buttonCancel.TabIndex = 0; @@ -215,6 +218,24 @@ private void InitializeComponent() this.buttonDel.UseVisualStyleBackColor = true; this.buttonDel.Click += new System.EventHandler(this.buttonDel_Click); // + // label3 + // + this.label3.Anchor = System.Windows.Forms.AnchorStyles.Right; + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(3, 61); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(71, 12); + this.label3.TabIndex = 0; + this.label3.Text = "Last Update"; + // + // textUpdate + // + this.textUpdate.Location = new System.Drawing.Point(80, 57); + this.textUpdate.Name = "textUpdate"; + this.textUpdate.ReadOnly = true; + this.textUpdate.Size = new System.Drawing.Size(186, 21); + this.textUpdate.TabIndex = 1; + // // SubscribeForm // this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); @@ -254,5 +275,7 @@ private void InitializeComponent() private System.Windows.Forms.TableLayoutPanel tableLayoutPanel4; private System.Windows.Forms.Button buttonAdd; private System.Windows.Forms.Button buttonDel; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TextBox textUpdate; } } \ No newline at end of file diff --git a/shadowsocks-csharp/View/SubscribeForm.cs b/shadowsocks-csharp/View/SubscribeForm.cs index f57dc54c..5d82a0a4 100644 --- a/shadowsocks-csharp/View/SubscribeForm.cs +++ b/shadowsocks-csharp/View/SubscribeForm.cs @@ -40,6 +40,7 @@ private void UpdateTexts() checkBoxAutoUpdate.Text = I18N.GetString("Auto update"); buttonOK.Text = I18N.GetString("OK"); buttonCancel.Text = I18N.GetString("Cancel"); + label3.Text = I18N.GetString("Last Update"); } private void SubscribeForm_FormClosed(object sender, FormClosedEventArgs e) @@ -98,11 +99,6 @@ private void buttonOK_Click(object sender, EventArgs e) this.Close(); } - private void textBoxURL_TextChanged(object sender, EventArgs e) - { - textBoxGroup.Text = ""; - } - private void UpdateList() { listServerSubscribe.Items.Clear(); @@ -129,6 +125,16 @@ private void UpdateSelected(int index) textBoxURL.Text = ss.URL; textBoxGroup.Text = ss.Group; _old_select_index = index; + if (ss.LastUpdateTime != 0) + { + DateTime now = new DateTime(1970, 1, 1, 0, 0, 0); + now = now.AddSeconds(ss.LastUpdateTime); + textUpdate.Text = now.ToLongDateString() + " " + now.ToLongTimeString(); + } + else + { + textUpdate.Text = "(「・ω・)「"; + } } } @@ -137,8 +143,12 @@ private void SaveSelected(int index) if (index >= 0 && index < _modifiedConfiguration.serverSubscribes.Count) { ServerSubscribe ss = _modifiedConfiguration.serverSubscribes[index]; - ss.URL = textBoxURL.Text; - ss.Group = textBoxGroup.Text; + if (ss.URL != textBoxURL.Text) + { + ss.URL = textBoxURL.Text; + ss.Group = ""; + ss.LastUpdateTime = 0; + } } }