├── torflow.csproj.user ├── Program.cs ├── torflow.sln ├── README.md ├── UNLICENSE ├── Properties └── AssemblyInfo.cs ├── torflow.csproj ├── Tests └── Test1.cs └── Lib └── TorFlow.cs /torflow.csproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ShowAllFiles 5 | 6 | -------------------------------------------------------------------------------- /Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Windows.Forms; 6 | 7 | namespace torflow 8 | { 9 | class Program 10 | { 11 | static void Main(string[] args) 12 | { 13 | new Tests1.TorFlow(args); 14 | Application.Run(); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /torflow.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31702.278 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "torflow", "torflow.csproj", "{1ACAF9A5-7254-4F0F-B346-55F435D1A64C}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {1ACAF9A5-7254-4F0F-B346-55F435D1A64C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {1ACAF9A5-7254-4F0F-B346-55F435D1A64C}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {1ACAF9A5-7254-4F0F-B346-55F435D1A64C}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {1ACAF9A5-7254-4F0F-B346-55F435D1A64C}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {A7AAA913-0E2E-4FAF-9CD7-9CF757889A99} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TorFlow (Updated: 13-Jan-2022) 2 | 3 | ## License 4 | Unlicense
5 | 6 | ### Requirements 7 | - Binary files of [TOR (Use official instead!)](https://github.com/SlowsieNT/TorFlow/releases/tag/resources) 8 | - .NET 3.5+ 9 | 10 | __Example__: 11 | ```cs 12 | TorProcess vTorProcess = new TorProcess { 13 | // (Both paths are full filenames) 14 | ExecutablePath = "etc/tor/tor.exe", 15 | TorrcFilePath = "etc/Config" 16 | }; 17 | // Once you call AddHiddenService, it will return HiddenService 18 | // HiddenService.AddPort will return HiddenService 19 | // Meaning you can call AddPort over and over again 20 | vTorProcess.Torrc.AddHiddenService("etc/website01").AddPort(11, 81).AddPort(24, 181); 21 | vTorProcess.Torrc.AddHiddenService("etc/website02").AddPort(80, 8080); 22 | // Handle events (optional, yes) 23 | vTorProcess.OnLine += TorProcess1_OnLine; 24 | vTorProcess.OnReady += TorProcess1_OnReady; 25 | vTorProcess.OnState += TorProcess1_OnState; 26 | // To get hostname of onion, best to use this: 27 | vTorProcess.OnHiddenServiceCreated += TorProcess1_OnHiddenServiceCreated; 28 | // Set data directory where the tor is supposed to write files 29 | vTorProcess.Torrc.DataDirectory = "etc/TorData"; 30 | // Run the Thread 31 | vTorProcess.Run(); 32 | ``` 33 | -------------------------------------------------------------------------------- /UNLICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("torflow")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("torflow")] 13 | [assembly: AssemblyCopyright("Copyright © 2021")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("1acaf9a5-7254-4f0f-b346-55f435d1a64c")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /torflow.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {1ACAF9A5-7254-4F0F-B346-55F435D1A64C} 8 | Exe 9 | torflow 10 | torflow 11 | v3.5 12 | 512 13 | true 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /Tests/Test1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Text.RegularExpressions; 6 | using System.Linq; 7 | using System.Threading; 8 | using System.Windows.Forms; 9 | using TorFlow; 10 | 11 | namespace Tests1 { 12 | public class TorFlow { 13 | public TorFlow(string[] aArgs) { 14 | // NOTE: You don't need to kill tor, 15 | // is usually independent tor instance. 16 | // Feel free to remove this line: 17 | Process.Start("tskill", "tor /a").WaitForExit(); 18 | SampleRun1(); 19 | } 20 | void SampleRun1() { 21 | // Very simple instancing 22 | TorProcess vTorProcess = new TorProcess { 23 | // (Both paths are full filenames) 24 | ExecutablePath = "etc/tor/tor.exe", 25 | TorrcFilePath = "etc/Config" 26 | }; 27 | // Once you call AddHiddenService, it will return HiddenService 28 | // HiddenService.AddPort will return HiddenService 29 | // Meaning you can call AddPort over and over again 30 | vTorProcess.Torrc.AddHiddenService("etc/website01").AddPort(11, 81).AddPort(24, 181); 31 | vTorProcess.Torrc.AddHiddenService("etc/website02").AddPort(80, 8080); 32 | // Handle events 33 | vTorProcess.OnLine += TorProcess1_OnLine; 34 | vTorProcess.OnReady += TorProcess1_OnReady; 35 | vTorProcess.OnState += TorProcess1_OnState; 36 | vTorProcess.OnHiddenServiceCreated += VTorProcess_OnHiddenServiceCreated; 37 | // Set data directory where the tor is supposed to write files 38 | vTorProcess.Torrc.DataDirectory = "etc/TorData"; 39 | // Run the Thread 40 | vTorProcess.Run(); 41 | } 42 | 43 | private void VTorProcess_OnHiddenServiceCreated(TorProcess aTorProc, TorProcess.HiddenService aValue) { 44 | Console.WriteLine(aValue.Hostname.Trim() + ":" + aValue.ToString(1)); 45 | } 46 | 47 | private void TorProcess1_OnState(TorProcess aTorProc, int aValue) { 48 | Console.Title = TorProcess.GetStateAsText(aValue); 49 | } 50 | 51 | private void TorProcess1_OnReady(TorProcess aTorProc) { 52 | //Console.Clear(); 53 | Console.Title = "ONIONs served!!!"; 54 | // KILL THE TOR ASAP 55 | aTorProc.Kill(); 56 | } 57 | 58 | private void TorProcess1_OnLine(TorProcess aTorProc, string aValue) { 59 | Console.WriteLine(aValue); 60 | } 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /Lib/TorFlow.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Text.RegularExpressions; 8 | using System.Threading; 9 | 10 | namespace TorFlow { 11 | 12 | /// Most events are background threads, remember: use try-catch. 13 | public class TorProcess { 14 | static string[] m_psStates = "Error,Starting,Running,Ready,Exited,Restarting".Split(','); 15 | public static string GetStateAsText(int aState) { 16 | return m_psStates[aState]; 17 | } 18 | /// Return state, use int/null to avoid errors. 19 | ///
null returns current state as text.
20 | public string this[object aState] { 21 | get { 22 | if (null == aState) 23 | return m_psStates[State]; 24 | // Disable out of bounds 25 | if (m_psStates.Length > (ushort)aState) 26 | return m_psStates[(int)aState]; 27 | return this[null]; 28 | } 29 | } 30 | public delegate void TorDelegateDef(TorProcess aTorProc); 31 | public delegate void TorDelegateInt(TorProcess aTorProc, int aValue); 32 | public delegate void TorDelegateString(TorProcess aTorProc, string aValue); 33 | public delegate void TorDelegateEx(TorProcess aTorProc, object aValue, int aDataType); 34 | public delegate void TorDelegateHS(TorProcess aTorProc, HiddenService aValue); 35 | public delegate void TorDelegateIntArray(TorProcess aTorProc, int[] aValue); 36 | /// Called when tor finishes bootstrapping. 37 | public event TorDelegateDef OnReady; 38 | public event TorDelegateDef OnClose; 39 | public event TorDelegateDef OnRestarting; 40 | public event TorDelegateInt OnState; 41 | public event TorDelegateHS OnHiddenServiceCreated; 42 | /// Silence is golden. 43 | public event TorDelegateEx OnError; 44 | /// This event is not background thread. 45 | ///
Useful when more ports are needed.
46 | public event TorDelegateIntArray OnTorrcPreparedPorts; 47 | /// Called every ReadLine of tor output 48 | public event TorDelegateString OnLine; 49 | /// On Bootstrapping 50 | public event TorDelegateInt OnRapping; 51 | /// Process ID 52 | public int Id; 53 | /// Used if tor is not intended to be terminated at all 54 | public bool Persist = true; 55 | /// Doesn't work for hidden service class 56 | public bool MakeDirs = true; 57 | /// Full File path to tor executable 58 | public string ExecutablePath = "dir/tor.exe"; 59 | /// Full File path to torrc 60 | public string TorrcFilePath = "dir/torrc"; 61 | /// States: 62 | /// 0 Error, 1 BeforeStart, 2 Running, 63 | /// 3 Ready, 4 Exited, 5 Restarting 64 | /// 65 | public int State; 66 | /// Time to wait [ms] before reinitiating tor process. 67 | public int RestartDelay = 1025; 68 | public TorConfig Torrc; 69 | public Process m_Process; 70 | public TorProcess() { 71 | Torrc = new TorConfig(this); 72 | } 73 | /// Run the background Thread. 74 | public void Run() { 75 | ThreadPool.QueueUserWorkItem(UserWorkItemRun); 76 | } 77 | /// Terminate Process, will reinitiate if abPersist is false. 78 | public void Kill(bool abPersist=false) { 79 | Persist = abPersist; 80 | m_Process.Kill(); 81 | } 82 | void FakeAsync(WaitCallback aAction) { 83 | ThreadPool.QueueUserWorkItem(aAction); 84 | } 85 | void InvokeOnHiddenServiceCreated(HiddenService aHiddenService) { 86 | FakeAsync(delegate (object aState) { 87 | OnHiddenServiceCreated?.Invoke(this, aHiddenService); 88 | }); 89 | } 90 | void InvokeOnError(object aValue, int aDataType) { 91 | FakeAsync(delegate (object aState) { 92 | OnError?.Invoke(this, aValue, aDataType); 93 | }); 94 | } 95 | void InvokeOnState(int aValue) { 96 | FakeAsync(delegate (object aState) { 97 | OnState?.Invoke(this, aValue); 98 | }); 99 | } 100 | void InvokeOnRapping(int aValue) { 101 | FakeAsync(delegate (object aState) { 102 | OnRapping?.Invoke(this, aValue); 103 | }); 104 | } 105 | void InvokeOnReady() { 106 | FakeAsync(delegate (object aState) { 107 | OnReady?.Invoke(this); 108 | }); 109 | } 110 | void InvokeOnLine(string aValue) { 111 | FakeAsync(delegate (object aState) { 112 | OnLine?.Invoke(this, aValue); 113 | }); 114 | } 115 | private void InvokeOnClose() { 116 | FakeAsync(delegate (object aState) { 117 | OnClose?.Invoke(this); 118 | }); 119 | } 120 | private void InvokeOnRestarting() { 121 | FakeAsync(delegate (object aState) { 122 | OnRestarting?.Invoke(this); 123 | }); 124 | } 125 | void UserWorkItemRun(object aState) { 126 | // Make sure all possible dirs are made 127 | if (MakeDirs) { 128 | IOUtils.MakeDirAll(IOUtils.ToDirs(TorrcFilePath)); 129 | IOUtils.MakeDirAll(Torrc.DataDirectory); 130 | } 131 | // Attempt to write torrc file 132 | IOUtils.WriteAllText(TorrcFilePath, "" + Torrc); 133 | // Check if all paths exist 134 | if (!File.Exists(TorrcFilePath)) 135 | InvokeOnError(TorrcFilePath + "\r\n", 0); 136 | if (!File.Exists(ExecutablePath)) 137 | InvokeOnError(ExecutablePath + "\r\n", 0); 138 | if (!Directory.Exists(Torrc.DataDirectory)) 139 | InvokeOnError(Torrc.DataDirectory + "\r\n", 0); 140 | m_Process = new Process { 141 | StartInfo = new ProcessStartInfo { 142 | FileName = ExecutablePath, 143 | Arguments = "-f " + '"' + TorrcFilePath + '"', 144 | UseShellExecute = false, 145 | RedirectStandardOutput = true, 146 | CreateNoWindow = true 147 | } 148 | }; 149 | InvokeOnState(State = 1); 150 | try { 151 | m_Process.Start(); 152 | Id = m_Process.Id; 153 | } catch (Exception vEx) { 154 | InvokeOnState(State = 0); 155 | InvokeOnError(vEx, 1); 156 | return; 157 | } 158 | // Report that TOR is alive and running 159 | InvokeOnState(State = 2); 160 | // While running, and console output incoming... 161 | while (!m_Process.StandardOutput.EndOfStream) { 162 | // Read console output line by line 163 | string vLine = m_Process.StandardOutput.ReadLine(); 164 | // Report each line to OnLine event 165 | InvokeOnLine(vLine); 166 | // TOR enjoys rap 167 | if (vLine.Contains("rapped ")) { 168 | // Get % of how much it rapped 169 | string vStrInt = Regex.Split(vLine, "rapped ")[1].Split('%')[0]; 170 | // Parse % and pass to event OnRapping 171 | InvokeOnRapping(int.Parse(vStrInt)); 172 | // If TOR rapped enough, report READY 173 | if ("100" == vStrInt) { 174 | InvokeOnState(State = 3); 175 | InvokeOnReady(); 176 | } 177 | } 178 | } 179 | // Report its refusal to rap 180 | InvokeOnState(State = 4); 181 | InvokeOnClose(); 182 | // Run tor again if escalated 183 | if (Persist) { 184 | Thread.Sleep(RestartDelay); 185 | InvokeOnState(State = 5); 186 | InvokeOnRestarting(); 187 | UserWorkItemRun(aState); 188 | } 189 | } 190 | 191 | public class TorConfig { 192 | TorProcess m_TProc; 193 | public TorConfig(TorProcess aTorProc) { 194 | m_TProc = aTorProc; 195 | ThreadPool.QueueUserWorkItem(UserWorkItemListenHostnames); 196 | } 197 | public int PreparePortCount = 0; 198 | public int[] PreparedPorts; 199 | void UserWorkItemListenHostnames(object state) { 200 | while (true) { 201 | for (int vI = 0; vI < TorHiddenServices.Count; vI++) { 202 | var vHS = TorHiddenServices[vI]; 203 | if (vHS != null && default == vHS.Hostname) { 204 | var vFileName = vHS.Directory + "/hostname"; 205 | // Attempt to read hostname. 206 | vHS.Hostname = IOUtils.ReadAllText(vFileName); 207 | if (default != vHS.Hostname) 208 | m_TProc.InvokeOnHiddenServiceCreated(vHS); 209 | } 210 | } 211 | Thread.Sleep(1000/50); // 50 Op/s 212 | } 213 | } 214 | public void PreparePorts() { 215 | List vPorts = new List(new int[] { TcpUtils.GetOpenPort() }); 216 | for (int vI = 0; vI < PreparePortCount; vI++) 217 | vPorts.Add(TcpUtils.GetOpenPort(1 + vPorts[vI])); 218 | PreparedPorts = vPorts.ToArray(); 219 | } 220 | public override string ToString() { 221 | if (null == PreparedPorts) { 222 | PreparePorts(); 223 | m_TProc.OnTorrcPreparedPorts?.Invoke(m_TProc, PreparedPorts); 224 | } 225 | if (0 == PreparedPorts.Length) { 226 | PreparePorts(); 227 | m_TProc.OnTorrcPreparedPorts?.Invoke(m_TProc, PreparedPorts); 228 | } 229 | string vOutput = ""; 230 | if ("auto" == SocksPort) 231 | SocksPort = "" + PreparedPorts[0]; 232 | if (AvoidDiskWrites) vOutput += "AvoidDiskWrites 1" + "\r\n"; 233 | // GeoIP checks before alloc 234 | if (File.Exists(GeoIPFile)) vOutput += "GeoIPFile " + GeoIPFile + "\r\n"; 235 | if (File.Exists(GeoIPv6File)) vOutput += "GeoIPv6File " + GeoIPv6File + "\r\n"; 236 | // DataDirectory before alloc 237 | if (m_TProc.MakeDirs) 238 | IOUtils.MakeDirAll(DataDirectory); 239 | if (Directory.Exists(DataDirectory)) 240 | vOutput += "DataDirectory " + DataDirectory + "\r\n"; 241 | vOutput += "ControlPort " + ControlPort + " " + ControlPortFlags + "\r\n"; 242 | vOutput += "SocksPort " + SocksPort + " " + SocksPortFlags + "\r\n"; 243 | foreach (HiddenService vHS in TorHiddenServices) { 244 | vOutput += "HiddenServiceDir " + vHS.Directory + "\r\n"; 245 | foreach (HiddenServicePort vPort in vHS.Ports) 246 | vOutput += "HiddenServicePort " + vPort.OnionPort + " " + vPort.ServerPort + "\r\n"; 247 | } 248 | return vOutput; 249 | } 250 | public bool AvoidDiskWrites = true; // default=0 251 | /// If not found, will attempt to create automatically. 252 | public string DataDirectory; 253 | public string ControlPort = "auto"; 254 | public string ControlPortFlags = ""; 255 | public string SocksPort = "auto"; 256 | public string SocksPortFlags = "IPv6Traffic PreferIPv6"; 257 | public string GeoIPFile, GeoIPv6File; 258 | public List CustomLines = new List(); 259 | public List TorHiddenServices = new List(); 260 | public bool RemoveCustomAt(int aIndex) { 261 | if (CustomLines.Count > aIndex) { 262 | CustomLines.RemoveAt(aIndex); 263 | return true; 264 | } 265 | return false; 266 | } 267 | public int AddCustom(string aValue, string aValue2) { 268 | return AddCustom(aValue + " " + aValue2); 269 | } 270 | public int AddCustom(string aValue) { 271 | CustomLines.Add(aValue); 272 | return CustomLines.Count - 1; 273 | } 274 | /// 275 | /// Used if hosting onion service, no port forwarding required. 276 | /// 277 | /// If not found, will attempt to create automatically. 278 | /// HiddenService always. 279 | public HiddenService AddHiddenService(string aDirectory) { 280 | HiddenService vHS = new HiddenService(aDirectory); 281 | TorHiddenServices.Add(vHS); 282 | return vHS; 283 | } 284 | } 285 | /// No port forwarding required. 286 | public class HiddenServicePort { 287 | public int OnionPort = 80, ServerPort = 8080; 288 | public string ServerHost = ""; 289 | public HiddenServicePort(int aOnionPort, int aServerPort, string aServerHost) { OnionPort = aOnionPort; ServerPort = aServerPort; ServerHost = aServerHost; } 290 | public HiddenServicePort(int aOnionPort, int aServerPort) { OnionPort = aOnionPort; ServerPort = aServerPort; } 291 | public HiddenServicePort(int aServerPort) { ServerPort = aServerPort; } 292 | public HiddenServicePort() { } 293 | public override string ToString() { 294 | string vStr = ServerHost; 295 | if (0 < vStr.Length) 296 | vStr += ":"; 297 | return OnionPort + " " + vStr + ServerPort; 298 | } 299 | } 300 | public class HiddenService { 301 | public string Directory; 302 | /// Hostname is readonly 303 | public string Hostname; 304 | public List Ports = new List(); 305 | public HiddenService(string aDir) { 306 | Directory = aDir; 307 | IOUtils.MakeDirAll(aDir); 308 | } 309 | public HiddenService AddPort(int vOnionPort, int vServerPort) { 310 | Ports.Add(new HiddenServicePort(vOnionPort, vServerPort)); 311 | return this; 312 | } 313 | /// ToString(1) will return onion ports separated by comma 314 | public string ToString(int aWhat) { 315 | if (1 == aWhat) { 316 | string vOut = ""; 317 | for (int vI = 0; vI < Ports.Count; vI++) 318 | vOut += Ports[vI].OnionPort + ", "; 319 | // Remove trailing comma 320 | if (vOut.Length > 3) 321 | return vOut.Substring(0, vOut.Length - 2); 322 | } 323 | return ToString(); 324 | } 325 | public override string ToString() { 326 | string vOutput = "HiddenServiceDir " + Directory + "\r\n"; 327 | for (int vI = 0, vL = Ports.Count; vI < vL; vI++) { 328 | vOutput += "HiddenServicePort " + Ports[vI]; 329 | if (vI + 1 < vL) vOutput += "\r\n"; 330 | } 331 | return vOutput; 332 | } 333 | } 334 | 335 | } 336 | public class IOUtils { 337 | public static string ToDirs(string aString) { 338 | string vOutput = "", vTemp = ""; 339 | for (int vI = 0, vL = aString.Length; vI < vL; vI++) { 340 | if ('\\' == aString[vI] || '/' == aString[vI]) { 341 | vOutput += vTemp + "/"; 342 | vTemp = ""; 343 | } else vTemp += aString[vI]; 344 | } 345 | return vOutput; 346 | } 347 | public static bool MakeDirAll(string aDirname) { 348 | try { 349 | if (!Directory.Exists(aDirname)) 350 | Directory.CreateDirectory(aDirname); 351 | return true; 352 | } catch { return false; } 353 | } 354 | public static bool DeleteFile(string aPath) { 355 | try { 356 | if (File.Exists(aPath)) 357 | File.Delete(aPath); 358 | return true; 359 | } catch { return false; } 360 | } 361 | public static bool DeleteDir(string aPath) { 362 | try { 363 | if (Directory.Exists(aPath)) 364 | Directory.Delete(aPath, true); 365 | return true; 366 | } catch { return false; } 367 | } 368 | public static bool WriteAllText(string aFilename, string aContent) { 369 | try { 370 | File.WriteAllText(aFilename, aContent); 371 | return true; 372 | } catch { return false; } 373 | } 374 | public static string ReadAllText(string aFilename) { 375 | try { 376 | if (!File.Exists(aFilename)) return default; 377 | return File.ReadAllText(aFilename); 378 | } catch { return default; } 379 | } 380 | } 381 | public class TcpUtils { 382 | public static int GetOpenPort(int aPStart = 9000, int aPEnd = 60000) { 383 | int vUUPort = 0; 384 | System.Net.NetworkInformation.IPGlobalProperties vProps = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties(); 385 | var vTEP = vProps.GetActiveTcpListeners(); 386 | var vUPorts = (from vP in vTEP select vP.Port).ToList(); 387 | for (int vPort = aPStart; vPort < aPEnd; vPort++) 388 | if (!vUPorts.Contains(vPort)) { 389 | vUUPort = vPort; 390 | break; 391 | } 392 | return vUUPort; 393 | } 394 | } 395 | } 396 | --------------------------------------------------------------------------------