Compare commits

...

19 Commits
5.4 ... 5.9

Author SHA1 Message Date
2dust
606da79372 Update AssemblyInfo.cs 2022-04-01 18:10:48 +08:00
2dust
0801c3db64 Refactor stat update 2022-04-01 18:09:58 +08:00
2dust
35deb0c915 Merge pull request #2148 from zhaogarvie/master
保存自定义路由信息时先排序后输出
2022-04-01 18:07:25 +08:00
uniceguy
fd4d712688 保存自定义路由信息时先排序后输出 2022-04-01 13:21:22 +08:00
2dust
354fc618b0 fix encode issue 2022-03-31 20:19:15 +08:00
2dust
82b6ee5ad2 Refactor ResUI 2022-03-31 19:53:58 +08:00
2dust
645e6c4ec0 Update ConfigHandler.cs 2022-03-28 19:21:31 +08:00
2dust
cdc83bc9d7 Update AssemblyInfo.cs 2022-03-28 19:09:27 +08:00
2dust
70feacd276 Add hysteria support 2022-03-28 19:08:54 +08:00
2dust
ece4572058 Refactor and improve 2022-03-28 18:54:05 +08:00
2dust
4d16a5e801 Update AssemblyInfo.cs 2022-03-24 19:09:15 +08:00
2dust
1493a8b03f add drag to sort 2022-03-24 19:07:45 +08:00
2dust
d20791bf73 Update AssemblyInfo.cs 2022-03-23 18:56:01 +08:00
2dust
7bb91f57ac Custom configuration overwrite port 2022-03-23 18:49:28 +08:00
2dust
b7a6004830 some improvements 2022-03-23 18:48:57 +08:00
2dust
dee5613f2f add move servers to group 2022-03-23 18:47:59 +08:00
2dust
e58e0d6ac7 Update AssemblyInfo.cs 2022-03-21 20:36:07 +08:00
2dust
a2679e009d refactor some code 2022-03-21 20:20:29 +08:00
2dust
78d6bcd57a Full profile can be subscribed 2022-03-20 20:40:07 +08:00
37 changed files with 1060 additions and 626 deletions

View File

@@ -1,10 +1,13 @@
using System.Drawing; using System;
using System.Drawing;
using System.Windows.Forms; using System.Windows.Forms;
namespace v2rayN.Base namespace v2rayN.Base
{ {
class ListViewFlickerFree : ListView class ListViewFlickerFree : ListView
{ {
Action<int, int> _updateFunc;
public ListViewFlickerFree() public ListViewFlickerFree()
{ {
SetStyle(ControlStyles.OptimizedDoubleBuffer SetStyle(ControlStyles.OptimizedDoubleBuffer
@@ -13,40 +16,82 @@ namespace v2rayN.Base
UpdateStyles(); UpdateStyles();
} }
public void RegisterDragEvent(Action<int, int> _update)
public void AutoResizeColumns()
{ {
try _updateFunc = _update;
{ this.AllowDrop = true;
this.SuspendLayout();
Graphics graphics = this.CreateGraphics();
// 原生 ColumnHeaderAutoResizeStyle.ColumnContent 将忽略列头宽度 this.ItemDrag += new ItemDragEventHandler(this.lv_ItemDrag);
this.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize); this.DragDrop += new DragEventHandler(this.lv_DragDrop);
this.DragEnter += new DragEventHandler(this.lv_DragEnter);
for (int i = 0; i < this.Columns.Count; i++) this.DragOver += new DragEventHandler(this.lv_DragOver);
{ this.DragLeave += new EventHandler(this.lv_DragLeave);
ColumnHeader c = this.Columns[i];
int cWidth = c.Width;
string MaxStr = "";
Font font = this.Items[0].SubItems[0].Font;
foreach (ListViewItem item in this.Items)
{
// 整行视作相同字形,不单独计算每个单元格
font = item.SubItems[i].Font;
string str = item.SubItems[i].Text;
if (str.Length > MaxStr.Length) // 未考虑非等宽问题
MaxStr = str;
} }
int strWidth = (int)graphics.MeasureString(MaxStr, font).Width;
c.Width = System.Math.Max(cWidth, strWidth); private void lv_DragDrop(object sender, DragEventArgs e)
{
int targetIndex = this.InsertionMark.Index;
if (targetIndex == -1)
{
return;
} }
this.ResumeLayout(); if (this.InsertionMark.AppearsAfterItem)
} {
catch { } targetIndex++;
} }
if (this.SelectedIndices.Count <= 0)
{
return;
}
_updateFunc(this.SelectedIndices[0], targetIndex);
//ListViewItem draggedItem = (ListViewItem)e.Data.GetData(typeof(ListViewItem));
//this.BeginUpdate();
//this.Items.Insert(targetIndex, (ListViewItem)draggedItem.Clone());
//this.Items.Remove(draggedItem);
//this.EndUpdate();
}
private void lv_DragEnter(object sender, DragEventArgs e)
{
e.Effect = e.AllowedEffect;
}
private void lv_DragLeave(object sender, EventArgs e)
{
this.InsertionMark.Index = -1;
}
private void lv_DragOver(object sender, DragEventArgs e)
{
Point targetPoint = this.PointToClient(new Point(e.X, e.Y));
int targetIndex = this.InsertionMark.NearestIndex(targetPoint);
if (targetIndex > -1)
{
Rectangle itemBounds = this.GetItemRect(targetIndex);
this.EnsureVisible(targetIndex);
if (targetPoint.Y > itemBounds.Top + (itemBounds.Height / 2))
{
this.InsertionMark.AppearsAfterItem = true;
}
else
{
this.InsertionMark.AppearsAfterItem = false;
}
}
this.InsertionMark.Index = targetIndex;
}
private void lv_ItemDrag(object sender, ItemDragEventArgs e)
{
this.DoDragDrop(e.Item, DragDropEffects.Move);
this.InsertionMark.Index = -1;
}
} }
} }

View File

@@ -4,6 +4,7 @@ using System.IO;
using System.Windows.Forms; using System.Windows.Forms;
using v2rayN.Handler; using v2rayN.Handler;
using v2rayN.Mode; using v2rayN.Mode;
using v2rayN.Resx;
namespace v2rayN.Forms namespace v2rayN.Forms
{ {
@@ -19,6 +20,7 @@ namespace v2rayN.Forms
{ {
cmbCoreType.Items.AddRange(Global.coreTypes.ToArray()); cmbCoreType.Items.AddRange(Global.coreTypes.ToArray());
cmbCoreType.Items.Add("clash"); cmbCoreType.Items.Add("clash");
cmbCoreType.Items.Add("hysteria");
cmbCoreType.Items.Add(string.Empty); cmbCoreType.Items.Add(string.Empty);
txtAddress.ReadOnly = true; txtAddress.ReadOnly = true;
@@ -66,12 +68,12 @@ namespace v2rayN.Forms
string remarks = txtRemarks.Text; string remarks = txtRemarks.Text;
if (Utils.IsNullOrEmpty(remarks)) if (Utils.IsNullOrEmpty(remarks))
{ {
UI.Show(UIRes.I18N("PleaseFillRemarks")); UI.Show(ResUI.PleaseFillRemarks);
return; return;
} }
if (Utils.IsNullOrEmpty(txtAddress.Text)) if (Utils.IsNullOrEmpty(txtAddress.Text))
{ {
UI.Show(UIRes.I18N("FillServerAddressCustom")); UI.Show(ResUI.FillServerAddressCustom);
return; return;
} }
vmessItem.remarks = remarks; vmessItem.remarks = remarks;
@@ -90,7 +92,7 @@ namespace v2rayN.Forms
} }
else else
{ {
UI.ShowWarning(UIRes.I18N("OperationFailed")); UI.ShowWarning(ResUI.OperationFailed);
} }
} }
@@ -108,7 +110,7 @@ namespace v2rayN.Forms
private void btnBrowse_Click(object sender, EventArgs e) private void btnBrowse_Click(object sender, EventArgs e)
{ {
UI.Show(UIRes.I18N("CustomServerTips")); UI.Show(ResUI.CustomServerTips);
OpenFileDialog fileDialog = new OpenFileDialog OpenFileDialog fileDialog = new OpenFileDialog
{ {
@@ -128,14 +130,14 @@ namespace v2rayN.Forms
vmessItem.address = fileName; vmessItem.address = fileName;
vmessItem.remarks = txtRemarks.Text; vmessItem.remarks = txtRemarks.Text;
if (ConfigHandler.AddCustomServer(ref config, vmessItem) == 0) if (ConfigHandler.AddCustomServer(ref config, vmessItem, false) == 0)
{ {
BindingServer(); BindingServer();
UI.Show(UIRes.I18N("SuccessfullyImportedCustomServer")); UI.Show(ResUI.SuccessfullyImportedCustomServer);
} }
else else
{ {
UI.ShowWarning(UIRes.I18N("FailedImportedCustomServer")); UI.ShowWarning(ResUI.FailedImportedCustomServer);
} }
} }
@@ -144,11 +146,11 @@ namespace v2rayN.Forms
var address = txtAddress.Text; var address = txtAddress.Text;
if (Utils.IsNullOrEmpty(address)) if (Utils.IsNullOrEmpty(address))
{ {
UI.Show(UIRes.I18N("FillServerAddressCustom")); UI.Show(ResUI.FillServerAddressCustom);
return; return;
} }
address = Path.Combine(Utils.GetTempPath(), address); address = Path.Combine(Utils.GetConfigPath(), address);
Process.Start(address); Process.Start(address);
} }
} }

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Windows.Forms; using System.Windows.Forms;
using v2rayN.Handler; using v2rayN.Handler;
using v2rayN.Mode; using v2rayN.Mode;
using v2rayN.Resx;
namespace v2rayN.Forms namespace v2rayN.Forms
{ {
@@ -17,12 +18,6 @@ namespace v2rayN.Forms
{ {
this.Text = (eConfigType).ToString(); this.Text = (eConfigType).ToString();
cmbSecurity.Items.AddRange(Global.vmessSecuritys.ToArray());
cmbSecurity3.Items.AddRange(config.GetShadowsocksSecuritys().ToArray());
cmbFlow5.Items.AddRange(Global.xtlsFlows.ToArray());
cmbFlow6.Items.AddRange(Global.xtlsFlows.ToArray());
cmbCoreType.Items.AddRange(Global.coreTypes.ToArray()); cmbCoreType.Items.AddRange(Global.coreTypes.ToArray());
cmbCoreType.Items.Add(string.Empty); cmbCoreType.Items.Add(string.Empty);
@@ -31,12 +26,16 @@ namespace v2rayN.Forms
case EConfigType.Vmess: case EConfigType.Vmess:
panVmess.Dock = DockStyle.Fill; panVmess.Dock = DockStyle.Fill;
panVmess.Visible = true; panVmess.Visible = true;
cmbSecurity.Items.AddRange(Global.vmessSecuritys.ToArray());
break; break;
case EConfigType.Shadowsocks: case EConfigType.Shadowsocks:
panSs.Dock = DockStyle.Fill; panSs.Dock = DockStyle.Fill;
panSs.Visible = true; panSs.Visible = true;
panTran.Visible = false; panTran.Visible = false;
this.Height = this.Height - panTran.Height; this.Height = this.Height - panTran.Height;
cmbSecurity3.Items.AddRange(LazyConfig.Instance.GetShadowsocksSecuritys().ToArray());
break; break;
case EConfigType.Socks: case EConfigType.Socks:
panSocks.Dock = DockStyle.Fill; panSocks.Dock = DockStyle.Fill;
@@ -48,11 +47,15 @@ namespace v2rayN.Forms
panVless.Dock = DockStyle.Fill; panVless.Dock = DockStyle.Fill;
panVless.Visible = true; panVless.Visible = true;
transportControl.AllowXtls = true; transportControl.AllowXtls = true;
cmbFlow5.Items.AddRange(Global.xtlsFlows.ToArray());
break; break;
case EConfigType.Trojan: case EConfigType.Trojan:
panTrojan.Dock = DockStyle.Fill; panTrojan.Dock = DockStyle.Fill;
panTrojan.Visible = true; panTrojan.Visible = true;
transportControl.AllowXtls = true; transportControl.AllowXtls = true;
cmbFlow6.Items.AddRange(Global.xtlsFlows.ToArray());
break; break;
} }
@@ -192,24 +195,24 @@ namespace v2rayN.Forms
if (Utils.IsNullOrEmpty(address)) if (Utils.IsNullOrEmpty(address))
{ {
UI.Show(UIRes.I18N("FillServerAddress")); UI.Show(ResUI.FillServerAddress);
return; return;
} }
if (Utils.IsNullOrEmpty(port) || !Utils.IsNumberic(port)) if (Utils.IsNullOrEmpty(port) || !Utils.IsNumberic(port))
{ {
UI.Show(UIRes.I18N("FillCorrectServerPort")); UI.Show(ResUI.FillCorrectServerPort);
return; return;
} }
if (eConfigType == EConfigType.Shadowsocks) if (eConfigType == EConfigType.Shadowsocks)
{ {
if (Utils.IsNullOrEmpty(id)) if (Utils.IsNullOrEmpty(id))
{ {
UI.Show(UIRes.I18N("FillPassword")); UI.Show(ResUI.FillPassword);
return; return;
} }
if (Utils.IsNullOrEmpty(security)) if (Utils.IsNullOrEmpty(security))
{ {
UI.Show(UIRes.I18N("PleaseSelectEncryption")); UI.Show(ResUI.PleaseSelectEncryption);
return; return;
} }
} }
@@ -217,7 +220,7 @@ namespace v2rayN.Forms
{ {
if (Utils.IsNullOrEmpty(id)) if (Utils.IsNullOrEmpty(id))
{ {
UI.Show(UIRes.I18N("FillUUID")); UI.Show(ResUI.FillUUID);
return; return;
} }
} }
@@ -268,7 +271,7 @@ namespace v2rayN.Forms
} }
else else
{ {
UI.ShowWarning(UIRes.I18N("OperationFailed")); UI.ShowWarning(ResUI.OperationFailed);
} }
} }

View File

@@ -4,6 +4,7 @@ using System.Windows.Forms;
using v2rayN.Base; using v2rayN.Base;
using v2rayN.Handler; using v2rayN.Handler;
using v2rayN.Mode; using v2rayN.Mode;
using v2rayN.Resx;
namespace v2rayN.Forms namespace v2rayN.Forms
{ {
@@ -104,7 +105,7 @@ namespace v2rayN.Forms
} }
else else
{ {
UI.ShowWarning(UIRes.I18N("OperationFailed")); UI.ShowWarning(ResUI.OperationFailed);
} }
} }

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Windows.Forms; using System.Windows.Forms;
using v2rayN.Handler; using v2rayN.Handler;
using v2rayN.Mode; using v2rayN.Mode;
using v2rayN.Resx;
namespace v2rayN.Forms namespace v2rayN.Forms
{ {
@@ -73,7 +74,7 @@ namespace v2rayN.Forms
} }
else else
{ {
UI.ShowWarning(UIRes.I18N("OperationFailed")); UI.ShowWarning(ResUI.OperationFailed);
} }
} }

View File

