public IEnumerable <Server> ParseSsdUri(string s) { var json = JsonConvert.DeserializeObject <Main>(ShareLink.URLSafeBase64Decode(s.Substring(6))); return(json.servers.Select(server => new Shadowsocks { Remark = server.remarks, Hostname = server.server, Port = server.port != 0 ? server.port : json.port, Password = server.password ?? json.password, EncryptMethod = server.encryption ?? json.encryption, Plugin = string.IsNullOrEmpty(json.plugin) ? string.IsNullOrEmpty(server.plugin) ? null : server.plugin : json.plugin, PluginOption = string.IsNullOrEmpty(json.plugin_options) ? string.IsNullOrEmpty(server.plugin_options) ? null : server.plugin_options : json.plugin_options }) .Where(CheckServer)); }
public IEnumerable <Server> ParseUri(string text) { var data = new VMess(); string s; try { s = ShareLink.URLSafeBase64Decode(text.Substring(8)); } catch { return(V2rayUtils.ParseVUri(text)); } V2rayNSharing vmess = JsonSerializer.Deserialize <V2rayNSharing>(s, new JsonSerializerOptions { NumberHandling = JsonNumberHandling.WriteAsString | JsonNumberHandling.AllowReadingFromString }) !; data.Remark = vmess.ps; data.Hostname = vmess.add; data.Port = vmess.port; data.UserID = vmess.id; data.AlterID = vmess.aid; data.TransferProtocol = vmess.net; data.FakeType = vmess.type; if (data.TransferProtocol == "quic") { if (VMessGlobal.QUIC.Contains(vmess.host !)) { data.QUICSecure = vmess.host; data.QUICSecret = vmess.path; } } else { data.Host = vmess.host; data.Path = vmess.path; } data.TLSSecureType = vmess.tls; data.EncryptMethod = "auto"; // V2Ray 加密方式不包括在链接中,主动添加一个 return(new[] { data }); }
public IEnumerable <Server> ParseUri(string text) { var data = new VMessServer(); string s; try { s = ShareLink.URLSafeBase64Decode(text.Substring(8)); } catch { return(V2rayUtils.ParseVUri(text)); } V2rayNJObject vmess = JsonSerializer.Deserialize <V2rayNJObject>(s, new JsonSerializerOptions { NumberHandling = JsonNumberHandling.WriteAsString | JsonNumberHandling.AllowReadingFromString }) !; data.Remark = vmess.ps; data.Hostname = vmess.add; data.EncryptMethod = vmess.scy; data.Port = vmess.port; data.UserID = vmess.id; data.AlterID = vmess.aid; data.TransferProtocol = vmess.net; data.FakeType = vmess.type; data.ServerName = vmess.sni; if (data.TransferProtocol == "quic") { data.QUICSecure = vmess.host; data.QUICSecret = vmess.path; } else { data.Host = vmess.host; data.Path = vmess.path; } data.TLSSecureType = vmess.tls; return(new[] { data }); }
public IEnumerable <Server> ParseUri(string text) { var data = new VMess(); text = text.Substring(8); V2rayNSharing vmess; try { vmess = JsonConvert.DeserializeObject <V2rayNSharing>(ShareLink.URLSafeBase64Decode(text)); } catch (Exception e) { Logging.Warning(e.ToString()); return(null); } data.Remark = vmess.ps; data.Hostname = vmess.add; data.Port = ushort.Parse(vmess.port); data.UserID = vmess.id; data.AlterID = int.Parse(vmess.aid); data.TransferProtocol = vmess.net; data.FakeType = vmess.type; if (data.TransferProtocol == "quic") { if (VMessGlobal.QUIC.Contains(vmess.host)) { data.QUICSecure = vmess.host; data.QUICSecret = vmess.path; } } else { data.Host = vmess.host; data.Path = vmess.path; } data.TLSSecure = vmess.tls == "tls"; data.EncryptMethod = "auto"; // V2Ray 加密方式不包括在链接中,主动添加一个 return(CheckServer(data) ? new[] { data } : null); }
public IEnumerable <Server> ParseUri(string text) { var data = new VMess(); V2rayNSharing vmess; try { vmess = JsonSerializer.Deserialize <V2rayNSharing>(ShareLink.URLSafeBase64Decode(text.Substring(8))); } catch { return(V2rayUtils.ParseVUri(text)); } data.Remark = vmess.ps; data.Hostname = vmess.add; data.Port = ushort.Parse(vmess.port); data.UserID = vmess.id; data.AlterID = int.Parse(vmess.aid); data.TransferProtocol = vmess.net; data.FakeType = vmess.type; if (data.TransferProtocol == "quic") { if (VMessGlobal.QUIC.Contains(vmess.host)) { data.QUICSecure = vmess.host; data.QUICSecret = vmess.path; } } else { data.Host = vmess.host; data.Path = vmess.path; } data.TLSSecureType = vmess.tls; data.EncryptMethod = "auto"; // V2Ray 加密方式不包括在链接中,主动添加一个 return(new[] { data }); }
public Shadowsocks ParseSsUri(string text) { var data = new Shadowsocks(); text = text.Replace("/?", "?"); if (text.Contains("#")) { data.Remark = HttpUtility.UrlDecode(text.Split('#')[1]); text = text.Split('#')[0]; } if (text.Contains("?")) { var finder = new Regex(@"^(?<data>.+?)\?(.+)$"); var match = finder.Match(text); if (!match.Success) { throw new FormatException(); } var plugins = HttpUtility.UrlDecode(HttpUtility.ParseQueryString(new Uri(text).Query).Get("plugin")); if (plugins != null) { var plugin = plugins.Substring(0, plugins.IndexOf(";", StringComparison.Ordinal)); var pluginopts = plugins.Substring(plugins.IndexOf(";", StringComparison.Ordinal) + 1); switch (plugin) { case "obfs-local": case "simple-obfs": plugin = "simple-obfs"; if (!pluginopts.Contains("obfs=")) { pluginopts = "obfs=http;obfs-host=" + pluginopts; } break; case "simple-obfs-tls": plugin = "simple-obfs"; if (!pluginopts.Contains("obfs=")) { pluginopts = "obfs=tls;obfs-host=" + pluginopts; } break; } data.Plugin = plugin; data.PluginOption = pluginopts; } text = match.Groups["data"].Value; } if (text.Contains("@")) { var finder = new Regex(@"^ss://(?<base64>.+?)@(?<server>.+):(?<port>\d+)"); var parser = new Regex(@"^(?<method>.+?):(?<password>.+)$"); var match = finder.Match(text); if (!match.Success) { throw new FormatException(); } data.Hostname = match.Groups["server"].Value; data.Port = ushort.Parse(match.Groups["port"].Value); var base64 = ShareLink.URLSafeBase64Decode(match.Groups["base64"].Value); match = parser.Match(base64); if (!match.Success) { throw new FormatException(); } data.EncryptMethod = match.Groups["method"].Value; data.Password = match.Groups["password"].Value; } else { var parser = new Regex(@"^((?<method>.+?):(?<password>.+)@(?<server>.+):(?<port>\d+))"); var match = parser.Match(ShareLink.URLSafeBase64Decode(text.Replace("ss://", ""))); if (!match.Success) { throw new FormatException(); } data.Hostname = match.Groups["server"].Value; data.Port = ushort.Parse(match.Groups["port"].Value); data.EncryptMethod = match.Groups["method"].Value; data.Password = match.Groups["password"].Value; } return(CheckServer(data) ? data : throw new FormatException()); }
private void UpdateServersFromSubscribeLinksToolStripMenuItem_Click(object sender, EventArgs e) { var bak_State = State; var bak_StateText = StatusLabel.Text; if (Global.Settings.UseProxyToUpdateSubscription && ServerComboBox.SelectedIndex == -1) { Global.Settings.UseProxyToUpdateSubscription = false; } if (Global.Settings.UseProxyToUpdateSubscription) { // 当前 ServerComboBox 中至少有一项 if (ServerComboBox.SelectedIndex == -1) { MessageBoxX.Show(i18N.Translate("Please select a server first")); return; } MenuStrip.Enabled = ConfigurationGroupBox.Enabled = ControlButton.Enabled = SettingsButton.Enabled = false; ControlButton.Text = "..."; } if (Global.Settings.SubscribeLink.Count > 0) { StatusText(i18N.Translate("Starting update subscription")); DeleteServerPictureBox.Enabled = false; UpdateServersFromSubscribeLinksToolStripMenuItem.Enabled = false; Task.Run(() => { if (Global.Settings.UseProxyToUpdateSubscription) { var mode = new Models.Mode { Remark = "ProxyUpdate", Type = 5 }; _mainController = new MainController(); _mainController.Start(ServerComboBox.SelectedItem as Models.Server, mode); } foreach (var item in Global.Settings.SubscribeLink) { using var client = new WebClient(); try { if (!string.IsNullOrEmpty(item.UserAgent)) { client.Headers.Add("User-Agent", item.UserAgent); } else { client.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36"); } if (Global.Settings.UseProxyToUpdateSubscription) { client.Proxy = new WebProxy($"http://127.0.0.1:{Global.Settings.HTTPLocalPort}"); } var response = client.DownloadString(item.Link); try { response = ShareLink.URLSafeBase64Decode(response); } catch (Exception) { // ignored } Global.Settings.Server = Global.Settings.Server.Where(server => server.Group != item.Remark).ToList(); var result = ShareLink.Parse(response); if (result != null) { foreach (var x in result) { x.Group = item.Remark; } Global.Settings.Server.AddRange(result); NotifyIcon.ShowBalloonTip(5, UpdateChecker.Name, string.Format(i18N.Translate("Update {1} server(s) from {0}"), item.Remark, result.Count), ToolTipIcon.Info); } else { NotifyIcon.ShowBalloonTip(5, UpdateChecker.Name, string.Format(i18N.Translate("Update servers error from {0}"), item.Remark), ToolTipIcon.Error); } } catch (Exception) { } } InitServer(); DeleteServerPictureBox.Enabled = true; if (Global.Settings.UseProxyToUpdateSubscription) { MenuStrip.Enabled = ConfigurationGroupBox.Enabled = ControlButton.Enabled = SettingsButton.Enabled = true; ControlButton.Text = i18N.Translate("Start"); _mainController.Stop(); NatTypeStatusLabel.Text = ""; } Configuration.Save(); StatusText(i18N.Translate("Subscription updated")); MenuStrip.Enabled = ConfigurationGroupBox.Enabled = ControlButton.Enabled = SettingsButton.Enabled = true; State = bak_State; StatusLabel.Text = bak_StateText; }).ContinueWith(task => { BeginInvoke(new Action(() => { UpdateServersFromSubscribeLinksToolStripMenuItem.Enabled = true; })); }); NotifyIcon.ShowBalloonTip(5, UpdateChecker.Name, i18N.Translate("Updating in the background"), ToolTipIcon.Info); } else { MessageBoxX.Show(i18N.Translate("No subscription link")); } }
public IEnumerable <Server> ParseUri(string text) { var data = new VMess(); text = text.Substring(8); var vmess = JsonConvert.DeserializeObject <VMessJObject>(ShareLink.URLSafeBase64Decode(text)); data.Remark = vmess.ps; data.Hostname = vmess.add; data.Port = vmess.port; data.UserID = vmess.id; data.AlterID = vmess.aid; data.TransferProtocol = vmess.net; data.FakeType = vmess.type; if (vmess.v == null || vmess.v == "1") { var info = vmess.host.Split(';'); if (info.Length == 2) { vmess.host = info[0]; vmess.path = info[1]; } } if (data.TransferProtocol == "quic") { if (VMessGlobal.QUIC.Contains(vmess.host)) { data.QUICSecure = vmess.host; data.QUICSecret = vmess.path; } } else { data.Host = vmess.host; data.Path = vmess.path; } data.TLSSecure = vmess.tls == "tls"; if (vmess.mux == null) { data.UseMux = false; } else { if (vmess.mux.enabled is bool enabled) { data.UseMux = enabled; } else if (vmess.mux.enabled is string muxEnabled) { data.UseMux = muxEnabled == "true"; // 针对使用字符串当作布尔值的情况 } else { data.UseMux = false; } } data.EncryptMethod = "auto"; // V2Ray 加密方式不包括在链接中,主动添加一个 return(CheckServer(data) ? new[] { data } : null); }
private async void UpdateServersFromSubscribeLinksToolStripMenuItem_Click(object sender, EventArgs e) { void DisableItems(bool v) { MenuStrip.Enabled = ConfigurationGroupBox.Enabled = ProfileGroupBox.Enabled = ControlButton.Enabled = v; } if (Global.Settings.UseProxyToUpdateSubscription && ServerComboBox.SelectedIndex == -1) { Global.Settings.UseProxyToUpdateSubscription = false; } if (Global.Settings.UseProxyToUpdateSubscription && ServerComboBox.SelectedIndex == -1) { MessageBoxX.Show(i18N.Translate("Please select a server first")); return; } if (Global.Settings.SubscribeLink.Count <= 0) { MessageBoxX.Show(i18N.Translate("No subscription link")); return; } StatusText(i18N.Translate("Starting update subscription")); DisableItems(false); try { if (Global.Settings.UseProxyToUpdateSubscription) { var mode = new Models.Mode { Remark = "ProxyUpdate", Type = 5 }; await MainController.Start(ServerComboBox.SelectedItem as Models.Server, mode); } var serverLock = new object(); await Task.WhenAll(Global.Settings.SubscribeLink.Select(async item => await Task.Run(async() => { try { var request = WebUtil.CreateRequest(item.Link); if (!string.IsNullOrEmpty(item.UserAgent)) { request.UserAgent = item.UserAgent; } if (Global.Settings.UseProxyToUpdateSubscription) { request.Proxy = new WebProxy($"http://127.0.0.1:{Global.Settings.HTTPLocalPort}"); } var str = await WebUtil.DownloadStringAsync(request); try { str = ShareLink.URLSafeBase64Decode(str); } catch { // ignored } lock (serverLock) { Global.Settings.Server.RemoveAll(server => server.Group == item.Remark); var result = ShareLink.Parse(str); if (result != null) { foreach (var server in result) { server.Group = item.Remark; Global.Settings.Server.Add(server); } } NotifyTip(i18N.TranslateFormat("Update {1} server(s) from {0}", item.Remark, result?.Count ?? 0)); } } catch (WebException e) { NotifyTip($"{i18N.TranslateFormat("Update servers error from {0}", item.Remark)}\n{e.Message}", info: false); } catch (Exception e) { Logging.Error(e.ToString()); } })).ToArray()); InitServer(); Configuration.Save(); StatusText(i18N.Translate("Subscription updated")); } catch (Exception) { // ignored } finally { if (Global.Settings.UseProxyToUpdateSubscription) { await MainController.Stop(); } DisableItems(true); } }
private void UpdateServersFromSubscribeLinksToolStripMenuItem_Click(object sender, EventArgs e) { if (Global.Settings.UseProxyToUpdateSubscription && ServerComboBox.SelectedIndex == -1) { Global.Settings.UseProxyToUpdateSubscription = false; } if (Global.Settings.UseProxyToUpdateSubscription && ServerComboBox.SelectedIndex == -1) { MessageBoxX.Show(i18N.Translate("Please select a server first")); return; } if (Global.Settings.SubscribeLink.Count > 0) { DeleteServerPictureBox.Enabled = false; UpdateServersFromSubscribeLinksToolStripMenuItem.Enabled = false; Task.Run(() => { if (Global.Settings.UseProxyToUpdateSubscription) { var mode = new Models.Mode { Remark = "ProxyUpdate", Type = 5 }; State = State.Starting; if (_mainController.Start(ServerComboBox.SelectedItem as Models.Server, mode)) { StatusText(i18N.Translate("Starting update subscription")); } } else { StatusText(i18N.Translate("Starting update subscription")); } Task.WaitAll(Global.Settings.SubscribeLink.Select(item => Task.Factory.StartNew(() => { try { var request = WebUtil.CreateRequest(item.Link); if (!string.IsNullOrEmpty(item.UserAgent)) { request.UserAgent = item.UserAgent; } if (Global.Settings.UseProxyToUpdateSubscription) { request.Proxy = new WebProxy($"http://127.0.0.1:{Global.Settings.HTTPLocalPort}"); } var str = WebUtil.DownloadString(request); try { str = ShareLink.URLSafeBase64Decode(str); } catch { // ignored } Global.Settings.Server = Global.Settings.Server.Where(server => server.Group != item.Remark).ToList(); var result = ShareLink.Parse(str); if (result != null) { foreach (var x in result) { x.Group = item.Remark; } Global.Settings.Server.AddRange(result); NotifyTip(i18N.TranslateFormat("Update {1} server(s) from {0}", item.Remark, result.Count)); } } catch (WebException e) { NotifyTip($"{i18N.TranslateFormat("Update servers error from {0}", item.Remark)}\n{e.Message}", info: false); } })).ToArray()); InitServer(); Configuration.Save(); NotifyTip(i18N.Translate("Subscription updated")); if (Global.Settings.UseProxyToUpdateSubscription) { _mainController.Stop(); State = State.Stopped; } State = State.Waiting; DeleteModePictureBox.Enabled = true; MenuStrip.Enabled = ConfigurationGroupBox.Enabled = ControlButton.Enabled = SettingsButton.Enabled = true; UpdateServersFromSubscribeLinksToolStripMenuItem.Enabled = true; }); NotifyTip(i18N.Translate("Updating in the background")); } else { MessageBoxX.Show(i18N.Translate("No subscription link")); } }
/// <summary> /// SSR链接解析器 /// Copy From /// https://github.com/HMBSbige/ShadowsocksR-Windows/blob/d9dc8d032a6e04c14b9dc6c8f673c9cc5aa9f607/shadowsocks-csharp/Model/Server.cs#L428 /// Thx :D /// </summary> /// <param name="text"></param> /// <returns></returns> public IEnumerable <Server> ParseUri(string text) { // ssr://host:port:protocol:method:obfs:base64pass/?obfsparam=base64&remarks=base64&group=base64&udpport=0&uot=1 var ssr = Regex.Match(text, "ssr://([A-Za-z0-9_-]+)", RegexOptions.IgnoreCase); if (!ssr.Success) { throw new FormatException(); } var data = ShareLink.URLSafeBase64Decode(ssr.Groups[1].Value); var paramsDict = new Dictionary <string, string>(); var paramStartPos = data.IndexOf("?", StringComparison.Ordinal); if (paramStartPos > 0) { paramsDict = ShareLink.ParseParam(data.Substring(paramStartPos + 1)); data = data.Substring(0, paramStartPos); } if (data.IndexOf("/", StringComparison.Ordinal) >= 0) { data = data.Substring(0, data.LastIndexOf("/", StringComparison.Ordinal)); } var urlFinder = new Regex("^(.+):([^:]+):([^:]*):([^:]+):([^:]*):([^:]+)"); var match = urlFinder.Match(data); if (match == null || !match.Success) { throw new FormatException(); } var serverAddr = match.Groups[1].Value; var serverPort = ushort.Parse(match.Groups[2].Value); var protocol = match.Groups[3].Value.Length == 0 ? "origin" : match.Groups[3].Value; protocol = protocol.Replace("_compatible", ""); var method = match.Groups[4].Value; var obfs = match.Groups[5].Value.Length == 0 ? "plain" : match.Groups[5].Value; obfs = obfs.Replace("_compatible", ""); var password = ShareLink.URLSafeBase64Decode(match.Groups[6].Value); var protocolParam = ""; var obfsParam = ""; var remarks = ""; if (paramsDict.ContainsKey("protoparam")) { protocolParam = ShareLink.URLSafeBase64Decode(paramsDict["protoparam"]); } if (paramsDict.ContainsKey("obfsparam")) { obfsParam = ShareLink.URLSafeBase64Decode(paramsDict["obfsparam"]); } if (paramsDict.ContainsKey("remarks")) { remarks = ShareLink.URLSafeBase64Decode(paramsDict["remarks"]); } var group = paramsDict.ContainsKey("group") ? ShareLink.URLSafeBase64Decode(paramsDict["group"]) : string.Empty; if (SSGlobal.EncryptMethods.Contains(method) && protocol == "origin" && obfs == "plain") { return new[] { new Shadowsocks.Shadowsocks { Hostname = serverAddr, Port = serverPort, EncryptMethod = method, Password = password, Remark = remarks, Group = group } } } ; return(new[] { new ShadowsocksR { Hostname = serverAddr, Port = serverPort, Protocol = protocol, EncryptMethod = method, OBFS = obfs, Password = password, ProtocolParam = protocolParam, OBFSParam = obfsParam, Remark = remarks, Group = group } }); }