@@ -47,6 +47,7 @@
this.menuCopyServer = new System.Windows.Forms.ToolStripMenuItem(); this.menuCopyServer = new System.Windows.Forms.ToolStripMenuItem();
this.menuSetDefaultServer = new System.Windows.Forms.ToolStripMenuItem(); this.menuSetDefaultServer = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator(); this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator();
this.menuMoveToGroup = new System.Windows.Forms.ToolStripMenuItem();
this.menuMoveTop = new System.Windows.Forms.ToolStripMenuItem(); this.menuMoveTop = new System.Windows.Forms.ToolStripMenuItem();
this.menuMoveUp = new System.Windows.Forms.ToolStripMenuItem(); this.menuMoveUp = new System.Windows.Forms.ToolStripMenuItem();
this.menuMoveDown = new System.Windows.Forms.ToolStripMenuItem(); this.menuMoveDown = new System.Windows.Forms.ToolStripMenuItem();
@@ -64,9 +65,9 @@
this.menuExport2ServerConfig = new System.Windows.Forms.ToolStripMenuItem(); this.menuExport2ServerConfig = new System.Windows.Forms.ToolStripMenuItem();
this.menuExport2ShareUrl = new System.Windows.Forms.ToolStripMenuItem(); this.menuExport2ShareUrl = new System.Windows.Forms.ToolStripMenuItem();
this.menuExport2SubContent = new System.Windows.Forms.ToolStripMenuItem(); this.menuExport2SubContent = new System.Windows.Forms.ToolStripMenuItem();
this.tsbServer = new System.Windows.Forms.ToolStripDropDownButton();
this.tabGroup = new System.Windows.Forms.TabControl(); this.tabGroup = new System.Windows.Forms.TabControl();
this.qrCodeControl = new v2rayN.Forms.QRCodeControl(); this.qrCodeControl = new v2rayN.Forms.QRCodeControl();
this.tsbServer = new System.Windows.Forms.ToolStripDropDownButton();
this.splitContainer1 = new System.Windows.Forms.SplitContainer(); this.splitContainer1 = new System.Windows.Forms.SplitContainer();
this.groupBox1 = new System.Windows.Forms.GroupBox(); this.groupBox1 = new System.Windows.Forms.GroupBox();
this.gbMsgTitle = new System.Windows.Forms.GroupBox(); this.gbMsgTitle = new System.Windows.Forms.GroupBox();
@@ -208,6 +209,7 @@
this.menuCopyServer, this.menuCopyServer,
this.menuSetDefaultServer, this.menuSetDefaultServer,
this.toolStripSeparator3, this.toolStripSeparator3,
this.menuMoveToGroup,
this.menuMoveTop, this.menuMoveTop,
this.menuMoveUp, this.menuMoveUp,
this.menuMoveDown, this.menuMoveDown,
@@ -226,6 +228,7 @@
this.menuExport2ShareUrl, this.menuExport2ShareUrl,
this.menuExport2SubContent}); this.menuExport2SubContent});
this.cmsLv.Name = "cmsLv"; this.cmsLv.Name = "cmsLv";
this.cmsLv.OwnerItem = this.tsbServer;
resources.ApplyResources(this.cmsLv, "cmsLv"); resources.ApplyResources(this.cmsLv, "cmsLv");
// //
// menuAddVmessServer // menuAddVmessServer
@@ -310,6 +313,12 @@
this.toolStripSeparator3.Name = "toolStripSeparator3"; this.toolStripSeparator3.Name = "toolStripSeparator3";
resources.ApplyResources(this.toolStripSeparator3, "toolStripSeparator3"); resources.ApplyResources(this.toolStripSeparator3, "toolStripSeparator3");
// //
// menuMoveToGroup
//
this.menuMoveToGroup.Name = "menuMoveToGroup";
resources.ApplyResources(this.menuMoveToGroup, "menuMoveToGroup");
this.menuMoveToGroup.Click += new System.EventHandler(this.menuMoveToGroup_Click);
//
// menuMoveTop // menuMoveTop
// //
this.menuMoveTop.Name = "menuMoveTop"; this.menuMoveTop.Name = "menuMoveTop";
@@ -410,6 +419,13 @@
resources.ApplyResources(this.menuExport2SubContent, "menuExport2SubContent"); resources.ApplyResources(this.menuExport2SubContent, "menuExport2SubContent");
this.menuExport2SubContent.Click += new System.EventHandler(this.menuExport2SubContent_Click); this.menuExport2SubContent.Click += new System.EventHandler(this.menuExport2SubContent_Click);
// //
// tsbServer
//
this.tsbServer.DropDown = this.cmsLv;
this.tsbServer.Image = global::v2rayN.Properties.Resources.server;
resources.ApplyResources(this.tsbServer, "tsbServer");
this.tsbServer.Name = "tsbServer";
//
// tabGroup // tabGroup
// //
resources.ApplyResources(this.tabGroup, "tabGroup"); resources.ApplyResources(this.tabGroup, "tabGroup");
@@ -422,13 +438,6 @@
resources.ApplyResources(this.qrCodeControl, "qrCodeControl"); resources.ApplyResources(this.qrCodeControl, "qrCodeControl");
this.qrCodeControl.Name = "qrCodeControl"; this.qrCodeControl.Name = "qrCodeControl";
// //
// tsbServer
//
this.tsbServer.DropDown = this.cmsLv;
this.tsbServer.Image = global::v2rayN.Properties.Resources.server;
resources.ApplyResources(this.tsbServer, "tsbServer");
this.tsbServer.Name = "tsbServer";
//
// splitContainer1 // splitContainer1
// //
resources.ApplyResources(this.splitContainer1, "splitContainer1"); resources.ApplyResources(this.splitContainer1, "splitContainer1");
@@ -1076,6 +1085,7 @@
private System.Windows.Forms.ToolStripMenuItem tsbGlobalHotkeySetting; private System.Windows.Forms.ToolStripMenuItem tsbGlobalHotkeySetting;
private System.Windows.Forms.TabControl tabGroup; private System.Windows.Forms.TabControl tabGroup;
private System.Windows.Forms.ToolStripMenuItem tsbGroupSetting; private System.Windows.Forms.ToolStripMenuItem tsbGroupSetting;
private System.Windows.Forms.ToolStripMenuItem menuMoveToGroup;
} }
} }

View File

@@ -12,6 +12,7 @@ using v2rayN.Handler;
using v2rayN.Mode; using v2rayN.Mode;
using v2rayN.Tool; using v2rayN.Tool;
using System.Linq; using System.Linq;
using v2rayN.Resx;
namespace v2rayN.Forms namespace v2rayN.Forms
{ {
@@ -149,12 +150,17 @@ namespace v2rayN.Forms
{ {
scMain.Panel2Collapsed = true; scMain.Panel2Collapsed = true;
if (!config.uiItem.mainLocation.IsEmpty)
{
this.Location = config.uiItem.mainLocation;
}
if (!config.uiItem.mainSize.IsEmpty) if (!config.uiItem.mainSize.IsEmpty)
{ {
this.Width = config.uiItem.mainSize.Width; this.Width = config.uiItem.mainSize.Width;
this.Height = config.uiItem.mainSize.Height; this.Height = config.uiItem.mainSize.Height;
} }
for (int k = 0; k < lvServers.Columns.Count; k++) for (int k = 0; k < lvServers.Columns.Count; k++)
{ {
var width = ConfigHandler.GetformMainLvColWidth(ref config, ((EServerColName)k).ToString(), lvServers.Columns[k].Width); var width = ConfigHandler.GetformMainLvColWidth(ref config, ((EServerColName)k).ToString(), lvServers.Columns[k].Width);
@@ -164,6 +170,8 @@ namespace v2rayN.Forms
private void StorageUI() private void StorageUI()
{ {
config.uiItem.mainLocation = this.Location;
config.uiItem.mainSize = new Size(this.Width, this.Height); config.uiItem.mainSize = new Size(this.Width, this.Height);
for (int k = 0; k < lvServers.Columns.Count; k++) for (int k = 0; k < lvServers.Columns.Count; k++)
@@ -225,28 +233,41 @@ namespace v2rayN.Forms
lvServers.Scrollable = true; lvServers.Scrollable = true;
lvServers.MultiSelect = true; lvServers.MultiSelect = true;
lvServers.HeaderStyle = ColumnHeaderStyle.Clickable; lvServers.HeaderStyle = ColumnHeaderStyle.Clickable;
lvServers.RegisterDragEvent(UpdateDragEventHandler);
lvServers.Columns.Add("", 30); lvServers.Columns.Add("", 30);
lvServers.Columns.Add(UIRes.I18N("LvServiceType"), 80); lvServers.Columns.Add(ResUI.LvServiceType, 80);
lvServers.Columns.Add(UIRes.I18N("LvAlias"), 100); lvServers.Columns.Add(ResUI.LvAlias, 100);
lvServers.Columns.Add(UIRes.I18N("LvAddress"), 120); lvServers.Columns.Add(ResUI.LvAddress, 120);
lvServers.Columns.Add(UIRes.I18N("LvPort"), 100); lvServers.Columns.Add(ResUI.LvPort, 100);
lvServers.Columns.Add(UIRes.I18N("LvEncryptionMethod"), 120); lvServers.Columns.Add(ResUI.LvEncryptionMethod, 120);
lvServers.Columns.Add(UIRes.I18N("LvTransportProtocol"), 120); lvServers.Columns.Add(ResUI.LvTransportProtocol, 120);
lvServers.Columns.Add(UIRes.I18N("LvTLS"), 100); lvServers.Columns.Add(ResUI.LvTLS, 100);
lvServers.Columns.Add(UIRes.I18N("LvSubscription"), 100); lvServers.Columns.Add(ResUI.LvSubscription, 100);
lvServers.Columns.Add(UIRes.I18N("LvTestResults"), 120, HorizontalAlignment.Right); lvServers.Columns.Add(ResUI.LvTestResults, 120, HorizontalAlignment.Right);
if (statistics != null && statistics.Enable) if (statistics != null && statistics.Enable)
{ {
lvServers.Columns.Add(UIRes.I18N("LvTodayDownloadDataAmount"), 70); lvServers.Columns.Add(ResUI.LvTodayDownloadDataAmount, 70);
lvServers.Columns.Add(UIRes.I18N("LvTodayUploadDataAmount"), 70); lvServers.Columns.Add(ResUI.LvTodayUploadDataAmount, 70);
lvServers.Columns.Add(UIRes.I18N("LvTotalDownloadDataAmount"), 70); lvServers.Columns.Add(ResUI.LvTotalDownloadDataAmount, 70);
lvServers.Columns.Add(UIRes.I18N("LvTotalUploadDataAmount"), 70); lvServers.Columns.Add(ResUI.LvTotalUploadDataAmount, 70);
} }
lvServers.EndUpdate(); lvServers.EndUpdate();
} }
private void UpdateDragEventHandler(int index, int targetIndex)
{
if (index < 0 || targetIndex < 0)
{
return;
}
if (ConfigHandler.MoveServer(ref config, ref lstVmess, index, EMove.Position, targetIndex) == 0)
{
RefreshServers();
}
}
/// <summary> /// <summary>
/// 刷新服务器列表 /// 刷新服务器列表
/// </summary> /// </summary>
@@ -472,7 +493,7 @@ namespace v2rayN.Forms
{ {
tabGroup.TabPages.Clear(); tabGroup.TabPages.Clear();
string title = $" {UIRes.I18N("AllGroupServers")} "; string title = $" {ResUI.AllGroupServers} ";
var tabPage = new TabPage(title); var tabPage = new TabPage(title);
tabPage.Name = ""; tabPage.Name = "";
tabGroup.TabPages.Add(tabPage); tabGroup.TabPages.Add(tabPage);
@@ -485,6 +506,23 @@ namespace v2rayN.Forms
} }
tabGroup.SelectedIndex = 0; tabGroup.SelectedIndex = 0;
//menuMoveToGroup
menuMoveToGroup.DropDownItems.Clear();
List<ToolStripMenuItem> lst = new List<ToolStripMenuItem>();
foreach (var item in config.groupItem)
{
string name = item.remarks;
ToolStripMenuItem ts = new ToolStripMenuItem(name)
{
Tag = item.id,
};
ts.Click += new EventHandler(ts_Group_Click);
lst.Add(ts);
}
menuMoveToGroup.DropDownItems.AddRange(lst.ToArray());
} }
private void tabGroup_SelectedIndexChanged(object sender, EventArgs e) private void tabGroup_SelectedIndexChanged(object sender, EventArgs e)
@@ -501,6 +539,29 @@ namespace v2rayN.Forms
lvServers.Focus(); lvServers.Focus();
} }
private void ts_Group_Click(object sender, EventArgs e)
{
try
{
ToolStripItem ts = (ToolStripItem)sender;
var groupIdSelected = Utils.ToString(ts.Tag);
int index = GetLvSelectedIndex();
if (index < 0)
{
return;
}
if (ConfigHandler.MoveServerToGroup(config, lstSelecteds, groupIdSelected) == 0)
{
RefreshServers();
}
}
catch
{
}
}
#endregion #endregion
#region v2ray #region v2ray
@@ -674,7 +735,7 @@ namespace v2rayN.Forms
{ {
return; return;
} }
if (UI.ShowYesNo(UIRes.I18N("RemoveServer")) == DialogResult.No) if (UI.ShowYesNo(ResUI.RemoveServer) == DialogResult.No)
{ {
return; return;
} }
@@ -688,11 +749,10 @@ namespace v2rayN.Forms
private void menuRemoveDuplicateServer_Click(object sender, EventArgs e) private void menuRemoveDuplicateServer_Click(object sender, EventArgs e)
{ {
int oldCount = lstVmess.Count; int oldCount = lstVmess.Count;
ConfigHandler.DedupServerList(ref config, ref lstVmess); int newCount = ConfigHandler.DedupServerList(ref config, ref lstVmess);
int newCount = lstVmess.Count;
RefreshServers(); RefreshServers();
_ = LoadV2ray(); _ = LoadV2ray();
UI.Show(string.Format(UIRes.I18N("RemoveDuplicateServerResult"), oldCount, newCount)); UI.Show(string.Format(ResUI.RemoveDuplicateServerResult, oldCount, newCount));
} }
private void menuCopyServer_Click(object sender, EventArgs e) private void menuCopyServer_Click(object sender, EventArgs e)
@@ -721,50 +781,50 @@ namespace v2rayN.Forms
private void menuPingServer_Click(object sender, EventArgs e) private void menuPingServer_Click(object sender, EventArgs e)
{ {
Speedtest("ping"); Speedtest(ESpeedActionType.Ping);
} }
private void menuTcpingServer_Click(object sender, EventArgs e) private void menuTcpingServer_Click(object sender, EventArgs e)
{ {
Speedtest("tcping"); Speedtest(ESpeedActionType.Tcping);
} }
private void menuRealPingServer_Click(object sender, EventArgs e) private void menuRealPingServer_Click(object sender, EventArgs e)
{ {
//if (!config.sysAgentEnabled) //if (!config.sysAgentEnabled)
//{ //{
// UI.Show(UIRes.I18N("NeedHttpGlobalProxy")); // UI.Show(ResUI.NeedHttpGlobalProxy"));
// return; // return;
//} //}
//UI.Show(UIRes.I18N("SpeedServerTips")); //UI.Show(ResUI.SpeedServerTips"));
Speedtest("realping"); Speedtest(ESpeedActionType.Realping);
} }
private void menuSpeedServer_Click(object sender, EventArgs e) private void menuSpeedServer_Click(object sender, EventArgs e)
{ {
//if (!config.sysAgentEnabled) //if (!config.sysAgentEnabled)
//{ //{
// UI.Show(UIRes.I18N("NeedHttpGlobalProxy")); // UI.Show(ResUI.NeedHttpGlobalProxy"));
// return; // return;
//} //}
//UI.Show(UIRes.I18N("SpeedServerTips")); //UI.Show(ResUI.SpeedServerTips"));
Speedtest("speedtest"); Speedtest(ESpeedActionType.Speedtest);
} }
private void Speedtest(string actionType) private void Speedtest(ESpeedActionType actionType)
{ {
if (GetLvSelectedIndex() < 0) return; if (GetLvSelectedIndex() < 0) return;
ClearTestResult(); ClearTestResult();
SpeedtestHandler statistics = new SpeedtestHandler(ref config, ref v2rayHandler, lstSelecteds, actionType, UpdateSpeedtestHandler); SpeedtestHandler statistics = new SpeedtestHandler(ref config, v2rayHandler, lstSelecteds, actionType, UpdateSpeedtestHandler);
} }
private void tsbTestMe_Click(object sender, EventArgs e) private void tsbTestMe_Click(object sender, EventArgs e)
{ {
SpeedtestHandler statistics = new SpeedtestHandler(ref config); SpeedtestHandler statistics = new SpeedtestHandler(ref config);
string result = statistics.RunAvailabilityCheck() + "ms"; string result = statistics.RunAvailabilityCheck() + "ms";
AppendText(false, string.Format(UIRes.I18N("TestMeOutput"), result)); AppendText(false, string.Format(ResUI.TestMeOutput, result));
} }
private void menuClearStatistic_Click(object sender, EventArgs e) private void menuClearStatistic_Click(object sender, EventArgs e)
@@ -805,8 +865,8 @@ namespace v2rayN.Forms
if (sb.Length > 0) if (sb.Length > 0)
{ {
Utils.SetClipboardData(sb.ToString()); Utils.SetClipboardData(sb.ToString());
AppendText(false, UIRes.I18N("BatchExportURLSuccessfully")); AppendText(false, ResUI.BatchExportURLSuccessfully);
//UI.Show(UIRes.I18N("BatchExportURLSuccessfully")); //UI.Show(ResUI.BatchExportURLSuccessfully"));
} }
} }
@@ -828,7 +888,7 @@ namespace v2rayN.Forms
if (sb.Length > 0) if (sb.Length > 0)
{ {
Utils.SetClipboardData(Utils.Base64Encode(sb.ToString())); Utils.SetClipboardData(Utils.Base64Encode(sb.ToString()));
UI.Show(UIRes.I18N("BatchExportSubscriptionSuccessfully")); UI.Show(ResUI.BatchExportSubscriptionSuccessfully);
} }
} }
@@ -898,7 +958,7 @@ namespace v2rayN.Forms
{ {
if (index < 0) if (index < 0)
{ {
UI.Show(UIRes.I18N("PleaseSelectServer")); UI.Show(ResUI.PleaseSelectServer);
return -1; return -1;
} }
if (ConfigHandler.SetDefaultServer(ref config, lstVmess[index]) == 0) if (ConfigHandler.SetDefaultServer(ref config, lstVmess[index]) == 0)
@@ -921,7 +981,7 @@ namespace v2rayN.Forms
{ {
if (lvServers.SelectedIndices.Count <= 0) if (lvServers.SelectedIndices.Count <= 0)
{ {
UI.Show(UIRes.I18N("PleaseSelectServer")); UI.Show(ResUI.PleaseSelectServer);
return index; return index;
} }
@@ -964,11 +1024,11 @@ namespace v2rayN.Forms
private void menuAddServers_Click(object sender, EventArgs e) private void menuAddServers_Click(object sender, EventArgs e)
{ {
string clipboardData = Utils.GetClipboardData(); string clipboardData = Utils.GetClipboardData();
int ret = MainFormHandler.Instance.AddBatchServers(config, clipboardData, "", groupId); int ret = ConfigHandler.AddBatchServers(ref config, clipboardData, "", groupId);
if (ret > 0) if (ret > 0)
{ {
RefreshServers(); RefreshServers();
UI.Show(string.Format(UIRes.I18N("SuccessfullyImportedServerViaClipboard"), ret)); UI.Show(string.Format(ResUI.SuccessfullyImportedServerViaClipboard, ret));
} }
} }
@@ -990,15 +1050,15 @@ namespace v2rayN.Forms
if (Utils.IsNullOrEmpty(result)) if (Utils.IsNullOrEmpty(result))
{ {
UI.ShowWarning(UIRes.I18N("NoValidQRcodeFound")); UI.ShowWarning(ResUI.NoValidQRcodeFound);
} }
else else
{ {
int ret = MainFormHandler.Instance.AddBatchServers(config, result, "", groupId); int ret = ConfigHandler.AddBatchServers(ref config, result, "", groupId);
if (ret > 0) if (ret > 0)
{ {
RefreshServers(); RefreshServers();
UI.Show(UIRes.I18N("SuccessfullyImportedServerViaScan")); UI.Show(ResUI.SuccessfullyImportedServerViaScan);
} }
} }
} }
@@ -1200,7 +1260,28 @@ namespace v2rayN.Forms
down /= (ulong)(config.statisticsFreshRate / 1000f); down /= (ulong)(config.statisticsFreshRate / 1000f);
toolSslServerSpeed.Text = string.Format("{0}/s↑ | {1}/s↓", Utils.HumanFy(up), Utils.HumanFy(down)); toolSslServerSpeed.Text = string.Format("{0}/s↑ | {1}/s↓", Utils.HumanFy(up), Utils.HumanFy(down));
List<string[]> datas = new List<string[]>(); foreach (var it in statistics)
{
int index = lstVmess.FindIndex(item => item.indexId == it.itemId);
if (index < 0)
{
continue;
}
lvServers.Invoke((MethodInvoker)delegate
{
lvServers.BeginUpdate();
lvServers.Items[index].SubItems["todayDown"].Text = Utils.HumanFy(it.todayDown);
lvServers.Items[index].SubItems["todayUp"].Text = Utils.HumanFy(it.todayUp);
lvServers.Items[index].SubItems["totalDown"].Text = Utils.HumanFy(it.totalDown);
lvServers.Items[index].SubItems["totalUp"].Text = Utils.HumanFy(it.totalUp);
lvServers.EndUpdate();
});
}
for (int i = 0; i < lstVmess.Count; i++) for (int i = 0; i < lstVmess.Count; i++)
{ {
int index = statistics.FindIndex(item_ => item_.itemId == lstVmess[i].indexId); int index = statistics.FindIndex(item_ => item_.itemId == lstVmess[i].indexId);
@@ -1264,7 +1345,7 @@ namespace v2rayN.Forms
int index = GetLvSelectedIndex(); int index = GetLvSelectedIndex();
if (index < 0) if (index < 0)
{ {
UI.Show(UIRes.I18N("PleaseSelectServer")); UI.Show(ResUI.PleaseSelectServer);
return; return;
} }
if (ConfigHandler.MoveServer(ref config, ref lstVmess, index, eMove) == 0) if (ConfigHandler.MoveServer(ref config, ref lstVmess, index, eMove) == 0)
@@ -1281,7 +1362,9 @@ namespace v2rayN.Forms
item.Selected = true; item.Selected = true;
} }
} }
private void menuMoveToGroup_Click(object sender, EventArgs e)
{
}
#endregion #endregion
#region #region
@@ -1338,15 +1421,15 @@ namespace v2rayN.Forms
private void tsbCheckUpdateCore_Click(object sender, EventArgs e) private void tsbCheckUpdateCore_Click(object sender, EventArgs e)
{ {
CheckUpdateCore("v2fly"); CheckUpdateCore(ECoreType.v2fly);
} }
private void tsbCheckUpdateXrayCore_Click(object sender, EventArgs e) private void tsbCheckUpdateXrayCore_Click(object sender, EventArgs e)
{ {
CheckUpdateCore("xray"); CheckUpdateCore(ECoreType.Xray);
} }
private void CheckUpdateCore(string type) private void CheckUpdateCore(ECoreType type)
{ {
void _updateUI(bool success, string msg) void _updateUI(bool success, string msg)
{ {
@@ -1358,12 +1441,12 @@ namespace v2rayN.Forms
string fileName = Utils.GetPath(Utils.GetDownloadFileName(msg)); string fileName = Utils.GetPath(Utils.GetDownloadFileName(msg));
FileManager.ZipExtractToFile(fileName, config.ignoreGeoUpdateCore ? "geo" : ""); FileManager.ZipExtractToFile(fileName, config.ignoreGeoUpdateCore ? "geo" : "");
AppendText(false, UIRes.I18N("MsgUpdateV2rayCoreSuccessfullyMore")); AppendText(false, ResUI.MsgUpdateV2rayCoreSuccessfullyMore);
Global.reloadV2ray = true; Global.reloadV2ray = true;
_ = LoadV2ray(); _ = LoadV2ray();
AppendText(false, UIRes.I18N("MsgUpdateV2rayCoreSuccessfully")); AppendText(false, ResUI.MsgUpdateV2rayCoreSuccessfully);
} }
}; };
(new UpdateHandle()).CheckUpdateCore(type, config, _updateUI); (new UpdateHandle()).CheckUpdateCore(type, config, _updateUI);
@@ -1605,7 +1688,7 @@ namespace v2rayN.Forms
if (fm.ShowDialog() == DialogResult.OK) if (fm.ShowDialog() == DialogResult.OK)
{ {
MsgFilter = fm.MsgFilter; MsgFilter = fm.MsgFilter;
gbMsgTitle.Text = string.Format(UIRes.I18N("MsgInformationTitle"), MsgFilter); gbMsgTitle.Text = string.Format(ResUI.MsgInformationTitle, MsgFilter);
} }
} }
#endregion #endregion

View File

@@ -206,6 +206,12 @@
<data name="toolStripSeparator3.Size" type="System.Drawing.Size, System.Drawing"> <data name="toolStripSeparator3.Size" type="System.Drawing.Size, System.Drawing">
<value>352, 6</value> <value>352, 6</value>
</data> </data>
<data name="menuMoveToGroup.Size" type="System.Drawing.Size, System.Drawing">
<value>355, 22</value>
</data>
<data name="menuMoveToGroup.Text" xml:space="preserve">
<value>Move to Group</value>
</data>
<data name="menuMoveTop.Size" type="System.Drawing.Size, System.Drawing"> <data name="menuMoveTop.Size" type="System.Drawing.Size, System.Drawing">
<value>355, 22</value> <value>355, 22</value>
</data> </data>
@@ -302,8 +308,20 @@
<data name="menuExport2SubContent.Text" xml:space="preserve"> <data name="menuExport2SubContent.Text" xml:space="preserve">
<value>Export subscription (base64) share to clipboard</value> <value>Export subscription (base64) share to clipboard</value>
</data> </data>
<data name="tsbServer.ImageTransparentColor" type="System.Drawing.Color, System.Drawing">
<value>Magenta</value>
</data>
<data name="tsbServer.Size" type="System.Drawing.Size, System.Drawing">
<value>64, 53</value>
</data>
<data name="tsbServer.Text" xml:space="preserve">
<value>Servers</value>
</data>
<data name="tsbServer.TextImageRelation" type="System.Windows.Forms.TextImageRelation, System.Windows.Forms">
<value>ImageAboveText</value>
</data>
<data name="cmsLv.Size" type="System.Drawing.Size, System.Drawing"> <data name="cmsLv.Size" type="System.Drawing.Size, System.Drawing">
<value>356, 622</value> <value>356, 666</value>
</data> </data>
<data name="&gt;&gt;cmsLv.Name" xml:space="preserve"> <data name="&gt;&gt;cmsLv.Name" xml:space="preserve">
<value>cmsLv</value> <value>cmsLv</value>
@@ -452,18 +470,6 @@
<data name="&gt;&gt;scMain.ZOrder" xml:space="preserve"> <data name="&gt;&gt;scMain.ZOrder" xml:space="preserve">
<value>0</value> <value>0</value>
</data> </data>
<data name="tsbServer.ImageTransparentColor" type="System.Drawing.Color, System.Drawing">
<value>Magenta</value>
</data>
<data name="tsbServer.Size" type="System.Drawing.Size, System.Drawing">
<value>64, 53</value>
</data>
<data name="tsbServer.Text" xml:space="preserve">
<value>Servers</value>
</data>
<data name="tsbServer.TextImageRelation" type="System.Windows.Forms.TextImageRelation, System.Windows.Forms">
<value>ImageAboveText</value>
</data>
<data name="splitContainer1.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms"> <data name="splitContainer1.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
<value>Fill</value> <value>Fill</value>
</data> </data>
@@ -549,7 +555,7 @@
<value>Set message filters</value> <value>Set message filters</value>
</data> </data>
<data name="cmsMsgBox.Size" type="System.Drawing.Size, System.Drawing"> <data name="cmsMsgBox.Size" type="System.Drawing.Size, System.Drawing">
<value>228, 158</value> <value>228, 136</value>
</data> </data>
<data name="&gt;&gt;cmsMsgBox.Name" xml:space="preserve"> <data name="&gt;&gt;cmsMsgBox.Name" xml:space="preserve">
<value>cmsMsgBox</value> <value>cmsMsgBox</value>
@@ -1205,6 +1211,12 @@
<data name="&gt;&gt;toolStripSeparator3.Type" xml:space="preserve"> <data name="&gt;&gt;toolStripSeparator3.Type" xml:space="preserve">
<value>System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data> </data>
<data name="&gt;&gt;menuMoveToGroup.Name" xml:space="preserve">
<value>menuMoveToGroup</value>
</data>
<data name="&gt;&gt;menuMoveToGroup.Type" xml:space="preserve">
<value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;menuMoveTop.Name" xml:space="preserve"> <data name="&gt;&gt;menuMoveTop.Name" xml:space="preserve">
<value>menuMoveTop</value> <value>menuMoveTop</value>
</data> </data>

View File

@@ -573,4 +573,7 @@
<data name="tsbClose.Text" xml:space="preserve"> <data name="tsbClose.Text" xml:space="preserve">
<value> 关闭窗口 </value> <value> 关闭窗口 </value>
</data> </data>
<data name="menuMoveToGroup.Text" xml:space="preserve">
<value>移至分组</value>
</data>
</root> </root>

View File

@@ -5,6 +5,7 @@ using System.Windows.Forms;
using v2rayN.Base; using v2rayN.Base;
using v2rayN.Handler; using v2rayN.Handler;
using v2rayN.Mode; using v2rayN.Mode;
using v2rayN.Resx;
namespace v2rayN.Forms namespace v2rayN.Forms
{ {
@@ -101,9 +102,9 @@ namespace v2rayN.Forms
ComboItem[] cbSource = new ComboItem[] ComboItem[] cbSource = new ComboItem[]
{ {
new ComboItem{ID = (int)Global.StatisticsFreshRate.quick, Text = UIRes.I18N("QuickFresh")}, new ComboItem{ID = (int)Global.StatisticsFreshRate.quick, Text = ResUI.QuickFresh},
new ComboItem{ID = (int)Global.StatisticsFreshRate.medium, Text = UIRes.I18N("MediumFresh")}, new ComboItem{ID = (int)Global.StatisticsFreshRate.medium, Text = ResUI.MediumFresh},
new ComboItem{ID = (int)Global.StatisticsFreshRate.slow, Text = UIRes.I18N("SlowFresh")}, new ComboItem{ID = (int)Global.StatisticsFreshRate.slow, Text = ResUI.SlowFresh},
}; };
cbFreshrate.DataSource = cbSource; cbFreshrate.DataSource = cbSource;
@@ -146,7 +147,7 @@ namespace v2rayN.Forms
config.coreTypeItem.Add(new CoreTypeItem() config.coreTypeItem.Add(new CoreTypeItem()
{ {
configType = it, configType = it,
coreType = ECoreType.v2fly coreType = ECoreType.Xray
}); });
} }
for (int k = 1; k <= config.coreTypeItem.Count; k++) for (int k = 1; k <= config.coreTypeItem.Count; k++)
@@ -187,7 +188,7 @@ namespace v2rayN.Forms
} }
else else
{ {
UI.ShowWarning(UIRes.I18N("OperationFailed")); UI.ShowWarning(ResUI.OperationFailed);
} }
} }
@@ -211,12 +212,12 @@ namespace v2rayN.Forms
bool sniffingEnabled = chksniffingEnabled.Checked; bool sniffingEnabled = chksniffingEnabled.Checked;
if (Utils.IsNullOrEmpty(localPort) || !Utils.IsNumberic(localPort)) if (Utils.IsNullOrEmpty(localPort) || !Utils.IsNumberic(localPort))
{ {
UI.Show(UIRes.I18N("FillLocalListeningPort")); UI.Show(ResUI.FillLocalListeningPort);
return -1; return -1;
} }
if (Utils.IsNullOrEmpty(protocol)) if (Utils.IsNullOrEmpty(protocol))
{ {
UI.Show(UIRes.I18N("PleaseSelectProtocol")); UI.Show(ResUI.PleaseSelectProtocol);
return -1; return -1;
} }
@@ -229,7 +230,7 @@ namespace v2rayN.Forms
{ {
if (remoteDNS.Contains("{") || remoteDNS.Contains("}")) if (remoteDNS.Contains("{") || remoteDNS.Contains("}"))
{ {
UI.Show(UIRes.I18N("FillCorrectDNSText")); UI.Show(ResUI.FillCorrectDNSText);
return -1; return -1;
} }
} }
@@ -248,12 +249,12 @@ namespace v2rayN.Forms
{ {
if (Utils.IsNullOrEmpty(localPort2) || !Utils.IsNumberic(localPort2)) if (Utils.IsNullOrEmpty(localPort2) || !Utils.IsNumberic(localPort2))
{ {
UI.Show(UIRes.I18N("FillLocalListeningPort")); UI.Show(ResUI.FillLocalListeningPort);
return -1; return -1;
} }
if (Utils.IsNullOrEmpty(protocol2)) if (Utils.IsNullOrEmpty(protocol2))
{ {
UI.Show(UIRes.I18N("PleaseSelectProtocol")); UI.Show(ResUI.PleaseSelectProtocol);
return -1; return -1;
} }
if (config.inbound.Count < 2) if (config.inbound.Count < 2)
@@ -312,7 +313,7 @@ namespace v2rayN.Forms
|| Utils.IsNullOrEmpty(readBufferSize) || !Utils.IsNumberic(readBufferSize) || Utils.IsNullOrEmpty(readBufferSize) || !Utils.IsNumberic(readBufferSize)
|| Utils.IsNullOrEmpty(writeBufferSize) || !Utils.IsNumberic(writeBufferSize)) || Utils.IsNullOrEmpty(writeBufferSize) || !Utils.IsNumberic(writeBufferSize))
{ {
UI.Show(UIRes.I18N("FillKcpParameters")); UI.Show(ResUI.FillKcpParameters);
return -1; return -1;
} }
config.kcpItem.mtu = Utils.ToInt(mtu); config.kcpItem.mtu = Utils.ToInt(mtu);

View File

@@ -4,6 +4,7 @@ using System.Windows.Forms;
using v2rayN.Base; using v2rayN.Base;
using v2rayN.Handler; using v2rayN.Handler;
using v2rayN.Mode; using v2rayN.Mode;
using v2rayN.Resx;
namespace v2rayN.Forms namespace v2rayN.Forms
{ {
@@ -47,8 +48,8 @@ namespace v2rayN.Forms
} }
rulesItem.inboundTag = inboundTag; rulesItem.inboundTag = inboundTag;
rulesItem.outboundTag = cmbOutboundTag.Text; rulesItem.outboundTag = cmbOutboundTag.Text;
rulesItem.domain = Utils.String2List(txtDomain.Text); rulesItem.domain = Utils.String2ListSorted(txtDomain.Text);
rulesItem.ip = Utils.String2List(txtIP.Text); rulesItem.ip = Utils.String2ListSorted(txtIP.Text);
var protocol = new List<string>(); var protocol = new List<string>();
for (int i = 0; i < clbProtocol.Items.Count; i++) for (int i = 0; i < clbProtocol.Items.Count; i++)
@@ -125,7 +126,7 @@ namespace v2rayN.Forms
} }
if (!hasRule) if (!hasRule)
{ {
UI.ShowWarning(string.Format(UIRes.I18N("RoutingRuleDetailRequiredTips"), "Port/Protocol/Domain/IP")); UI.ShowWarning(string.Format(ResUI.RoutingRuleDetailRequiredTips, "Port/Protocol/Domain/IP"));
return; return;
} }
this.DialogResult = DialogResult.OK; this.DialogResult = DialogResult.OK;

View File

@@ -4,6 +4,7 @@ using System.Windows.Forms;
using v2rayN.Base; using v2rayN.Base;
using v2rayN.Handler; using v2rayN.Handler;
using v2rayN.Mode; using v2rayN.Mode;
using v2rayN.Resx;
namespace v2rayN.Forms namespace v2rayN.Forms
{ {
@@ -54,6 +55,7 @@ namespace v2rayN.Forms
lvRoutings.View = View.Details; lvRoutings.View = View.Details;
lvRoutings.MultiSelect = true; lvRoutings.MultiSelect = true;
lvRoutings.HeaderStyle = ColumnHeaderStyle.Clickable; lvRoutings.HeaderStyle = ColumnHeaderStyle.Clickable;
lvRoutings.RegisterDragEvent(UpdateDragEventHandler);
lvRoutings.Columns.Add("", 30); lvRoutings.Columns.Add("", 30);
lvRoutings.Columns.Add("outboundTag", 80); lvRoutings.Columns.Add("outboundTag", 80);
@@ -66,6 +68,17 @@ namespace v2rayN.Forms
lvRoutings.EndUpdate(); lvRoutings.EndUpdate();
} }
private void UpdateDragEventHandler(int index, int targetIndex)
{
if (index < 0 || targetIndex < 0)
{
return;
}
if (ConfigHandler.MoveRoutingRule(ref routingItem, index, EMove.Position, targetIndex) == 0)
{
RefreshRoutingsView();
}
}
private void RefreshRoutingsView() private void RefreshRoutingsView()
{ {
@@ -102,7 +115,7 @@ namespace v2rayN.Forms
} }
else else
{ {
UI.ShowWarning(UIRes.I18N("OperationFailed")); UI.ShowWarning(ResUI.OperationFailed);
} }
} }
@@ -142,7 +155,7 @@ namespace v2rayN.Forms
{ {
if (lvRoutings.SelectedIndices.Count <= 0) if (lvRoutings.SelectedIndices.Count <= 0)
{ {
UI.Show(UIRes.I18N("PleaseSelectRules")); UI.Show(ResUI.PleaseSelectRules);
return index; return index;
} }
@@ -186,7 +199,7 @@ namespace v2rayN.Forms
int index = GetLvSelectedIndex(); int index = GetLvSelectedIndex();
if (index < 0) if (index < 0)
{ {
UI.Show(UIRes.I18N("PleaseSelectRules")); UI.Show(ResUI.PleaseSelectRules);
return; return;
} }
if (ConfigHandler.MoveRoutingRule(ref routingItem, index, eMove) == 0) if (ConfigHandler.MoveRoutingRule(ref routingItem, index, eMove) == 0)
@@ -220,7 +233,7 @@ namespace v2rayN.Forms
{ {
return; return;
} }
if (UI.ShowYesNo(UIRes.I18N("RemoveRules")) == DialogResult.No) if (UI.ShowYesNo(ResUI.RemoveRules) == DialogResult.No)
{ {
return; return;
} }
@@ -241,7 +254,7 @@ namespace v2rayN.Forms
if (lst.Count > 0) if (lst.Count > 0)
{ {
Utils.SetClipboardData(Utils.ToJson(lst)); Utils.SetClipboardData(Utils.ToJson(lst));
//UI.Show(UIRes.I18N("OperationSuccess")); //UI.Show(ResUI.OperationSuccess"));
} }
} }
@@ -311,7 +324,7 @@ namespace v2rayN.Forms
if (AddBatchRoutingRules(ref routingItem, result) == 0) if (AddBatchRoutingRules(ref routingItem, result) == 0)
{ {
RefreshRoutingsView(); RefreshRoutingsView();
UI.Show(UIRes.I18N("OperationSuccess")); UI.Show(ResUI.OperationSuccess);
} }
} }
@@ -321,7 +334,7 @@ namespace v2rayN.Forms
if (AddBatchRoutingRules(ref routingItem, clipboardData) == 0) if (AddBatchRoutingRules(ref routingItem, clipboardData) == 0)
{ {
RefreshRoutingsView(); RefreshRoutingsView();
UI.Show(UIRes.I18N("OperationSuccess")); UI.Show(ResUI.OperationSuccess);
} }
} }
private void menuImportRulesFromUrl_Click(object sender, EventArgs e) private void menuImportRulesFromUrl_Click(object sender, EventArgs e)
@@ -329,7 +342,7 @@ namespace v2rayN.Forms
var url = txtUrl.Text.Trim(); var url = txtUrl.Text.Trim();
if (Utils.IsNullOrEmpty(url)) if (Utils.IsNullOrEmpty(url))
{ {
UI.Show(UIRes.I18N("MsgNeedUrl")); UI.Show(ResUI.MsgNeedUrl);
return; return;
} }
DownloadHandle downloadHandle = new DownloadHandle(); DownloadHandle downloadHandle = new DownloadHandle();
@@ -337,13 +350,13 @@ namespace v2rayN.Forms
if (AddBatchRoutingRules(ref routingItem, clipboardData) == 0) if (AddBatchRoutingRules(ref routingItem, clipboardData) == 0)
{ {
RefreshRoutingsView(); RefreshRoutingsView();
UI.Show(UIRes.I18N("OperationSuccess")); UI.Show(ResUI.OperationSuccess);
} }
} }
private int AddBatchRoutingRules(ref RoutingItem routingItem, string clipboardData) private int AddBatchRoutingRules(ref RoutingItem routingItem, string clipboardData)
{ {
bool blReplace = false; bool blReplace = false;
if (UI.ShowYesNo(UIRes.I18N("AddBatchRoutingRulesYesNo")) == DialogResult.No) if (UI.ShowYesNo(ResUI.AddBatchRoutingRulesYesNo) == DialogResult.No)
{ {
blReplace = true; blReplace = true;
} }

View File

@@ -4,6 +4,7 @@ using System.Windows.Forms;
using v2rayN.Base; using v2rayN.Base;
using v2rayN.Handler; using v2rayN.Handler;
using v2rayN.Mode; using v2rayN.Mode;
using v2rayN.Resx;
namespace v2rayN.Forms namespace v2rayN.Forms
{ {
@@ -61,7 +62,7 @@ namespace v2rayN.Forms
} }
else else
{ {
UI.ShowWarning(UIRes.I18N("OperationFailed")); UI.ShowWarning(ResUI.OperationFailed);
} }
} }
@@ -144,10 +145,10 @@ namespace v2rayN.Forms
lvRoutings.HeaderStyle = ColumnHeaderStyle.Clickable; lvRoutings.HeaderStyle = ColumnHeaderStyle.Clickable;
lvRoutings.Columns.Add("", 30); lvRoutings.Columns.Add("", 30);
lvRoutings.Columns.Add(UIRes.I18N("LvAlias"), 200); lvRoutings.Columns.Add(ResUI.LvAlias, 200);
lvRoutings.Columns.Add(UIRes.I18N("LvCount"), 60); lvRoutings.Columns.Add(ResUI.LvCount, 60);
lvRoutings.Columns.Add(UIRes.I18N("LvUrl"), 240); lvRoutings.Columns.Add(ResUI.LvUrl, 240);
lvRoutings.Columns.Add(UIRes.I18N("LvCustomIcon"), 240); lvRoutings.Columns.Add(ResUI.LvCustomIcon, 240);
lvRoutings.EndUpdate(); lvRoutings.EndUpdate();
} }
@@ -211,7 +212,7 @@ namespace v2rayN.Forms
{ {
if (lvRoutings.SelectedIndices.Count <= 0) if (lvRoutings.SelectedIndices.Count <= 0)
{ {
UI.Show(UIRes.I18N("PleaseSelectRules")); UI.Show(ResUI.PleaseSelectRules);
return index; return index;
} }
@@ -259,7 +260,7 @@ namespace v2rayN.Forms
{ {
return; return;
} }
if (UI.ShowYesNo(UIRes.I18N("RemoveRules")) == DialogResult.No) if (UI.ShowYesNo(ResUI.RemoveRules) == DialogResult.No)
{ {
return; return;
} }
@@ -282,7 +283,7 @@ namespace v2rayN.Forms
{ {
if (index < 0) if (index < 0)
{ {
UI.Show(UIRes.I18N("PleaseSelectServer")); UI.Show(ResUI.PleaseSelectServer);
return -1; return -1;
} }
if (ConfigHandler.SetDefaultRouting(ref config, index) == 0) if (ConfigHandler.SetDefaultRouting(ref config, index) == 0)
@@ -301,7 +302,7 @@ namespace v2rayN.Forms
txtBlockDomain.Text = "geosite:category-ads-all"; txtBlockDomain.Text = "geosite:category-ads-all";
UI.Show(UIRes.I18N("OperationSuccess")); UI.Show(ResUI.OperationSuccess);
} }
private void menuImportAdvancedRules_Click(object sender, EventArgs e) private void menuImportAdvancedRules_Click(object sender, EventArgs e)

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Windows.Forms; using System.Windows.Forms;
using v2rayN.Mode; using v2rayN.Mode;
using v2rayN.Resx;
namespace v2rayN.Forms namespace v2rayN.Forms
{ {
@@ -156,34 +157,34 @@ namespace v2rayN.Forms
if (network.Equals(Global.DefaultNetwork)) if (network.Equals(Global.DefaultNetwork))
{ {
tipRequestHost.Text = UIRes.I18N("TransportRequestHostTip1"); tipRequestHost.Text = ResUI.TransportRequestHostTip1;
tipHeaderType.Text = UIRes.I18N("TransportHeaderTypeTip1"); tipHeaderType.Text = ResUI.TransportHeaderTypeTip1;
} }
else if (network.Equals("kcp")) else if (network.Equals("kcp"))
{ {
tipHeaderType.Text = UIRes.I18N("TransportHeaderTypeTip2"); tipHeaderType.Text = ResUI.TransportHeaderTypeTip2;
tipPath.Text = UIRes.I18N("TransportPathTip5"); tipPath.Text = ResUI.TransportPathTip5;
} }
else if (network.Equals("ws")) else if (network.Equals("ws"))
{ {
tipRequestHost.Text = UIRes.I18N("TransportRequestHostTip2"); tipRequestHost.Text = ResUI.TransportRequestHostTip2;
tipPath.Text = UIRes.I18N("TransportPathTip1"); tipPath.Text = ResUI.TransportPathTip1;
} }
else if (network.Equals("h2")) else if (network.Equals("h2"))
{ {
tipRequestHost.Text = UIRes.I18N("TransportRequestHostTip3"); tipRequestHost.Text = ResUI.TransportRequestHostTip3;
tipPath.Text = UIRes.I18N("TransportPathTip2"); tipPath.Text = ResUI.TransportPathTip2;
} }
else if (network.Equals("quic")) else if (network.Equals("quic"))
{ {
tipRequestHost.Text = UIRes.I18N("TransportRequestHostTip4"); tipRequestHost.Text = ResUI.TransportRequestHostTip4;
tipPath.Text = UIRes.I18N("TransportPathTip3"); tipPath.Text = ResUI.TransportPathTip3;
tipHeaderType.Text = UIRes.I18N("TransportHeaderTypeTip3"); tipHeaderType.Text = ResUI.TransportHeaderTypeTip3;
} }
else if (network.Equals("grpc")) else if (network.Equals("grpc"))
{ {
tipPath.Text = UIRes.I18N("TransportPathTip4"); tipPath.Text = ResUI.TransportPathTip4;
tipHeaderType.Text = UIRes.I18N("TransportHeaderTypeTip4"); tipHeaderType.Text = ResUI.TransportHeaderTypeTip4;
labHeaderType.Visible = false; labHeaderType.Visible = false;
} }
} }

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Windows.Forms; using System.Windows.Forms;
using v2rayN.Handler; using v2rayN.Handler;
using v2rayN.Mode; using v2rayN.Mode;
using v2rayN.Resx;
namespace v2rayN.Forms namespace v2rayN.Forms
{ {
@@ -74,7 +75,7 @@ namespace v2rayN.Forms
} }
else else
{ {
UI.ShowWarning(UIRes.I18N("OperationFailed")); UI.ShowWarning(ResUI.OperationFailed);
} }
} }

View File

@@ -15,6 +15,7 @@ namespace v2rayN
public const string xrayCoreUrl = "https://github.com/XTLS/Xray-core/releases"; public const string xrayCoreUrl = "https://github.com/XTLS/Xray-core/releases";
public const string NUrl = @"https://github.com/2dust/v2rayN/releases"; public const string NUrl = @"https://github.com/2dust/v2rayN/releases";
public const string clashCoreUrl = "https://github.com/Dreamacro/clash/releases"; public const string clashCoreUrl = "https://github.com/Dreamacro/clash/releases";
public const string hysteriaCoreUrl = "https://github.com/HyNetwork/hysteria/releases";

View File

@@ -15,6 +15,7 @@ namespace v2rayN.Handler
class ConfigHandler class ConfigHandler
{ {
private static string configRes = Global.ConfigFileName; private static string configRes = Global.ConfigFileName;
private static object objLock = new object();
#region ConfigHandler #region ConfigHandler
@@ -184,6 +185,31 @@ namespace v2rayN.Handler
LazyConfig.Instance.SetConfig(ref config); LazyConfig.Instance.SetConfig(ref config);
return 0; return 0;
} }
/// <summary>
/// 保参数
/// </summary>
/// <param name="config"></param>
/// <returns></returns>
public static int SaveConfig(ref Config config, bool reload = true)
{
Global.reloadV2ray = reload;
ToJsonFile(config);
return 0;
}
/// <summary>
/// 存储文件
/// </summary>
/// <param name="config"></param>
private static void ToJsonFile(Config config)
{
lock (objLock)
{
Utils.ToJsonFile(config, Utils.GetPath(configRes));
}
}
#endregion #endregion
@@ -235,7 +261,7 @@ namespace v2rayN.Handler
var index = config.FindIndexId(item.indexId); var index = config.FindIndexId(item.indexId);
if (index >= 0) if (index >= 0)
{ {
config.vmess.RemoveAt(index); RemoveVmessItem(config, index);
} }
} }
@@ -323,29 +349,6 @@ namespace v2rayN.Handler
return config.vmess[index]; return config.vmess[index];
} }
/// <summary>
/// 保参数
/// </summary>
/// <param name="config"></param>
/// <returns></returns>
public static int SaveConfig(ref Config config, bool reload = true)
{
Global.reloadV2ray = reload;
ToJsonFile(config);
return 0;
}
/// <summary>
/// 存储文件
/// </summary>
/// <param name="config"></param>
private static void ToJsonFile(Config config)
{
Utils.ToJsonFile(config, Utils.GetPath(configRes));
}
/// <summary> /// <summary>
/// 移动服务器 /// 移动服务器
/// </summary> /// </summary>
@@ -354,7 +357,7 @@ namespace v2rayN.Handler
/// <param name="index"></param> /// <param name="index"></param>
/// <param name="eMove"></param> /// <param name="eMove"></param>
/// <returns></returns> /// <returns></returns>
public static int MoveServer(ref Config config, ref List<VmessItem> lstVmess, int index, EMove eMove) public static int MoveServer(ref Config config, ref List<VmessItem> lstVmess, int index, EMove eMove, int pos = -1)
{ {
int count = lstVmess.Count; int count = lstVmess.Count;
if (index < 0 || index > lstVmess.Count - 1) if (index < 0 || index > lstVmess.Count - 1)
@@ -410,6 +413,9 @@ namespace v2rayN.Handler
break; break;
} }
case EMove.Position:
lstVmess[index].sort = pos * 10 + 1;
break;
} }
ToJsonFile(config); ToJsonFile(config);
@@ -423,7 +429,7 @@ namespace v2rayN.Handler
/// <param name="config"></param> /// <param name="config"></param>
/// <param name="vmessItem"></param> /// <param name="vmessItem"></param>
/// <returns></returns> /// <returns></returns>
public static int AddCustomServer(ref Config config, VmessItem vmessItem) public static int AddCustomServer(ref Config config, VmessItem vmessItem, bool blDelete)
{ {
var fileName = vmessItem.address; var fileName = vmessItem.address;
if (!File.Exists(fileName)) if (!File.Exists(fileName))
@@ -436,7 +442,11 @@ namespace v2rayN.Handler
try try
{ {
File.Copy(fileName, Path.Combine(Utils.GetTempPath(), newFileName)); File.Copy(fileName, Path.Combine(Utils.GetConfigPath(), newFileName));
if (blDelete)
{
File.Delete(fileName);
}
} }
catch catch
{ {
@@ -485,7 +495,7 @@ namespace v2rayN.Handler
vmessItem.id = vmessItem.id.TrimEx(); vmessItem.id = vmessItem.id.TrimEx();
vmessItem.security = vmessItem.security.TrimEx(); vmessItem.security = vmessItem.security.TrimEx();
if (!config.GetShadowsocksSecuritys().Contains(vmessItem.security)) if (!LazyConfig.Instance.GetShadowsocksSecuritys().Contains(vmessItem.security))
{ {
return -1; return -1;
} }
@@ -522,7 +532,6 @@ namespace v2rayN.Handler
return 0; return 0;
} }
/// <summary> /// <summary>
/// 添加服务器或编辑 /// 添加服务器或编辑
/// </summary> /// </summary>
@@ -619,178 +628,6 @@ namespace v2rayN.Handler
return 0; return 0;
} }
/// <summary>
/// 批量添加服务器
/// </summary>
/// <param name="config"></param>
/// <param name="clipboardData"></param>
/// <param name="subid"></param>
/// <returns>成功导入的数量</returns>
public static int AddBatchServers(ref Config config, string clipboardData, string subid, List<VmessItem> lstOriSub, string groupId)
{
if (Utils.IsNullOrEmpty(clipboardData))
{
return -1;
}
//copy sub items
if (!Utils.IsNullOrEmpty(subid))
{
RemoveServerViaSubid(ref config, subid);
}
//if (clipboardData.IndexOf("vmess") >= 0 && clipboardData.IndexOf("vmess") == clipboardData.LastIndexOf("vmess"))
//{
// clipboardData = clipboardData.Replace("\r\n", "").Replace("\n", "");
//}
int countServers = 0;
//string[] arrData = clipboardData.Split(new string[] { "\r\n" }, StringSplitOptions.None);
string[] arrData = clipboardData.Split(Environment.NewLine.ToCharArray());
foreach (string str in arrData)
{
//maybe sub
if (Utils.IsNullOrEmpty(subid) && (str.StartsWith(Global.httpsProtocol) || str.StartsWith(Global.httpProtocol)))
{
if (AddSubItem(ref config, str) == 0)
{
countServers++;
}
continue;
}
VmessItem vmessItem = ShareHandler.ImportFromClipboardConfig(str, out string msg);
if (vmessItem == null)
{
continue;
}
//exist sub items
if (!Utils.IsNullOrEmpty(subid))
{
var existItem = lstOriSub?.FirstOrDefault(t => CompareVmessItem(t, vmessItem, true));
if (existItem != null)
{
vmessItem = existItem;
}
vmessItem.subid = subid;
}
//groupId
vmessItem.groupId = groupId;
if (vmessItem.configType == EConfigType.Vmess)
{
if (AddServer(ref config, vmessItem, false) == 0)
{
countServers++;
}
}
else if (vmessItem.configType == EConfigType.Shadowsocks)
{
if (AddShadowsocksServer(ref config, vmessItem, false) == 0)
{
countServers++;
}
}
else if (vmessItem.configType == EConfigType.Socks)
{
if (AddSocksServer(ref config, vmessItem, false) == 0)
{
countServers++;
}
}
else if (vmessItem.configType == EConfigType.Trojan)
{
if (AddTrojanServer(ref config, vmessItem, false) == 0)
{
countServers++;
}
}
else if (vmessItem.configType == EConfigType.VLESS)
{
if (AddVlessServer(ref config, vmessItem, false) == 0)
{
countServers++;
}
}
}
ToJsonFile(config);
return countServers;
}
/// <summary>
/// add sub
/// </summary>
/// <param name="config"></param>
/// <param name="url"></param>
/// <returns></returns>
public static int AddSubItem(ref Config config, string url)
{
//already exists
if (config.subItem.FindIndex(e => e.url == url) >= 0)
{
return 0;
}
SubItem subItem = new SubItem
{
id = string.Empty,
remarks = "import sub",
url = url
};
config.subItem.Add(subItem);
return SaveSubItem(ref config);
}
/// <summary>
/// save sub
/// </summary>
/// <param name="config"></param>
/// <returns></returns>
public static int SaveSubItem(ref Config config)
{
if (config.subItem == null)
{
return -1;
}
foreach (SubItem item in config.subItem)
{
if (Utils.IsNullOrEmpty(item.id))
{
item.id = Utils.GetGUID(false);
}
}
ToJsonFile(config);
return 0;
}
/// <summary>
/// 移除服务器
/// </summary>
/// <param name="config"></param>
/// <param name="subid"></param>
/// <returns></returns>
public static int RemoveServerViaSubid(ref Config config, string subid)
{
if (Utils.IsNullOrEmpty(subid) || config.vmess.Count <= 0)
{
return -1;
}
for (int k = config.vmess.Count - 1; k >= 0; k--)
{
if (config.vmess[k].subid.Equals(subid))
{
config.vmess.RemoveAt(k);
}
}
ToJsonFile(config);
return 0;
}
public static int SortServers(ref Config config, ref List<VmessItem> lstVmess, EServerColName name, bool asc) public static int SortServers(ref Config config, ref List<VmessItem> lstVmess, EServerColName name, bool asc)
{ {
if (lstVmess.Count <= 0) if (lstVmess.Count <= 0)
@@ -884,14 +721,14 @@ namespace v2rayN.Handler
var index = config.FindIndexId(item.indexId); var index = config.FindIndexId(item.indexId);
if (index >= 0) if (index >= 0)
{ {
config.vmess.RemoveAt(index); RemoveVmessItem(config, index);
} }
} }
} }
//if (!keepOlder) list.Reverse(); //if (!keepOlder) list.Reverse();
//config.vmess = list; //config.vmess = list;
return 0; return list.Count;
} }
public static int AddServerCommon(ref Config config, VmessItem vmessItem) public static int AddServerCommon(ref Config config, VmessItem vmessItem)
@@ -910,6 +747,10 @@ namespace v2rayN.Handler
{ {
vmessItem.indexId = Utils.GetGUID(false); vmessItem.indexId = Utils.GetGUID(false);
} }
else if (vmessItem.indexId == config.indexId)
{
Global.reloadV2ray = true;
}
if (!config.vmess.Exists(it => it.indexId == vmessItem.indexId)) if (!config.vmess.Exists(it => it.indexId == vmessItem.indexId))
{ {
var maxSort = config.vmess.Any() ? config.vmess.Max(t => t.sort) : 0; var maxSort = config.vmess.Any() ? config.vmess.Max(t => t.sort) : 0;
@@ -918,11 +759,6 @@ namespace v2rayN.Handler
config.vmess.Add(vmessItem); config.vmess.Add(vmessItem);
} }
//if (config.vmess.Count == 1)
//{
// config.indexId = config.vmess[0].indexId;
// Global.reloadV2ray = true;
//}
return 0; return 0;
} }
@@ -949,6 +785,300 @@ namespace v2rayN.Handler
&& (remarks ? o.remarks == n.remarks : true); && (remarks ? o.remarks == n.remarks : true);
} }
private static int RemoveVmessItem(Config config, int index)
{
try
{
if (config.vmess[index].configType == EConfigType.Custom)
{
File.Delete(Utils.GetConfigPath(config.vmess[index].address));
}
}
catch (Exception ex)
{
Utils.SaveLog("RemoveVmessItem", ex);
}
config.vmess.RemoveAt(index);
return 0;
}
#endregion
#region Batch add servers
/// <summary>
/// 批量添加服务器
/// </summary>
/// <param name="config"></param>
/// <param name="clipboardData"></param>
/// <param name="subid"></param>
/// <returns>成功导入的数量</returns>
private static int AddBatchServers(ref Config config, string clipboardData, string subid, List<VmessItem> lstOriSub, string groupId)
{
if (Utils.IsNullOrEmpty(clipboardData))
{
return -1;
}
//copy sub items
if (!Utils.IsNullOrEmpty(subid))
{
RemoveServerViaSubid(ref config, subid);
}
//if (clipboardData.IndexOf("vmess") >= 0 && clipboardData.IndexOf("vmess") == clipboardData.LastIndexOf("vmess"))
//{
// clipboardData = clipboardData.Replace("\r\n", "").Replace("\n", "");
//}
int countServers = 0;
//string[] arrData = clipboardData.Split(new string[] { "\r\n" }, StringSplitOptions.None);
string[] arrData = clipboardData.Split(Environment.NewLine.ToCharArray());
foreach (string str in arrData)
{
//maybe sub
if (Utils.IsNullOrEmpty(subid) && (str.StartsWith(Global.httpsProtocol) || str.StartsWith(Global.httpProtocol)))
{
if (AddSubItem(ref config, str) == 0)
{
countServers++;
}
continue;
}
VmessItem vmessItem = ShareHandler.ImportFromClipboardConfig(str, out string msg);
if (vmessItem == null)
{
continue;
}
//exist sub items
if (!Utils.IsNullOrEmpty(subid))
{
var existItem = lstOriSub?.FirstOrDefault(t => CompareVmessItem(t, vmessItem, true));
if (existItem != null)
{
vmessItem = existItem;
}
vmessItem.subid = subid;
}
//groupId
vmessItem.groupId = groupId;
if (vmessItem.configType == EConfigType.Vmess)
{
if (AddServer(ref config, vmessItem, false) == 0)
{
countServers++;
}
}
else if (vmessItem.configType == EConfigType.Shadowsocks)
{
if (AddShadowsocksServer(ref config, vmessItem, false) == 0)
{
countServers++;
}
}
else if (vmessItem.configType == EConfigType.Socks)
{
if (AddSocksServer(ref config, vmessItem, false) == 0)
{
countServers++;
}
}
else if (vmessItem.configType == EConfigType.Trojan)
{
if (AddTrojanServer(ref config, vmessItem, false) == 0)
{
countServers++;
}
}
else if (vmessItem.configType == EConfigType.VLESS)
{
if (AddVlessServer(ref config, vmessItem, false) == 0)
{
countServers++;
}
}
}
ToJsonFile(config);
return countServers;
}
private static int AddBatchServers4Custom(ref Config config, string clipboardData, string subid, List<VmessItem> lstOriSub, string groupId)
{
if (Utils.IsNullOrEmpty(clipboardData))
{
return -1;
}
VmessItem vmessItem = new VmessItem();
//Is v2ray configuration
V2rayConfig v2rayConfig = Utils.FromJson<V2rayConfig>(clipboardData);
if (v2rayConfig != null
&& v2rayConfig.inbounds != null
&& v2rayConfig.inbounds.Count > 0
&& v2rayConfig.outbounds != null
&& v2rayConfig.outbounds.Count > 0)
{
var fileName = Utils.GetTempPath($"{Utils.GetGUID(false)}.json");
File.WriteAllText(fileName, clipboardData);
vmessItem.coreType = ECoreType.Xray;
vmessItem.address = fileName;
vmessItem.remarks = "v2ray_custom";
}
//Is Clash configuration
else if (clipboardData.IndexOf("port") >= 0
&& clipboardData.IndexOf("socks-port") >= 0
&& clipboardData.IndexOf("proxies") >= 0)
{
var fileName = Utils.GetTempPath($"{Utils.GetGUID(false)}.yaml");
File.WriteAllText(fileName, clipboardData);
vmessItem.coreType = ECoreType.clash;
vmessItem.address = fileName;
vmessItem.remarks = "clash_custom";
}
//Is Other configuration
else
{
var fileName = Utils.GetTempPath($"{Utils.GetGUID(false)}.txt");
File.WriteAllText(fileName, clipboardData);
vmessItem.address = fileName;
vmessItem.remarks = "other_custom";
}
if (!Utils.IsNullOrEmpty(subid))
{
RemoveServerViaSubid(ref config, subid);
}
if (lstOriSub != null && lstOriSub.Count == 1)
{
vmessItem.indexId = lstOriSub[0].indexId;
}
vmessItem.subid = subid;
vmessItem.groupId = groupId;
if (Utils.IsNullOrEmpty(vmessItem.address))
{
return -1;
}
if (AddCustomServer(ref config, vmessItem, true) == 0)
{
return 1;
}
else
{
return -1;
}
}
public static int AddBatchServers(ref Config config, string clipboardData, string subid, string groupId)
{
List<VmessItem> lstOriSub = null;
if (!Utils.IsNullOrEmpty(subid))
{
lstOriSub = config.vmess.Where(it => it.subid == subid).ToList();
}
int counter = AddBatchServers(ref config, clipboardData, subid, lstOriSub, groupId);
if (counter < 1)
{
counter = AddBatchServers(ref config, Utils.Base64Decode(clipboardData), subid, lstOriSub, groupId);
}
//maybe other sub
if (counter < 1)
{
counter = AddBatchServers4Custom(ref config, clipboardData, subid, lstOriSub, groupId);
}
return counter;
}
#endregion
#region Sub & Group
/// <summary>
/// add sub
/// </summary>
/// <param name="config"></param>
/// <param name="url"></param>
/// <returns></returns>
public static int AddSubItem(ref Config config, string url)
{
//already exists
if (config.subItem.FindIndex(e => e.url == url) >= 0)
{
return 0;
}
SubItem subItem = new SubItem
{
id = string.Empty,
remarks = "import sub",
url = url
};
config.subItem.Add(subItem);
return SaveSubItem(ref config);
}
/// <summary>
/// save sub
/// </summary>
/// <param name="config"></param>
/// <returns></returns>
public static int SaveSubItem(ref Config config)
{
if (config.subItem == null)
{
return -1;
}
foreach (SubItem item in config.subItem)
{
if (Utils.IsNullOrEmpty(item.id))
{
item.id = Utils.GetGUID(false);
}
}
ToJsonFile(config);
return 0;
}
/// <summary>
/// 移除服务器
/// </summary>
/// <param name="config"></param>
/// <param name="subid"></param>
/// <returns></returns>
public static int RemoveServerViaSubid(ref Config config, string subid)
{
if (Utils.IsNullOrEmpty(subid) || config.vmess.Count <= 0)
{
return -1;
}
for (int k = config.vmess.Count - 1; k >= 0; k--)
{
if (config.vmess[k].subid.Equals(subid))
{
RemoveVmessItem(config, k);
}
}
ToJsonFile(config);
return 0;
}
/// <summary> /// <summary>
/// save Group /// save Group
/// </summary> /// </summary>
@@ -999,6 +1129,18 @@ namespace v2rayN.Handler
ToJsonFile(config); ToJsonFile(config);
return 0; return 0;
} }
public static int MoveServerToGroup(Config config, List<VmessItem> indexs, string groupId)
{
foreach (var item in indexs)
{
item.groupId = groupId;
}
ToJsonFile(config);
return 0;
}
#endregion #endregion
#region UI #region UI
@@ -1017,6 +1159,8 @@ namespace v2rayN.Handler
{ {
config.uiItem.mainLvColWidth.Add(name, width); config.uiItem.mainLvColWidth.Add(name, width);
} }
ToJsonFile(config);
return 0; return 0;
} }
public static int GetformMainLvColWidth(ref Config config, string name, int width) public static int GetformMainLvColWidth(ref Config config, string name, int width)
@@ -1131,7 +1275,7 @@ namespace v2rayN.Handler
/// <param name="index"></param> /// <param name="index"></param>
/// <param name="eMove"></param> /// <param name="eMove"></param>
/// <returns></returns> /// <returns></returns>
public static int MoveRoutingRule(ref RoutingItem routingItem, int index, EMove eMove) public static int MoveRoutingRule(ref RoutingItem routingItem, int index, EMove eMove, int pos = -1)
{ {
int count = routingItem.rules.Count; int count = routingItem.rules.Count;
if (index < 0 || index > routingItem.rules.Count - 1) if (index < 0 || index > routingItem.rules.Count - 1)
@@ -1189,6 +1333,14 @@ namespace v2rayN.Handler
break; break;
} }
case EMove.Position:
{
var removeItem = routingItem.rules[index];
var item = Utils.DeepCopy(routingItem.rules[index]);
routingItem.rules.Insert(pos, item);
routingItem.rules.Remove(removeItem);
break;
}
} }
return 0; return 0;

View File

@@ -1,7 +1,9 @@
using System; using System;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Text;
using v2rayN.Base; using v2rayN.Base;
using v2rayN.Resx;
namespace v2rayN.Handler namespace v2rayN.Handler
{ {
@@ -38,7 +40,7 @@ namespace v2rayN.Handler
try try
{ {
Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().enableSecurityProtocolTls13); Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().enableSecurityProtocolTls13);
UpdateCompleted?.Invoke(this, new ResultEventArgs(false, UIRes.I18N("Downloading"))); UpdateCompleted?.Invoke(this, new ResultEventArgs(false, ResUI.Downloading));
progressPercentage = -1; progressPercentage = -1;
totalBytesToReceive = 0; totalBytesToReceive = 0;
@@ -139,6 +141,7 @@ namespace v2rayN.Handler
Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().enableSecurityProtocolTls13); Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().enableSecurityProtocolTls13);
WebClientEx ws = new WebClientEx(); WebClientEx ws = new WebClientEx();
ws.Encoding = Encoding.UTF8;
if (webProxy != null) if (webProxy != null)
{ {
ws.Proxy = webProxy; ws.Proxy = webProxy;
@@ -197,7 +200,7 @@ namespace v2rayN.Handler
Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().enableSecurityProtocolTls13); Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().enableSecurityProtocolTls13);
WebClientEx ws = new WebClientEx(); WebClientEx ws = new WebClientEx();
ws.Encoding = Encoding.UTF8;
return ws.DownloadString(new Uri(url)); return ws.DownloadString(new Uri(url));
} }
catch (Exception ex) catch (Exception ex)
@@ -213,7 +216,7 @@ namespace v2rayN.Handler
try try
{ {
Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().enableSecurityProtocolTls13); Utils.SetSecurityProtocol(LazyConfig.Instance.GetConfig().enableSecurityProtocolTls13);
UpdateCompleted?.Invoke(this, new ResultEventArgs(false, UIRes.I18N("Downloading"))); UpdateCompleted?.Invoke(this, new ResultEventArgs(false, ResUI.Downloading));
progressPercentage = -1; progressPercentage = -1;
totalBytesToReceive = 0; totalBytesToReceive = 0;

View File

@@ -1,5 +1,7 @@
using System; using System;
using System.Collections.Generic;
using v2rayN.Mode; using v2rayN.Mode;
using System.Linq;
namespace v2rayN.Handler namespace v2rayN.Handler
{ {
@@ -7,6 +9,7 @@ namespace v2rayN.Handler
{ {
private static readonly Lazy<LazyConfig> _instance = new Lazy<LazyConfig>(() => new LazyConfig()); private static readonly Lazy<LazyConfig> _instance = new Lazy<LazyConfig>(() => new LazyConfig());
private Config _config; private Config _config;
private List<CoreInfo> coreInfos;
public static LazyConfig Instance public static LazyConfig Instance
{ {
@@ -20,5 +23,82 @@ namespace v2rayN.Handler
{ {
return _config; return _config;
} }
public List<string> GetShadowsocksSecuritys()
{
if (GetCoreType(null, EConfigType.Shadowsocks) == ECoreType.v2fly)
{
return Global.ssSecuritys;
}
return Global.ssSecuritysInXray;
}
public ECoreType GetCoreType(VmessItem vmessItem, EConfigType eConfigType)
{
if (vmessItem != null && vmessItem.coreType != null)
{
return (ECoreType)vmessItem.coreType;
}
if (_config.coreTypeItem == null)
{
return ECoreType.Xray;
}
var item = _config.coreTypeItem.FirstOrDefault(it => it.configType == eConfigType);
if (item == null)
{
return ECoreType.Xray;
}
return item.coreType;
}
public CoreInfo GetCoreInfo(ECoreType coreType)
{
if (coreInfos == null)
{
InitCoreInfo();
}
return coreInfos.Where(t => t.coreType == coreType).FirstOrDefault();
}
private void InitCoreInfo()
{
coreInfos = new List<CoreInfo>();
coreInfos.Add(new CoreInfo
{
coreType = ECoreType.v2fly,
coreExes = new List<string> { "wv2ray", "v2ray" },
arguments = "",
coreUrl = Global.v2flyCoreUrl
});
coreInfos.Add(new CoreInfo
{
coreType = ECoreType.Xray,
coreExes = new List<string> { "xray" },
arguments = "",
coreUrl = Global.xrayCoreUrl
});
coreInfos.Add(new CoreInfo
{
coreType = ECoreType.clash,
coreExes = new List<string> { "clash-windows-amd64", "clash-windows-386", "clash" },
arguments = "-f config.json",
coreUrl = Global.clashCoreUrl
});
coreInfos.Add(new CoreInfo
{
coreType = ECoreType.hysteria,
coreExes = new List<string> { "hysteria-tun-windows-6.0-amd64", "hysteria-tun-windows-6.0-386", "hysteria" },
arguments = "",
coreUrl = Global.hysteriaCoreUrl
});
}
} }
} }

View File

@@ -9,6 +9,7 @@ using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
using v2rayN.Mode; using v2rayN.Mode;
using System.Linq; using System.Linq;
using v2rayN.Resx;
namespace v2rayN.Handler namespace v2rayN.Handler
{ {
@@ -53,7 +54,7 @@ namespace v2rayN.Handler
if (!Utils.IsNullOrEmpty(item.customIcon) && File.Exists(item.customIcon)) if (!Utils.IsNullOrEmpty(item.customIcon) && File.Exists(item.customIcon))
{ {
graphics.FillRectangle(drawBrush, new Rectangle(0, 0, width, height)); graphics.FillRectangle(drawBrush, new Rectangle(0, 0, width, height));
graphics.DrawImage(new Bitmap(item.customIcon), 0, 0); graphics.DrawImage(new Bitmap(item.customIcon), 0, 0, width, height);
customIcon = true; customIcon = true;
} }
} }
@@ -88,7 +89,7 @@ namespace v2rayN.Handler
if (item.configType != EConfigType.Vmess if (item.configType != EConfigType.Vmess
&& item.configType != EConfigType.VLESS) && item.configType != EConfigType.VLESS)
{ {
UI.Show(UIRes.I18N("NonVmessService")); UI.Show(ResUI.NonVmessService);
return; return;
} }
@@ -115,7 +116,7 @@ namespace v2rayN.Handler
} }
else else
{ {
UI.ShowWarning(string.Format(UIRes.I18N("SaveClientConfigurationIn"), fileName)); UI.ShowWarning(string.Format(ResUI.SaveClientConfigurationIn, fileName));
} }
} }
@@ -128,7 +129,7 @@ namespace v2rayN.Handler
if (item.configType != EConfigType.Vmess if (item.configType != EConfigType.Vmess
&& item.configType != EConfigType.VLESS) && item.configType != EConfigType.VLESS)
{ {
UI.Show(UIRes.I18N("NonVmessService")); UI.Show(ResUI.NonVmessService);
return; return;
} }
@@ -155,33 +156,16 @@ namespace v2rayN.Handler
} }
else else
{ {
UI.ShowWarning(string.Format(UIRes.I18N("SaveServerConfigurationIn"), fileName)); UI.ShowWarning(string.Format(ResUI.SaveServerConfigurationIn, fileName));
} }
} }
public int AddBatchServers(Config config, string clipboardData, string subid, string groupId)
{
List<VmessItem> lstOriSub = null;
if (!Utils.IsNullOrEmpty(subid))
{
lstOriSub = config.vmess.Where(it => it.subid == subid).ToList();
}
int counter = ConfigHandler.AddBatchServers(ref config, clipboardData, subid, lstOriSub, groupId);
if (counter < 1)
{
counter = ConfigHandler.AddBatchServers(ref config, Utils.Base64Decode(clipboardData), subid, lstOriSub, groupId);
}
return counter;
}
public void BackupGuiNConfig(Config config, bool auto = false) public void BackupGuiNConfig(Config config, bool auto = false)
{ {
string fileName = $"guiNConfig_{DateTime.Now.ToString("yyyy_MM_dd_HH_mm_ss_fff")}.json"; string fileName = $"guiNConfig_{DateTime.Now.ToString("yyyy_MM_dd_HH_mm_ss_fff")}.json";
if (auto) if (auto)
{ {
fileName = Utils.GetTempPath(fileName); fileName = Utils.GetBackupPath(fileName);
} }
else else
{ {
@@ -208,11 +192,11 @@ namespace v2rayN.Handler
if (ret == 0) if (ret == 0)
{ {
UI.Show(UIRes.I18N("OperationSuccess")); UI.Show(ResUI.OperationSuccess);
} }
else else
{ {
UI.ShowWarning(UIRes.I18N("OperationFailed")); UI.ShowWarning(ResUI.OperationFailed);
} }
} }
} }
@@ -285,12 +269,12 @@ namespace v2rayN.Handler
try try
{ {
HotkeyManager.Current.AddOrReplace(((int)item.eGlobalHotkey).ToString(), keys, handler); HotkeyManager.Current.AddOrReplace(((int)item.eGlobalHotkey).ToString(), keys, handler);
var msg = string.Format(UIRes.I18N("RegisterGlobalHotkeySuccessfully"), $"{item.eGlobalHotkey.ToString()} = {keys}"); var msg = string.Format(ResUI.RegisterGlobalHotkeySuccessfully, $"{item.eGlobalHotkey.ToString()} = {keys}");
update(false, msg); update(false, msg);
} }
catch (Exception ex) catch (Exception ex)
{ {
var msg = string.Format(UIRes.I18N("RegisterGlobalHotkeyFailed"), $"{item.eGlobalHotkey.ToString()} = {keys}", ex.Message); var msg = string.Format(ResUI.RegisterGlobalHotkeyFailed, $"{item.eGlobalHotkey.ToString()} = {keys}", ex.Message);
update(false, msg); update(false, msg);
Utils.SaveLog(msg); Utils.SaveLog(msg);
} }

View File

@@ -9,6 +9,7 @@ using System.Threading.Tasks;
using System.Web; using System.Web;
using v2rayN.Base; using v2rayN.Base;
using v2rayN.Mode; using v2rayN.Mode;
using v2rayN.Resx;
namespace v2rayN.Handler namespace v2rayN.Handler
{ {
@@ -318,7 +319,7 @@ namespace v2rayN.Handler
string result = clipboardData.TrimEx();// Utils.GetClipboardData(); string result = clipboardData.TrimEx();// Utils.GetClipboardData();
if (Utils.IsNullOrEmpty(result)) if (Utils.IsNullOrEmpty(result))
{ {
msg = UIRes.I18N("FailedReadConfiguration"); msg = ResUI.FailedReadConfiguration;
return null; return null;
} }
@@ -338,7 +339,7 @@ namespace v2rayN.Handler
} }
else if (result.StartsWith(Global.ssProtocol)) else if (result.StartsWith(Global.ssProtocol))
{ {
msg = UIRes.I18N("ConfigurationFormatIncorrect"); msg = ResUI.ConfigurationFormatIncorrect;
vmessItem = ResolveSSLegacy(result); vmessItem = ResolveSSLegacy(result);
if (vmessItem == null) if (vmessItem == null)
@@ -358,7 +359,7 @@ namespace v2rayN.Handler
} }
else if (result.StartsWith(Global.socksProtocol)) else if (result.StartsWith(Global.socksProtocol))
{ {
msg = UIRes.I18N("ConfigurationFormatIncorrect"); msg = ResUI.ConfigurationFormatIncorrect;
vmessItem = ResolveSocksNew(result); vmessItem = ResolveSocksNew(result);
if (vmessItem == null) if (vmessItem == null)
@@ -378,7 +379,7 @@ namespace v2rayN.Handler
} }
else if (result.StartsWith(Global.trojanProtocol)) else if (result.StartsWith(Global.trojanProtocol))
{ {
msg = UIRes.I18N("ConfigurationFormatIncorrect"); msg = ResUI.ConfigurationFormatIncorrect;
vmessItem = ResolveTrojan(result); vmessItem = ResolveTrojan(result);
} }
@@ -390,13 +391,13 @@ namespace v2rayN.Handler
} }
else else
{ {
msg = UIRes.I18N("NonvmessOrssProtocol"); msg = ResUI.NonvmessOrssProtocol;
return null; return null;
} }
} }
catch catch
{ {
msg = UIRes.I18N("Incorrectconfiguration"); msg = ResUI.Incorrectconfiguration;
return null; return null;
} }
@@ -416,7 +417,7 @@ namespace v2rayN.Handler
VmessQRCode vmessQRCode = Utils.FromJson<VmessQRCode>(result); VmessQRCode vmessQRCode = Utils.FromJson<VmessQRCode>(result);
if (vmessQRCode == null) if (vmessQRCode == null)
{ {
msg = UIRes.I18N("FailedConversionConfiguration"); msg = ResUI.FailedConversionConfiguration;
return null; return null;
} }
@@ -507,7 +508,7 @@ namespace v2rayN.Handler
i.address = u.IdnHost; i.address = u.IdnHost;
i.port = u.Port; i.port = u.Port;
i.remarks = Utils.UrlDecode(u.GetComponents(UriComponents.Fragment, UriFormat.Unescaped)); i.remarks = u.GetComponents(UriComponents.Fragment, UriFormat.Unescaped);
var q = HttpUtility.ParseQueryString(u.Query); var q = HttpUtility.ParseQueryString(u.Query);
var m = StdVmessUserInfo.Match(u.UserInfo); var m = StdVmessUserInfo.Match(u.UserInfo);
@@ -589,13 +590,13 @@ namespace v2rayN.Handler
} }
VmessItem server = new VmessItem VmessItem server = new VmessItem
{ {
remarks = Utils.UrlDecode(parsedUrl.GetComponents(UriComponents.Fragment, UriFormat.Unescaped)), remarks = parsedUrl.GetComponents(UriComponents.Fragment, UriFormat.Unescaped),
address = parsedUrl.IdnHost, address = parsedUrl.IdnHost,
port = parsedUrl.Port, port = parsedUrl.Port,
}; };
// parse base64 UserInfo // parse base64 UserInfo
string rawUserInfo = parsedUrl.GetComponents(UriComponents.UserInfo, UriFormat.Unescaped); string rawUserInfo = parsedUrl.GetComponents(UriComponents.UserInfo, UriFormat.UriEscaped);
string userInfo = Utils.Base64Decode(rawUserInfo); string userInfo = Utils.Base64Decode(rawUserInfo);
string[] userInfoParts = userInfo.Split(new char[] { ':' }, 2); string[] userInfoParts = userInfo.Split(new char[] { ':' }, 2);
if (userInfoParts.Length != 2) if (userInfoParts.Length != 2)
@@ -711,7 +712,7 @@ namespace v2rayN.Handler
} }
VmessItem server = new VmessItem VmessItem server = new VmessItem
{ {
remarks = Utils.UrlDecode(parsedUrl.GetComponents(UriComponents.Fragment, UriFormat.Unescaped)), remarks = parsedUrl.GetComponents(UriComponents.Fragment, UriFormat.Unescaped),
address = parsedUrl.IdnHost, address = parsedUrl.IdnHost,
port = parsedUrl.Port, port = parsedUrl.Port,
}; };
@@ -740,7 +741,7 @@ namespace v2rayN.Handler
item.address = url.IdnHost; item.address = url.IdnHost;
item.port = url.Port; item.port = url.Port;
item.remarks = Utils.UrlDecode(url.GetComponents(UriComponents.Fragment, UriFormat.Unescaped)); item.remarks = url.GetComponents(UriComponents.Fragment, UriFormat.Unescaped);
item.id = url.UserInfo; item.id = url.UserInfo;
var query = HttpUtility.ParseQueryString(url.Query); var query = HttpUtility.ParseQueryString(url.Query);
@@ -760,7 +761,7 @@ namespace v2rayN.Handler
item.address = url.IdnHost; item.address = url.IdnHost;
item.port = url.Port; item.port = url.Port;
item.remarks = Utils.UrlDecode(url.GetComponents(UriComponents.Fragment, UriFormat.Unescaped)); item.remarks = url.GetComponents(UriComponents.Fragment, UriFormat.Unescaped);
item.id = url.UserInfo; item.id = url.UserInfo;
var query = HttpUtility.ParseQueryString(url.Query); var query = HttpUtility.ParseQueryString(url.Query);

View File

@@ -6,6 +6,7 @@ using System.Net.Sockets;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using v2rayN.Mode; using v2rayN.Mode;
using v2rayN.Resx;
namespace v2rayN.Handler namespace v2rayN.Handler
{ {
@@ -21,7 +22,7 @@ namespace v2rayN.Handler
_config = config; _config = config;
} }
public SpeedtestHandler(ref Config config, ref V2rayHandler v2rayHandler, List<VmessItem> selecteds, string actionType, Action<string, string> update) public SpeedtestHandler(ref Config config, V2rayHandler v2rayHandler, List<VmessItem> selecteds, ESpeedActionType actionType, Action<string, string> update)
{ {
_config = config; _config = config;
_v2rayHandler = v2rayHandler; _v2rayHandler = v2rayHandler;
@@ -40,19 +41,19 @@ namespace v2rayN.Handler
}); });
} }
if (actionType == "ping") if (actionType == ESpeedActionType.Ping)
{ {
Task.Run(() => RunPing()); Task.Run(() => RunPing());
} }
if (actionType == "tcping") else if (actionType == ESpeedActionType.Tcping)
{ {
Task.Run(() => RunTcping()); Task.Run(() => RunTcping());
} }
else if (actionType == "realping") else if (actionType == ESpeedActionType.Realping)
{ {
Task.Run(() => RunRealPing()); Task.Run(() => RunRealPing());
} }
else if (actionType == "speedtest") else if (actionType == ESpeedActionType.Speedtest)
{ {
Task.Run(() => RunSpeedTest()); Task.Run(() => RunSpeedTest());
} }
@@ -117,7 +118,7 @@ namespace v2rayN.Handler
pid = _v2rayHandler.LoadV2rayConfigString(_config, _selecteds); pid = _v2rayHandler.LoadV2rayConfigString(_config, _selecteds);
if (pid < 0) if (pid < 0)
{ {
_updateFunc(_selecteds[0].indexId, UIRes.I18N("OperationFailed")); _updateFunc(_selecteds[0].indexId, ResUI.OperationFailed);
return; return;
} }
@@ -203,7 +204,7 @@ namespace v2rayN.Handler
pid = _v2rayHandler.LoadV2rayConfigString(_config, _selecteds); pid = _v2rayHandler.LoadV2rayConfigString(_config, _selecteds);
if (pid < 0) if (pid < 0)
{ {
_updateFunc(_selecteds[0].indexId, UIRes.I18N("OperationFailed")); _updateFunc(_selecteds[0].indexId, ResUI.OperationFailed);
return; return;
} }

View File

@@ -8,6 +8,7 @@ using System.Text.RegularExpressions;
using System.Windows.Forms; using System.Windows.Forms;
using v2rayN.Base; using v2rayN.Base;
using v2rayN.Mode; using v2rayN.Mode;
using v2rayN.Resx;
namespace v2rayN.Handler namespace v2rayN.Handler
{ {
@@ -53,7 +54,7 @@ namespace v2rayN.Handler
{ {
if (args.Success) if (args.Success)
{ {
_updateFunc(false, UIRes.I18N("MsgDownloadV2rayCoreSuccessfully")); _updateFunc(false, ResUI.MsgDownloadV2rayCoreSuccessfully);
try try
{ {
@@ -93,7 +94,7 @@ namespace v2rayN.Handler
{ {
if (args.Success) if (args.Success)
{ {
_updateFunc(false, string.Format(UIRes.I18N("MsgParsingSuccessfully"), "v2rayN")); _updateFunc(false, string.Format(ResUI.MsgParsingSuccessfully, "v2rayN"));
url = args.Msg; url = args.Msg;
askToDownload(downloadHandle, url, true); askToDownload(downloadHandle, url, true);
@@ -103,12 +104,12 @@ namespace v2rayN.Handler
_updateFunc(false, args.Msg); _updateFunc(false, args.Msg);
} }
}; };
_updateFunc(false, string.Format(UIRes.I18N("MsgStartUpdating"), "v2rayN")); _updateFunc(false, string.Format(ResUI.MsgStartUpdating, "v2rayN"));
CheckUpdateAsync("v2rayN"); CheckUpdateAsync(ECoreType.v2rayN);
} }
public void CheckUpdateCore(string type, Config config, Action<bool, string> update) public void CheckUpdateCore(ECoreType type, Config config, Action<bool, string> update)
{ {
_config = config; _config = config;
_updateFunc = update; _updateFunc = update;
@@ -122,8 +123,8 @@ namespace v2rayN.Handler
{ {
if (args.Success) if (args.Success)
{ {
_updateFunc(false, UIRes.I18N("MsgDownloadV2rayCoreSuccessfully")); _updateFunc(false, ResUI.MsgDownloadV2rayCoreSuccessfully);
_updateFunc(false, UIRes.I18N("MsgUnpacking")); _updateFunc(false, ResUI.MsgUnpacking);
try try
{ {
@@ -149,7 +150,7 @@ namespace v2rayN.Handler
{ {
if (args.Success) if (args.Success)
{ {
_updateFunc(false, string.Format(UIRes.I18N("MsgParsingSuccessfully"), "Core")); _updateFunc(false, string.Format(ResUI.MsgParsingSuccessfully, "Core"));
url = args.Msg; url = args.Msg;
askToDownload(downloadHandle, url, true); askToDownload(downloadHandle, url, true);
} }
@@ -158,7 +159,7 @@ namespace v2rayN.Handler
_updateFunc(false, args.Msg); _updateFunc(false, args.Msg);
} }
}; };
_updateFunc(false, string.Format(UIRes.I18N("MsgStartUpdating"), "Core")); _updateFunc(false, string.Format(ResUI.MsgStartUpdating, "Core"));
CheckUpdateAsync(type); CheckUpdateAsync(type);
} }
@@ -168,11 +169,11 @@ namespace v2rayN.Handler
_config = config; _config = config;
_updateFunc = update; _updateFunc = update;
_updateFunc(false, UIRes.I18N("MsgUpdateSubscriptionStart")); _updateFunc(false, ResUI.MsgUpdateSubscriptionStart);
if (config.subItem == null || config.subItem.Count <= 0) if (config.subItem == null || config.subItem.Count <= 0)
{ {
_updateFunc(false, UIRes.I18N("MsgNoValidSubscription")); _updateFunc(false, ResUI.MsgNoValidSubscription);
return; return;
} }
@@ -182,14 +183,14 @@ namespace v2rayN.Handler
string url = config.subItem[k - 1].url.TrimEx(); string url = config.subItem[k - 1].url.TrimEx();
string userAgent = config.subItem[k - 1].userAgent.TrimEx(); string userAgent = config.subItem[k - 1].userAgent.TrimEx();
string groupId = config.subItem[k - 1].groupId.TrimEx(); string groupId = config.subItem[k - 1].groupId.TrimEx();
string hashCode = $"{k}->"; string hashCode = $"{k}){config.subItem[k - 1].remarks}->";
if (config.subItem[k - 1].enabled == false) if (config.subItem[k - 1].enabled == false)
{ {
continue; continue;
} }
if (Utils.IsNullOrEmpty(id) || Utils.IsNullOrEmpty(url)) if (Utils.IsNullOrEmpty(id) || Utils.IsNullOrEmpty(url))
{ {
_updateFunc(false, $"{hashCode}{UIRes.I18N("MsgNoValidSubscription")}"); _updateFunc(false, $"{hashCode}{ResUI.MsgNoValidSubscription}");
continue; continue;
} }
@@ -198,28 +199,28 @@ namespace v2rayN.Handler
{ {
if (args.Success) if (args.Success)
{ {
_updateFunc(false, $"{hashCode}{UIRes.I18N("MsgGetSubscriptionSuccessfully")}"); _updateFunc(false, $"{hashCode}{ResUI.MsgGetSubscriptionSuccessfully}");
//string result = Utils.Base64Decode(args.Msg); //string result = Utils.Base64Decode(args.Msg);
string result = args.Msg; string result = args.Msg;
if (Utils.IsNullOrEmpty(result)) if (Utils.IsNullOrEmpty(result))
{ {
_updateFunc(false, $"{hashCode}{UIRes.I18N("MsgSubscriptionDecodingFailed")}"); _updateFunc(false, $"{hashCode}{ResUI.MsgSubscriptionDecodingFailed}");
return; return;
} }
//ConfigHandler.RemoveServerViaSubid(ref config, id); //ConfigHandler.RemoveServerViaSubid(ref config, id);
//_updateFunc(false, $"{hashCode}{UIRes.I18N("MsgClearSubscription")}"); //_updateFunc(false, $"{hashCode}{ResUI.MsgClearSubscription")}");
// RefreshServers(); // RefreshServers();
int ret = MainFormHandler.Instance.AddBatchServers(config, result, id, groupId); int ret = ConfigHandler.AddBatchServers(ref config, result, id, groupId);
if (ret > 0) if (ret > 0)
{ {
// RefreshServers(); // RefreshServers();
} }
else else
{ {
_updateFunc(false, $"{hashCode}{UIRes.I18N("MsgFailedImportSubscription")}"); _updateFunc(false, $"{hashCode}{ResUI.MsgFailedImportSubscription}");
} }
_updateFunc(true, $"{hashCode}{UIRes.I18N("MsgUpdateSubscriptionEnd")}"); _updateFunc(true, $"{hashCode}{ResUI.MsgUpdateSubscriptionEnd}");
} }
else else
{ {
@@ -234,7 +235,7 @@ namespace v2rayN.Handler
WebProxy webProxy = blProxy ? new WebProxy(Global.Loopback, _config.GetLocalPort(Global.InboundHttp)) : null; WebProxy webProxy = blProxy ? new WebProxy(Global.Loopback, _config.GetLocalPort(Global.InboundHttp)) : null;
downloadHandle3.WebDownloadString(url, webProxy, userAgent); downloadHandle3.WebDownloadString(url, webProxy, userAgent);
_updateFunc(false, $"{hashCode}{UIRes.I18N("MsgStartGettingSubscriptions")}"); _updateFunc(false, $"{hashCode}{ResUI.MsgStartGettingSubscriptions}");
} }
} }
@@ -255,7 +256,7 @@ namespace v2rayN.Handler
{ {
if (args.Success) if (args.Success)
{ {
_updateFunc(false, string.Format(UIRes.I18N("MsgDownloadGeoFileSuccessfully"), geoName)); _updateFunc(false, string.Format(ResUI.MsgDownloadGeoFileSuccessfully, geoName));
try try
{ {
@@ -292,7 +293,7 @@ namespace v2rayN.Handler
#region private #region private
private async void CheckUpdateAsync(string type) private async void CheckUpdateAsync(ECoreType type)
{ {
try try
{ {
@@ -310,15 +311,15 @@ namespace v2rayN.Handler
HttpClient httpClient = new HttpClient(webRequestHandler); HttpClient httpClient = new HttpClient(webRequestHandler);
string url; string url;
if (type == "v2fly") if (type == ECoreType.v2fly)
{ {
url = v2flyCoreLatestUrl; url = v2flyCoreLatestUrl;
} }
else if (type == "xray") else if (type == ECoreType.Xray)
{ {
url = xrayCoreLatestUrl; url = xrayCoreLatestUrl;
} }
else if (type == "v2rayN") else if (type == ECoreType.v2rayN)
{ {
url = nLatestUrl; url = nLatestUrl;
} }
@@ -347,18 +348,18 @@ namespace v2rayN.Handler
/// <summary> /// <summary>
/// 获取V2RayCore版本 /// 获取V2RayCore版本
/// </summary> /// </summary>
private string getCoreVersion(string type) private string getCoreVersion(ECoreType type)
{ {
try try
{ {
var core = string.Empty; var core = string.Empty;
var match = string.Empty; var match = string.Empty;
if (type == "v2fly") if (type == ECoreType.v2fly)
{ {
core = "v2ray.exe"; core = "v2ray.exe";
match = "V2Ray"; match = "V2Ray";
} }
else if (type == "xray") else if (type == ECoreType.Xray)
{ {
core = "xray.exe"; core = "xray.exe";
match = "Xray"; match = "Xray";
@@ -366,7 +367,7 @@ namespace v2rayN.Handler
string filePath = Utils.GetPath(core); string filePath = Utils.GetPath(core);
if (!File.Exists(filePath)) if (!File.Exists(filePath))
{ {
string msg = string.Format(UIRes.I18N("NotFoundCore"), @""); string msg = string.Format(ResUI.NotFoundCore, @"");
//ShowMsg(true, msg); //ShowMsg(true, msg);
return ""; return "";
} }
@@ -392,7 +393,7 @@ namespace v2rayN.Handler
return ""; return "";
} }
} }
private void responseHandler(string type, string redirectUrl) private void responseHandler(ECoreType type, string redirectUrl)
{ {
try try
{ {
@@ -401,24 +402,24 @@ namespace v2rayN.Handler
string curVersion; string curVersion;
string message; string message;
string url; string url;
if (type == "v2fly") if (type == ECoreType.v2fly)
{ {
curVersion = "v" + getCoreVersion(type); curVersion = "v" + getCoreVersion(type);
message = string.Format(UIRes.I18N("IsLatestCore"), curVersion); message = string.Format(ResUI.IsLatestCore, curVersion);
string osBit = Environment.Is64BitProcess ? "64" : "32"; string osBit = Environment.Is64BitProcess ? "64" : "32";
url = string.Format(v2flyCoreUrl, version, osBit); url = string.Format(v2flyCoreUrl, version, osBit);
} }
else if (type == "xray") else if (type == ECoreType.Xray)
{ {
curVersion = "v" + getCoreVersion(type); curVersion = "v" + getCoreVersion(type);
message = string.Format(UIRes.I18N("IsLatestCore"), curVersion); message = string.Format(ResUI.IsLatestCore, curVersion);
string osBit = Environment.Is64BitProcess ? "64" : "32"; string osBit = Environment.Is64BitProcess ? "64" : "32";
url = string.Format(xrayCoreUrl, version, osBit); url = string.Format(xrayCoreUrl, version, osBit);
} }
else if (type == "v2rayN") else if (type == ECoreType.v2rayN)
{ {
curVersion = FileVersionInfo.GetVersionInfo(Utils.GetExePath()).FileVersion.ToString(); curVersion = FileVersionInfo.GetVersionInfo(Utils.GetExePath()).FileVersion.ToString();
message = string.Format(UIRes.I18N("IsLatestN"), curVersion); message = string.Format(ResUI.IsLatestN, curVersion);
url = string.Format(nUrl, version); url = string.Format(nUrl, version);
} }
else else
@@ -446,7 +447,7 @@ namespace v2rayN.Handler
bool blDownload = false; bool blDownload = false;
if (blAsk) if (blAsk)
{ {
if (UI.ShowYesNo(string.Format(UIRes.I18N("DownloadYesNo"), url)) == DialogResult.Yes) if (UI.ShowYesNo(string.Format(ResUI.DownloadYesNo, url)) == DialogResult.Yes)
{ {
blDownload = true; blDownload = true;
} }

View File

@@ -6,6 +6,7 @@ using System.Net;
using System.Net.NetworkInformation; using System.Net.NetworkInformation;
using v2rayN.Base; using v2rayN.Base;
using v2rayN.Mode; using v2rayN.Mode;
using v2rayN.Resx;
namespace v2rayN.Handler namespace v2rayN.Handler
{ {
@@ -32,11 +33,11 @@ namespace v2rayN.Handler
{ {
if (node == null) if (node == null)
{ {
msg = UIRes.I18N("CheckServerSettings"); msg = ResUI.CheckServerSettings;
return -1; return -1;
} }
msg = UIRes.I18N("InitialConfiguration"); msg = ResUI.InitialConfiguration;
if (node.configType == EConfigType.Custom) if (node.configType == EConfigType.Custom)
{ {
return GenerateClientCustomConfig(node, fileName, out msg); return GenerateClientCustomConfig(node, fileName, out msg);
@@ -46,7 +47,7 @@ namespace v2rayN.Handler
string result = Utils.GetEmbedText(SampleClient); string result = Utils.GetEmbedText(SampleClient);
if (Utils.IsNullOrEmpty(result)) if (Utils.IsNullOrEmpty(result))
{ {
msg = UIRes.I18N("FailedGetDefaultConfiguration"); msg = ResUI.FailedGetDefaultConfiguration;
return -1; return -1;
} }
@@ -54,7 +55,7 @@ namespace v2rayN.Handler
V2rayConfig v2rayConfig = Utils.FromJson<V2rayConfig>(result); V2rayConfig v2rayConfig = Utils.FromJson<V2rayConfig>(result);
if (v2rayConfig == null) if (v2rayConfig == null)
{ {
msg = UIRes.I18N("FailedGenDefaultConfiguration"); msg = ResUI.FailedGenDefaultConfiguration;
return -1; return -1;
} }
@@ -80,11 +81,11 @@ namespace v2rayN.Handler
Utils.ToJsonFile(v2rayConfig, fileName, false); Utils.ToJsonFile(v2rayConfig, fileName, false);
msg = string.Format(UIRes.I18N("SuccessfulConfiguration"), $"[{config.GetGroupRemarks(node.groupId)}] {node.GetSummary()}"); msg = string.Format(ResUI.SuccessfulConfiguration, $"[{config.GetGroupRemarks(node.groupId)}] {node.GetSummary()}");
} }
catch catch
{ {
msg = UIRes.I18N("FailedGenDefaultConfiguration"); msg = ResUI.FailedGenDefaultConfiguration;
return -1; return -1;
} }
return 0; return 0;
@@ -168,6 +169,7 @@ namespace v2rayN.Handler
inbound2.protocol = Global.InboundHttp; inbound2.protocol = Global.InboundHttp;
inbound2.listen = inbound.listen; inbound2.listen = inbound.listen;
inbound2.settings.allowTransparent = false; inbound2.settings.allowTransparent = false;
inbound2.sniffing.enabled = inbound.sniffing.enabled;
} }
catch catch
{ {
@@ -400,7 +402,7 @@ namespace v2rayN.Handler
serversItem.address = node.address; serversItem.address = node.address;
serversItem.port = node.port; serversItem.port = node.port;
serversItem.password = node.id; serversItem.password = node.id;
if (config.GetShadowsocksSecuritys().Contains(node.security)) if (LazyConfig.Instance.GetShadowsocksSecuritys().Contains(node.security))
{ {
serversItem.method = node.security; serversItem.method = node.security;
} }
@@ -900,7 +902,7 @@ namespace v2rayN.Handler
//检查GUI设置 //检查GUI设置
if (node == null) if (node == null)
{ {
msg = UIRes.I18N("CheckServerSettings"); msg = ResUI.CheckServerSettings;
return -1; return -1;
} }
@@ -912,20 +914,43 @@ namespace v2rayN.Handler
string addressFileName = node.address; string addressFileName = node.address;
if (!File.Exists(addressFileName)) if (!File.Exists(addressFileName))
{ {
addressFileName = Path.Combine(Utils.GetTempPath(), addressFileName); addressFileName = Path.Combine(Utils.GetConfigPath(), addressFileName);
} }
if (!File.Exists(addressFileName)) if (!File.Exists(addressFileName))
{ {
msg = UIRes.I18N("FailedGenDefaultConfiguration"); msg = ResUI.FailedGenDefaultConfiguration;
return -1; return -1;
} }
File.Copy(addressFileName, fileName); File.Copy(addressFileName, fileName);
msg = string.Format(UIRes.I18N("SuccessfulConfiguration"), $"[{LazyConfig.Instance.GetConfig().GetGroupRemarks(node.groupId)}] {node.GetSummary()}"); //check again
} if (!File.Exists(fileName))
catch
{ {
msg = UIRes.I18N("FailedGenDefaultConfiguration"); msg = ResUI.FailedGenDefaultConfiguration;
return -1;
}
//overwrite port
var fileContent = File.ReadAllLines(fileName).ToList();
var coreType = LazyConfig.Instance.GetCoreType(node, node.configType);
switch (coreType)
{
case ECoreType.v2fly:
case ECoreType.Xray:
break;
case ECoreType.clash:
fileContent.Add($"port: {LazyConfig.Instance.GetConfig().GetLocalPort(Global.InboundHttp)}");
fileContent.Add($"socks-port: {LazyConfig.Instance.GetConfig().GetLocalPort(Global.InboundSocks)}");
break;
}
File.WriteAllLines(fileName, fileContent);
msg = string.Format(ResUI.SuccessfulConfiguration, $"[{LazyConfig.Instance.GetConfig().GetGroupRemarks(node.groupId)}] {node.GetSummary()}");
}
catch (Exception ex)
{
Utils.SaveLog("GenerateClientCustomConfig", ex);
msg = ResUI.FailedGenDefaultConfiguration;
return -1; return -1;
} }
return 0; return 0;
@@ -949,17 +974,17 @@ namespace v2rayN.Handler
//检查GUI设置 //检查GUI设置
if (node == null) if (node == null)
{ {
msg = UIRes.I18N("CheckServerSettings"); msg = ResUI.CheckServerSettings;
return -1; return -1;
} }
msg = UIRes.I18N("InitialConfiguration"); msg = ResUI.InitialConfiguration;
//取得默认配置 //取得默认配置
string result = Utils.GetEmbedText(SampleServer); string result = Utils.GetEmbedText(SampleServer);
if (Utils.IsNullOrEmpty(result)) if (Utils.IsNullOrEmpty(result))
{ {
msg = UIRes.I18N("FailedGetDefaultConfiguration"); msg = ResUI.FailedGetDefaultConfiguration;
return -1; return -1;
} }
@@ -967,7 +992,7 @@ namespace v2rayN.Handler
V2rayConfig v2rayConfig = Utils.FromJson<V2rayConfig>(result); V2rayConfig v2rayConfig = Utils.FromJson<V2rayConfig>(result);
if (v2rayConfig == null) if (v2rayConfig == null)
{ {
msg = UIRes.I18N("FailedGenDefaultConfiguration"); msg = ResUI.FailedGenDefaultConfiguration;
return -1; return -1;
} }
@@ -984,11 +1009,11 @@ namespace v2rayN.Handler
Utils.ToJsonFile(v2rayConfig, fileName, false); Utils.ToJsonFile(v2rayConfig, fileName, false);
msg = string.Format(UIRes.I18N("SuccessfulConfiguration"), node.GetSummary()); msg = string.Format(ResUI.SuccessfulConfiguration, node.GetSummary());
} }
catch catch
{ {
msg = UIRes.I18N("FailedGenDefaultConfiguration"); msg = ResUI.FailedGenDefaultConfiguration;
return -1; return -1;
} }
return 0; return 0;
@@ -1086,7 +1111,7 @@ namespace v2rayN.Handler
string result = Utils.LoadResource(fileName); string result = Utils.LoadResource(fileName);
if (Utils.IsNullOrEmpty(result)) if (Utils.IsNullOrEmpty(result))
{ {
msg = UIRes.I18N("FailedReadConfiguration"); msg = ResUI.FailedReadConfiguration;
return null; return null;
} }
@@ -1094,14 +1119,14 @@ namespace v2rayN.Handler
V2rayConfig v2rayConfig = Utils.FromJson<V2rayConfig>(result); V2rayConfig v2rayConfig = Utils.FromJson<V2rayConfig>(result);
if (v2rayConfig == null) if (v2rayConfig == null)
{ {
msg = UIRes.I18N("FailedConversionConfiguration"); msg = ResUI.FailedConversionConfiguration;
return null; return null;
} }
if (v2rayConfig.outbounds == null if (v2rayConfig.outbounds == null
|| v2rayConfig.outbounds.Count <= 0) || v2rayConfig.outbounds.Count <= 0)
{ {
msg = UIRes.I18N("IncorrectClientConfiguration"); msg = ResUI.IncorrectClientConfiguration;
return null; return null;
} }
@@ -1115,7 +1140,7 @@ namespace v2rayN.Handler
|| outbound.settings.vnext[0].users == null || outbound.settings.vnext[0].users == null
|| outbound.settings.vnext[0].users.Count <= 0) || outbound.settings.vnext[0].users.Count <= 0)
{ {
msg = UIRes.I18N("IncorrectClientConfiguration"); msg = ResUI.IncorrectClientConfiguration;
return null; return null;
} }
@@ -1208,7 +1233,7 @@ namespace v2rayN.Handler
} }
catch catch
{ {
msg = UIRes.I18N("IncorrectClientConfiguration"); msg = ResUI.IncorrectClientConfiguration;
return null; return null;
} }
@@ -1232,7 +1257,7 @@ namespace v2rayN.Handler
string result = Utils.LoadResource(fileName); string result = Utils.LoadResource(fileName);
if (Utils.IsNullOrEmpty(result)) if (Utils.IsNullOrEmpty(result))
{ {
msg = UIRes.I18N("FailedReadConfiguration"); msg = ResUI.FailedReadConfiguration;
return null; return null;
} }
@@ -1240,14 +1265,14 @@ namespace v2rayN.Handler
V2rayConfig v2rayConfig = Utils.FromJson<V2rayConfig>(result); V2rayConfig v2rayConfig = Utils.FromJson<V2rayConfig>(result);
if (v2rayConfig == null) if (v2rayConfig == null)
{ {
msg = UIRes.I18N("FailedConversionConfiguration"); msg = ResUI.FailedConversionConfiguration;
return null; return null;
} }
if (v2rayConfig.inbounds == null if (v2rayConfig.inbounds == null
|| v2rayConfig.inbounds.Count <= 0) || v2rayConfig.inbounds.Count <= 0)
{ {
msg = UIRes.I18N("IncorrectServerConfiguration"); msg = ResUI.IncorrectServerConfiguration;
return null; return null;
} }
@@ -1259,7 +1284,7 @@ namespace v2rayN.Handler
|| inbound.settings.clients == null || inbound.settings.clients == null
|| inbound.settings.clients.Count <= 0) || inbound.settings.clients.Count <= 0)
{ {
msg = UIRes.I18N("IncorrectServerConfiguration"); msg = ResUI.IncorrectServerConfiguration;
return null; return null;
} }
@@ -1353,7 +1378,7 @@ namespace v2rayN.Handler
} }
catch catch
{ {
msg = UIRes.I18N("IncorrectClientConfiguration"); msg = ResUI.IncorrectClientConfiguration;
return null; return null;
} }
return vmessItem; return vmessItem;
@@ -1394,25 +1419,25 @@ namespace v2rayN.Handler
{ {
if (config == null) if (config == null)
{ {
msg = UIRes.I18N("CheckServerSettings"); msg = ResUI.CheckServerSettings;
return ""; return "";
} }
msg = UIRes.I18N("InitialConfiguration"); msg = ResUI.InitialConfiguration;
Config configCopy = Utils.DeepCopy(config); Config configCopy = Utils.DeepCopy(config);
string result = Utils.GetEmbedText(SampleClient); string result = Utils.GetEmbedText(SampleClient);
if (Utils.IsNullOrEmpty(result)) if (Utils.IsNullOrEmpty(result))
{ {
msg = UIRes.I18N("FailedGetDefaultConfiguration"); msg = ResUI.FailedGetDefaultConfiguration;
return ""; return "";
} }
V2rayConfig v2rayConfig = Utils.FromJson<V2rayConfig>(result); V2rayConfig v2rayConfig = Utils.FromJson<V2rayConfig>(result);
if (v2rayConfig == null) if (v2rayConfig == null)
{ {
msg = UIRes.I18N("FailedGenDefaultConfiguration"); msg = ResUI.FailedGenDefaultConfiguration;
return ""; return "";
} }
List<IPEndPoint> lstIpEndPoints = null; List<IPEndPoint> lstIpEndPoints = null;
@@ -1493,12 +1518,12 @@ namespace v2rayN.Handler
v2rayConfig.routing.rules.Add(rule); v2rayConfig.routing.rules.Add(rule);
} }
//msg = string.Format(UIRes.I18N("SuccessfulConfiguration"), node.getSummary()); //msg = string.Format(ResUI.SuccessfulConfiguration"), node.getSummary());
return Utils.ToJson(v2rayConfig); return Utils.ToJson(v2rayConfig);
} }
catch catch
{ {
msg = UIRes.I18N("FailedGenDefaultConfiguration"); msg = ResUI.FailedGenDefaultConfiguration;
return ""; return "";
} }
} }

View File

@@ -4,6 +4,7 @@ using System.Diagnostics;
using System.IO; using System.IO;
using System.Text; using System.Text;
using v2rayN.Mode; using v2rayN.Mode;
using v2rayN.Resx;
namespace v2rayN.Handler namespace v2rayN.Handler
{ {
@@ -21,9 +22,7 @@ namespace v2rayN.Handler
class V2rayHandler class V2rayHandler
{ {
private static string v2rayConfigRes = Global.v2rayConfigFileName; private static string v2rayConfigRes = Global.v2rayConfigFileName;
private List<string> lstV2ray; private CoreInfo coreInfo;
private string coreUrl;
private string coreArguments;
public event ProcessDelegate ProcessEvent; public event ProcessDelegate ProcessEvent;
//private int processId = 0; //private int processId = 0;
private Process _process; private Process _process;
@@ -42,11 +41,15 @@ namespace v2rayN.Handler
var item = ConfigHandler.GetDefaultServer(ref config); var item = ConfigHandler.GetDefaultServer(ref config);
if (item == null) if (item == null)
{ {
ShowMsg(false, UIRes.I18N("CheckServerSettings")); ShowMsg(false, ResUI.CheckServerSettings);
return; return;
} }
SetCore(config, item); if (SetCore(config, item) != 0)
{
ShowMsg(false, ResUI.CheckServerSettings);
return;
}
string fileName = Utils.GetPath(v2rayConfigRes); string fileName = Utils.GetPath(v2rayConfigRes);
if (V2rayConfigHandler.GenerateClientConfig(item, fileName, false, out string msg) != 0) if (V2rayConfigHandler.GenerateClientConfig(item, fileName, false, out string msg) != 0)
{ {
@@ -106,7 +109,7 @@ namespace v2rayN.Handler
} }
else else
{ {
foreach (string vName in lstV2ray) foreach (string vName in coreInfo.coreExes)
{ {
Process[] existing = Process.GetProcessesByName(vName); Process[] existing = Process.GetProcessesByName(vName);
foreach (Process p in existing) foreach (Process p in existing)
@@ -163,12 +166,10 @@ namespace v2rayN.Handler
} }
} }
private string V2rayFindexe() private string V2rayFindexe(List<string> lstCoreTemp)
{ {
//查找v2ray文件是否存在
string fileName = string.Empty; string fileName = string.Empty;
//lstV2ray.Reverse(); foreach (string name in lstCoreTemp)
foreach (string name in lstV2ray)
{ {
string vName = string.Format("{0}.exe", name); string vName = string.Format("{0}.exe", name);
vName = Utils.GetPath(vName); vName = Utils.GetPath(vName);
@@ -180,7 +181,7 @@ namespace v2rayN.Handler
} }
if (Utils.IsNullOrEmpty(fileName)) if (Utils.IsNullOrEmpty(fileName))
{ {
string msg = string.Format(UIRes.I18N("NotFoundCore"), coreUrl); string msg = string.Format(ResUI.NotFoundCore, coreInfo.coreUrl);
ShowMsg(false, msg); ShowMsg(false, msg);
} }
return fileName; return fileName;
@@ -191,11 +192,11 @@ namespace v2rayN.Handler
/// </summary> /// </summary>
private void V2rayStart() private void V2rayStart()
{ {
ShowMsg(false, string.Format(UIRes.I18N("StartService"), DateTime.Now.ToString())); ShowMsg(false, string.Format(ResUI.StartService, DateTime.Now.ToString()));
try try
{ {
string fileName = V2rayFindexe(); string fileName = V2rayFindexe(coreInfo.coreExes);
if (fileName == "") return; if (fileName == "") return;
Process p = new Process Process p = new Process
@@ -203,7 +204,7 @@ namespace v2rayN.Handler
StartInfo = new ProcessStartInfo StartInfo = new ProcessStartInfo
{ {
FileName = fileName, FileName = fileName,
Arguments = coreArguments, Arguments = coreInfo.arguments,
WorkingDirectory = Utils.StartupPath(), WorkingDirectory = Utils.StartupPath(),
UseShellExecute = false, UseShellExecute = false,
RedirectStandardOutput = true, RedirectStandardOutput = true,
@@ -245,11 +246,11 @@ namespace v2rayN.Handler
/// </summary> /// </summary>
private int V2rayStartNew(string configStr) private int V2rayStartNew(string configStr)
{ {
ShowMsg(false, string.Format(UIRes.I18N("StartService"), DateTime.Now.ToString())); ShowMsg(false, string.Format(ResUI.StartService, DateTime.Now.ToString()));
try try
{ {
string fileName = V2rayFindexe(); string fileName = V2rayFindexe(new List<string> { "xray" });
if (fileName == "") return -1; if (fileName == "") return -1;
Process p = new Process Process p = new Process
@@ -326,48 +327,21 @@ namespace v2rayN.Handler
} }
} }
private void SetCore(Config config, VmessItem item) private int SetCore(Config config, VmessItem item)
{ {
if (item == null) if (item == null)
{ {
return; return -1;
}
var coreType = config.GetCoreType(item.configType);
if (item.coreType != null)
{
coreType = (ECoreType)item.coreType;
} }
var coreType = LazyConfig.Instance.GetCoreType(item, item.configType);
if (coreType == ECoreType.v2fly) coreInfo = LazyConfig.Instance.GetCoreInfo(coreType);
if (coreInfo == null)
{ {
lstV2ray = new List<string> return -1;
{
"wv2ray",
"v2ray"
};
coreUrl = Global.v2flyCoreUrl;
coreArguments = string.Empty;
}
else if (coreType == ECoreType.Xray)
{
lstV2ray = new List<string>
{
"xray"
};
coreUrl = Global.xrayCoreUrl;
coreArguments = string.Empty;
}
else if (coreType == ECoreType.clash)
{
lstV2ray = new List<string>
{
"clash-windows-amd64",
"clash-windows-386",
"clash"
};
coreUrl = Global.clashCoreUrl;
coreArguments = "-f config.json";
} }
return 0;
} }
} }
} }

View File

@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Windows.Forms; using System.Windows.Forms;
using v2rayN.Base; using v2rayN.Base;
using System.Linq; using System.Linq;
using System.Drawing;
namespace v2rayN.Mode namespace v2rayN.Mode
{ {
@@ -256,16 +256,6 @@ namespace v2rayN.Mode
return vmess.FirstOrDefault(it => it.indexId == id); return vmess.FirstOrDefault(it => it.indexId == id);
} }
public List<string> GetShadowsocksSecuritys()
{
if (GetCoreType(EConfigType.Shadowsocks) == ECoreType.v2fly)
{
return Global.ssSecuritys;
}
return Global.ssSecuritysInXray;
}
public bool IsActiveNode(VmessItem item) public bool IsActiveNode(VmessItem item)
{ {
if (!Utils.IsNullOrEmpty(item.indexId) && item.indexId == indexId) if (!Utils.IsNullOrEmpty(item.indexId) && item.indexId == indexId)
@@ -285,19 +275,6 @@ namespace v2rayN.Mode
return groupItem.Where(it => it.id == groupId).FirstOrDefault()?.remarks; return groupItem.Where(it => it.id == groupId).FirstOrDefault()?.remarks;
} }
public ECoreType GetCoreType(EConfigType eConfigType)
{
if (coreTypeItem == null)
{
return ECoreType.v2fly;
}
var item = coreTypeItem.FirstOrDefault(it => it.configType == eConfigType);
if (item == null)
{
return ECoreType.v2fly;
}
return item.coreType;
}
#endregion #endregion
} }
@@ -715,7 +692,9 @@ namespace v2rayN.Mode
get; set; get; set;
} }
public System.Drawing.Size mainSize public Point mainLocation { get; set; }
public Size mainSize
{ {
get; set; get; set;
} }

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
namespace v2rayN.Mode
{
[Serializable]
public class CoreInfo
{
public ECoreType coreType { get; set; }
public List<string> coreExes { get; set; }
public string arguments { get; set; }
public string coreUrl { get; set; }
}
}

View File

@@ -5,6 +5,8 @@ namespace v2rayN.Mode
{ {
v2fly = 1, v2fly = 1,
Xray = 2, Xray = 2,
clash = 3 clash = 11,
hysteria = 21,
v2rayN = 99
} }
} }

View File

@@ -6,6 +6,7 @@ namespace v2rayN.Mode
Top = 1, Top = 1,
Up = 2, Up = 2,
Down = 3, Down = 3,
Bottom = 4 Bottom = 4,
Position = 5
} }
} }

View File

@@ -0,0 +1,11 @@

namespace v2rayN.Mode
{
public enum ESpeedActionType
{
Ping,
Tcping,
Realping,
Speedtest
}
}

View File

@@ -32,4 +32,4 @@ using System.Runtime.InteropServices;
// 方法是按如下所示使用“*”: // 方法是按如下所示使用“*”:
//[assembly: AssemblyVersion("1.0.*")] //[assembly: AssemblyVersion("1.0.*")]
//[assembly: AssemblyVersion("1.0.0")] //[assembly: AssemblyVersion("1.0.0")]
[assembly: AssemblyFileVersion("5.4")] [assembly: AssemblyFileVersion("5.9")]

View File

@@ -115,7 +115,7 @@ namespace v2rayN.Resx {
} }
/// <summary> /// <summary>
/// 查找类似 Note that custom configuration relies entirely on your own configuration and does not work with all settings. The system agent is available when the socks port is equal to the port in the settings in the custom configuration inbound. 的本地化字符串。 /// 查找类似 Note that custom configuration relies entirely on your own configuration and does not work with all settings. If you want to use the system proxy, please modify the listening port manually. 的本地化字符串。
/// </summary> /// </summary>
internal static string CustomServerTips { internal static string CustomServerTips {
get { get {

View File

@@ -130,7 +130,7 @@
<value> configuration format is incorrect</value> <value> configuration format is incorrect</value>
</data> </data>
<data name="CustomServerTips" xml:space="preserve"> <data name="CustomServerTips" xml:space="preserve">
<value>Note that custom configuration relies entirely on your own configuration and does not work with all settings. The system agent is available when the socks port is equal to the port in the settings in the custom configuration inbound.</value> <value>Note that custom configuration relies entirely on your own configuration and does not work with all settings. If you want to use the system proxy, please modify the listening port manually.</value>
</data> </data>
<data name="Downloading" xml:space="preserve"> <data name="Downloading" xml:space="preserve">
<value>Downloading...</value> <value>Downloading...</value>

View File

@@ -130,7 +130,7 @@
<value>配置格式不正确</value> <value>配置格式不正确</value>
</data> </data>
<data name="CustomServerTips" xml:space="preserve"> <data name="CustomServerTips" xml:space="preserve">
<value>注意,自定义配置完全依赖您自己的配置,不能使用所有设置功能。在自定义配置inbound中有socks port等于设置中的port时系统代理才可用</value> <value>注意,自定义配置完全依赖您自己的配置,不能使用所有设置功能。如需使用系统代理请手工修改监听端口。</value>
</data> </data>
<data name="Downloading" xml:space="preserve"> <data name="Downloading" xml:space="preserve">
<value>下载开始...</value> <value>下载开始...</value>

View File

@@ -1,26 +0,0 @@
using System.Collections.Generic;
using System.Reflection;
using System.Resources;
namespace v2rayN
{
public class UIRes
{
static ResourceManager res = new ResourceManager("v2rayN.Resx.ResUI", Assembly.GetExecutingAssembly());
static string LoadString(ResourceManager resMgr, string key)
{
string value = resMgr.GetString(key);
if (value == null)
{
throw new KeyNotFoundException($"key: {key}");
}
return value;
}
public static string I18N(string key)
{
return LoadString(res, key);
}
}
}

View File

@@ -219,6 +219,26 @@ namespace v2rayN
} }
} }
/// <summary>
/// 逗号分隔的字符串,先排序后转List<string>
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static List<string> String2ListSorted(string str)
{
try
{
str = str.Replace(Environment.NewLine, "");
List<string> list = new List<string>(str.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries));
return list.OrderBy(x => x).ToList();
}
catch (Exception ex)
{
SaveLog(ex.Message, ex);
return new List<string>();
}
}
/// <summary> /// <summary>
/// Base64编码 /// Base64编码
/// </summary> /// </summary>
@@ -370,7 +390,8 @@ namespace v2rayN
public static string UrlEncode(string url) public static string UrlEncode(string url)
{ {
return HttpUtility.UrlEncode(url); return Uri.EscapeDataString(url);
//return HttpUtility.UrlEncode(url);
} }
public static string UrlDecode(string url) public static string UrlDecode(string url)
{ {
@@ -943,19 +964,21 @@ namespace v2rayN
#region TempPath #region TempPath
// return path to store temporary files // return path to store temporary files
public static string GetTempPath() public static string GetTempPath(string filename = "")
{ {
string _tempPath = Path.Combine(StartupPath(), "v2ray_win_temp"); string _tempPath = Path.Combine(StartupPath(), "v2ray_win_temp");
if (!Directory.Exists(_tempPath)) if (!Directory.Exists(_tempPath))
{ {
Directory.CreateDirectory(_tempPath); Directory.CreateDirectory(_tempPath);
} }
if (string.IsNullOrEmpty(filename))
{
return _tempPath; return _tempPath;
} }
else
public static string GetTempPath(string filename)
{ {
return Path.Combine(GetTempPath(), filename); return Path.Combine(_tempPath, filename);
}
} }
public static string UnGzip(byte[] buf) public static string UnGzip(byte[] buf)
@@ -970,6 +993,32 @@ namespace v2rayN
return Encoding.UTF8.GetString(sb.ToArray()); return Encoding.UTF8.GetString(sb.ToArray());
} }
public static string GetBackupPath(string filename)
{
string _tempPath = Path.Combine(StartupPath(), "guiBackups");
if (!Directory.Exists(_tempPath))
{
Directory.CreateDirectory(_tempPath);
}
return Path.Combine(_tempPath, filename);
}
public static string GetConfigPath(string filename = "")
{
string _tempPath = Path.Combine(StartupPath(), "guiConfigs");
if (!Directory.Exists(_tempPath))
{
Directory.CreateDirectory(_tempPath);
}
if (string.IsNullOrEmpty(filename))
{
return _tempPath;
}
else
{
return Path.Combine(_tempPath, filename);
}
}
#endregion #endregion
#region Log #region Log

View File

@@ -199,6 +199,7 @@
<SubType>Component</SubType> <SubType>Component</SubType>
</Compile> </Compile>
<Compile Include="Handler\SysProxyHandle.cs" /> <Compile Include="Handler\SysProxyHandle.cs" />
<Compile Include="Mode\ESpeedActionType.cs" />
<Compile Include="Mode\EGlobalHotkey.cs" /> <Compile Include="Mode\EGlobalHotkey.cs" />
<Compile Include="Mode\ECoreType.cs" /> <Compile Include="Mode\ECoreType.cs" />
<Compile Include="Mode\ESysProxyType.cs" /> <Compile Include="Mode\ESysProxyType.cs" />
@@ -207,6 +208,7 @@
<Compile Include="Mode\RoutingItem.cs" /> <Compile Include="Mode\RoutingItem.cs" />
<Compile Include="Mode\RulesItem.cs" /> <Compile Include="Mode\RulesItem.cs" />
<Compile Include="Mode\ServerStatistics.cs" /> <Compile Include="Mode\ServerStatistics.cs" />
<Compile Include="Mode\CoreInfo.cs" />
<Compile Include="Mode\SysproxyConfig.cs" /> <Compile Include="Mode\SysproxyConfig.cs" />
<Compile Include="Mode\EConfigType.cs" /> <Compile Include="Mode\EConfigType.cs" />
<Compile Include="Mode\ServerTestItem.cs" /> <Compile Include="Mode\ServerTestItem.cs" />
@@ -260,7 +262,6 @@
<Compile Include="Tool\Job.cs" /> <Compile Include="Tool\Job.cs" />
<Compile Include="Tool\Logging.cs" /> <Compile Include="Tool\Logging.cs" />
<Compile Include="Tool\QueryableExtension.cs" /> <Compile Include="Tool\QueryableExtension.cs" />
<Compile Include="Tool\UIRes.cs" />
<Compile Include="Tool\UI.cs" /> <Compile Include="Tool\UI.cs" />
<Compile Include="Tool\Utils.cs" /> <Compile Include="Tool\Utils.cs" />
<Compile Include="Handler\V2rayConfigHandler.cs" /> <Compile Include="Handler\V2rayConfigHandler.cs" />