diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 040120d..0000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,2 +0,0 @@ -github: TheDcoder -liberapay: DcodingTheWeb diff --git a/.gitignore b/.gitignore index 44e9599..9ac0f11 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,2 @@ -Tor/ -Tor Data/ -config.torrc -config.ini -Builds/ +# Ignore the build directory +build/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..2bee9a1 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "liballium"] + path = allium + url = https://github.com/DcodingTheWeb/liballium diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc deleted file mode 100644 index 7e31190..0000000 --- a/CHANGELOG.adoc +++ /dev/null @@ -1,92 +0,0 @@ -= Changelog - -== v0.4.3 (Luscious Last) - -A minor release to add support for Snowflake bridges and to fix a fatal bug which could crash ProxAllium, as well as a few other quality of life improvements. - -You can now obtain ProxAllium via https://community.chocolatey.org/packages/proxallium[Chocolately], a package manager for Windows. It's maintained by https://github.com/Cossey[Stewart Cossey] (big thanks!). - -.Additions -* Added support for the Snowflake pluggable transport -* Added an option to run Tor setup manually - -.Changes -* Main window no longer hides when minimized, instead it hides when closed - -.Fixes -* An out-of-bounds bug in Tor output handling code - -== v0.4.2 (Luscious Last) - -This is a maintainence release with some updates to how ProxAllium is packaged, I no longer wish to package Tor along with ProxAllium for various reasons, mainly that I was no longer using ProxAllium in Windows myself and it was getting harder to keep track of new Tor releases and push an updated package everytime. - -I understand that it has been a while since the last release, but many things have happened since. I now have a full-timeish job that keeps me busy and I have also switched to Linux as my main operating system a while ago. The good news is that I have been working on a cross-platform version of ProxAllium, the progress is slow due to myself not being very experienced at writing a program in C and interacting with the system on a lower level... and also my job takes most of my time. - -.Additions -* A new interactive guide for setting up Tor -* A new setting to define the path for obfs4 pluggable transport in the configuration file - -.Changes -* Tor is no longer packaged along with ProxAllium - -== v0.4 (Luscious Last) -(_Thanks to my dear friend TheSaint for suggesting the name for this release_) - -This will probably be the first and final stable release of ProxAllium written in AutoIt. I am planning to rewrite it in C so that it can take advantage of various thing which cannot be done in AutoIt. This was challenging to accomplish and I learned many new things about AutoIt and programming, it maybe a while before I start working on the cross-platform C version as I am busy with work and life these days. Thank you to everyone who has used ProxAllium! - -.Additions -* *ProxAllium now directly communicates with Tor*. This means Tor is handled properly and opens up more possibilities! -* Support for bridges with pluggable transports `obfs` (all versions) and `scramblesuit`, GUI included for configuration -* Support for HTTP tunnel -* Added documentation for all INI options -* Added an option to start with Windows -* Added an option to start minimized -* Added an option to regenerate Tor configuration -* Added an option to switch to clean Tor circuits - -.Fixed and changes -* Tor Output now resets after starting Tor instead of resetting everytime Tor stops or crashes -* Paths from configuration (`config.ini`) are no longer converted to absolute paths internally, this prevents use of absolute paths in the generated `torrc` file which may cause portability issues - -== v0.3-beta (GUI Goodness) -Finally out of alpha! :) - -.Additions -* **New GUI** with buttons, text fields, menubar, status indicator etc. -* Added "Hostname" -* Added Tray Tips (ProxAllium will notify you about Tor) -* Added multi-instance detection (ProxAllium will detect if it is already running) - -.Fixes and changes -* Closing the Tor Output window will no longer prompt to stop Tor -* AsciiDoc is used instead of Markdown -* Fixed crashing if Tor was not initialized properly -* Tor is handled better internally (ProxAllium can detect crashes now) -* `config.ini` uses relative paths instead of absolute paths which can cause problems in a portable environment (Fixes https://github.com/DcodingTheWeb/ProxAllium/issues/1[#1]) -* UPX is no longer used to compile ProxAllium, this should reduce anti-virus false positives. -* More minor internal changes - -.Changes independent of ProxAllium's code -* New website with documentation, screenshots, webchat etc! - -== v0.2-alpha (Featury Feast) -.Additions -* `ProxAllium.exe` now has its Product Version property filled -* Added ability to show Error/Warning messages made by Tor -* Added ability to Stop/Start Tor without restarting ProxAllium! -* Added ability to auto-generate `config.ini` (Therefore there is no need to pack `config.ini` in the release packages) -* Added support for HTTP(S) and SOCKS4/5 proxies (No GUI yet to configure these though) - -.Fixes and changes -* **Fixed a lot of bugs** (including the bug where ProxAllium was not stopping Tor when exiting) -* **Optimisation and cleanup** -* Updated `README.md` and `CREDITS.md` -* Changed the internal structure/workings/design of ProxAllium -* Changed some text to be more meaningful -* Changed Tor's data directories location (You can now delete the `data` directory in `Tor/data` if you are upgrading) -* Tor Output Window no longer asks for confirmation if Tor has already exited -* ProxAllium no longer prompts to exit after closing Tor - -(You can also https://github.com/DcodingTheWeb/ProxAllium/compare/v0.1-alpha...v0.2-alpha[view] the complete code changes across the previous release if you want) - -**EDIT (23-02-2017)**: Added PGP signature to the list of downloads, you can find Dcoding The Web's public key https://dcodingtheweb.com/key.asc[here]. diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..611f217 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_minimum_required(VERSION 3.0) + +# Define the project and executable +project(ProxAllium C) +add_executable(proxallium proxallium.c log.c utils.c) + +# Set the version +set(VERSION dev) +find_program(git git) +execute_process( + COMMAND ${git} rev-parse --short HEAD + OUTPUT_VARIABLE "GIT_HASH" + OUTPUT_STRIP_TRAILING_WHITESPACE +) +add_compile_definitions("VERSION=\"${VERSION} (git-${GIT_HASH})\"") + +# Enable warnings +if(CMAKE_C_COMPILER_ID STREQUAL "GNU") + add_compile_options(-Wall -Wno-maybe-uninitialized -Wno-parentheses -Wpedantic) +endif() + +# Link liballium +set($ENV{SKIP_CRYPT} "") +add_subdirectory(allium) +target_link_libraries(proxallium PRIVATE allium) diff --git a/IniReadWrite.au3 b/IniReadWrite.au3 deleted file mode 100644 index 9431756..0000000 --- a/IniReadWrite.au3 +++ /dev/null @@ -1,21 +0,0 @@ -; #FUNCTION# ==================================================================================================================== -; Name ..........: IniReadWrite -; Description ...: Write the default value to Ini if it does not exist -; Syntax ........: IniReadWrite($sFile, $sSection, $sKey, $sDefault) -; Parameters ....: $sFile - The path for the .ini file. -; $sSection - The section name in the .ini file. -; $sKey - The key name in the .ini file. -; $sDefault - The default value. -; Return values .: The value of the $sKey in the Ini file or $sDefault if the $sKey does not exists -; Author ........: Damon Harris (TheDcoder) -; Remarks .......: PRO TIP: IniReadWrite is fully compatible with IniRead (i.e Same parameters) -; Related .......: IniRead and IniWrite -; Link ..........: https://gist.github.com/TheDcoder/b5035d600b7a130ea45311541a15a555 -; Example .......: No -; =============================================================================================================================== -Func IniReadWrite($sFile, $sSection, $sKey, $sDefault) - Local $sIniRead = IniRead($sFile, $sSection, $sKey, "") - If Not $sIniRead = "" Then Return $sIniRead - IniWrite($sFile, $sSection, $sKey, $sDefault) - Return $sDefault -EndFunc diff --git a/IsMgcNumPresent.au3 b/IsMgcNumPresent.au3 deleted file mode 100644 index 22b78da..0000000 --- a/IsMgcNumPresent.au3 +++ /dev/null @@ -1,18 +0,0 @@ -; #FUNCTION# ==================================================================================================================== -; Name ..........: IsMgcNumPresent -; Description ...: Checks if a number is a present in a number (Magic numbers aka Powers of 2) -; Syntax ........: IsMgcNumPresent($iNumber, $iMagicNumber) -; Parameters ....: $iNumber - Number to check if it exists in $iMagicNumber. -; $iMagicNumber - The number which might contain $iNumber. -; Return values .: Success: True -; Failure: False -; Author ........: Damon Harris (TheDcoder) -; Modified ......: -; Remarks .......: -; Related .......: -; Link ..........: https://git.io/vPFjk -; Example .......: Yes, see IsMgcNumPresent_Example.au3 -; =============================================================================================================================== -Func IsMgcNumPresent($iNumber, $iMagicNumber) - Return BitAND($iMagicNumber, $iNumber) = $iNumber -EndFunc \ No newline at end of file diff --git a/LICENSE b/LICENSE index 91c296c..563b1b3 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,27 @@ -MIT License +Copyright (c) 2019, Dcoding The Web +All rights reserved. -Copyright (c) 2016 Dcoding The Web +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/ProcessEx.au3 b/ProcessEx.au3 deleted file mode 100644 index ea30eaa..0000000 --- a/ProcessEx.au3 +++ /dev/null @@ -1,305 +0,0 @@ -#include-once -#include -#include -#include -#include -#include -#include -#include -#include -#include "IsMgcNumPresent.au3" - -#AutoIt3Wrapper_Au3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w- 4 -w 5 -w 6 -w- 7 - -; #INDEX# ======================================================================================================================= -; Title ............: Process UDF. -; AutoIt Version ...: 3.3.14.1 -; Description ......: UDF for AutoIt which contains useful functions which can be used to interact with processes in windows! -; Author(s) ........: Damon Harris (TheDcoder). -; This UDF Uses ....: PslatyDS's Code - https://www.autoitscript.com/forum/topic/98602-run-not-runwait-with-dos-exit-code/?do=findComment&comment=720326 -; Is Magic Number Present? - https://git.io/vPFjk -; Links ............: GitHub - https://github.com/TheDcoder/Process-UDF-for-AutoIt/ -; AutoIt Forum - https://www.autoitscript.com/forum/topic/174697-process-udf-get-both-the-output-the-exit-code -; =============================================================================================================================== - -; #CURRENT# ===================================================================================================================== -; _Process_RunCommand -; _Process_WaitUntil -; _Process_GetPID -; _Process_GetPath -; _Process_GetHandle -; _Process_CloseHandle -; _Process_GetExitCode -; _Process_DebugRunCommand -; =============================================================================================================================== - -; #INTERNAL_USE_ONLY# =========================================================================================================== -; __Process_WM_SIZE -; =============================================================================================================================== - -; #CONSTANTS# =================================================================================================================== -Global Const $PROCESS_RUN = 2, $PROCESS_RUNWAIT = 4, $PROCESS_EXIST = 8, $PROCESS_NOTEXIST = 16, $PROCESS_DEBUG = 32 - -Global Const $PROCESS_COMMAND = @ComSpec & " /c " ; Use this in RunCommand function to run commands -; =============================================================================================================================== - -; #FUNCTION# ==================================================================================================================== -; Name ..........: _Process_RunCommand -; Description ...: Runs a command or a executable -; Syntax ........: _Process_RunCommand($iMode, $sExecutable [, $sWorkingDir = "" [, $iRunOptFlag = $STDERR_MERGED]]) -; Parameters ....: $iMode - Mode in which this function should operate, See Remarks. -; $sExecutable - The command to run/execute (along with any arguments). -; $sWorkingDir - [optional] The working directroy for the command. Default is "". -; $iRunOptFlag - [optional] The Opt flag for the Run function. Default is $STDERR_MERGED. -; Return values .: Success: Mode $PROCESS_RUN : Will return the process handle & @extended will contain the PID of the command -; Mode $PROCESS_RUNWAIT : Will return the output & @extended will contain the exit code for the function -; Failure: Will return False & @error will contain: -; 1 - If the $iMode flag is invalid -; 2 - If the command is invalid -; Author ........: TheDcoder -; Remarks .......: 1. The ONLY valid modes are: $PROCESS_RUN & $PROCESS_RUNWAIT -; $PROCESS_RUN : Will act similarly to Run function, See Return values -; $PROCESS_RUNWAIT : Will act similarly to RunWait function, See Return values -; If you use $PROCESS_RUN then use _Process_GetExitCode to get the exit code & use StdoutRead to get the output of the command -; 2. Use $PROCESS_COMMAND to run commands like this: $PROCESS_COMMAND & "ping 127.0.0.1" -; 3. Add $PROCESS_DEBUG to $iMode to automagically debug the command, $PROCESS_RUN is equivalent to $PROCESS_RUNWAIT in this case -; Related .......: Run, RunWait -; Example .......: Yes, see example.au3 -; ===============================================================================================================================; Functions -Func _Process_RunCommand($iMode, $sExecutable, $sWorkingDir = "", $iRunOptFlag = $STDERR_MERGED) - Local $iExitCode = 0 ; Declare the exit code variable before hand - Local $sOutput = "" ; Declare the output variable before hand - Local $bDebug = IsMgcNumPresent($PROCESS_DEBUG, $iMode) ; Check if $PROCESS_DEBUG is present. - Select ; Select... - Case IsMgcNumPresent($PROCESS_RUN, $iMode) ; If the mode is $PROCESS_RUN - $iMode = $PROCESS_RUN - - Case IsMgcNumPresent($PROCESS_RUNWAIT, $iMode) ; If the mode is $PROCESS_RUNWAIT - $iMode = $PROCESS_RUNWAIT - - Case Else - Return SetError(1, 0, False) ; If the mode is invalid... - EndSelect - Local $iPID = Run($sExecutable, $sWorkingDir, @SW_HIDE, $iRunOptFlag) ; Run!!! :P - If @error Then Return SetError(2, 0, False) ; If the command is invalid... - Local $hProcessHandle = _Process_GetHandle($iPID) ; Get the handle of the process - If $iMode = $PROCESS_RUN Then - If Not $bDebug Then Return SetExtended($iPID, $hProcessHandle) ; If the function is in Run mode then return the PID & Process Handle - $sOutput = _Process_DebugRunCommand($hProcessHandle, $iPID) ; Debug the process - $iExitCode = _Process_GetExitCode($hProcessHandle) ; Note the exit code - Return SetExtended($iExitCode, $sOutput) ; Return the output & exit code - EndIf - If Not $bDebug Then - While ProcessExists($iPID) - $sOutput &= StdoutRead($iPID) ; Capture the output - Sleep(10) ; Don't kill the CPU - WEnd - $sOutput &= StdoutRead($iPID) ; Capture any remaining output - $iExitCode = _Process_GetExitCode($hProcessHandle) ; Note the exit code - Return SetExtended($iExitCode, $sOutput) ; Return the exit code & the output :D - EndIf - $sOutput = _Process_DebugRunCommand($hProcessHandle, $iPID) ; Debug the process - $iExitCode = _Process_GetExitCode($hProcessHandle) ; Note the exit code - Return SetExtended($iExitCode, $sOutput) ; Return the output & exit code -EndFunc - -; #FUNCTION# ==================================================================================================================== -; Name ..........: _Process_WaitUntil -; Description ...: Waits until a process starts or quits. Also returns the exit code... -; Syntax ........: _Process_WaitUntil($iMode, $vProcess [, $iUpdateInterval = 10]) -; Parameters ....: $iMode - Mode in which this function should operate, See Remarks. -; $vProcess - The PID or Name of the process, Same as ProcessExist's "process" parameter. -; $iUpdateInterval - [optional] The time (in milliseconds) to wait before performing another check. Default is 10. -; Return values .: Success: True and sets @extended to the exit code if the mode is $PROCESS_NOTEXIST -; Failure: False -; Special: 0(See Remarks) -; Author ........: TheDcoder -; Remarks .......: 1. There are only 2 valid modes: -; $PROCESS_EXIST : Waits until a process starts. -; $PROCESS_NOTEXIST : Waits until a process quits. -; 2. 0 is returned when unable to retrive the PID of the process when in $PROCESS_NOTEXIST as the mode, -; There is an good chance that the process has already quit before the function starts checking. -; Example .......: No -; =============================================================================================================================== -Func _Process_WaitUntil($iMode, $vProcess, $iUpdateInterval = 10) - If $iMode = $PROCESS_NOTEXIST And Not IsInt($vProcess) Then ; If it is in $PROCESS_NOTEXIST mode & not an PID - $vProcess = _Process_GetPID($vProcess) ; Get the PID - If @error Then Return 0 ; Return Immediatly - EndIf - Switch $iMode ; Switch to the required mode to opreate in. - Case $PROCESS_EXIST - While Not ProcessExists($vProcess) ; Wait for the process to start - Sleep($iUpdateInterval) ; Some mercy on the CPU - WEnd - Return True ; Return True - - Case $PROCESS_NOTEXIST - Local $hProcessHandle = _Process_GetHandle($vProcess) ; Get the process handle :) - While ProcessExists($vProcess) ; Wait for the process to quit - Sleep($iUpdateInterval) ; Some mercy on the CPU - WEnd - Return SetExtended(_Process_GetExitCode($hProcessHandle), True) ; Return True & set @extended to the exit code - - Case Else - Return False - EndSwitch -EndFunc - -; #FUNCTION# ==================================================================================================================== -; Name ..........: _Process_GetPID -; Description ...: Gets the PID of the process using the name of the process -; Syntax ........: _Process_GetPID($sProcess) -; Parameters ....: $sProcess - The name of the process. -; Return values .: Success: The PID of the process -; Failure: False & sets @error to non-zero -; Author ........: TheDcoder -; Remarks .......: If multiple processes exist then the most recent process's PID is returned. -; Example .......: No -; =============================================================================================================================== -Func _Process_GetPID($sProcess) - Local $aProcess = ProcessList($sProcess) ; List processes with that name - If @error Or $aProcess[0][0] = 0 Then Return SetError(@error, False) ; Return False & set @error to non-zero if an error - Return $aProcess[1][1] ; Return the PID -EndFunc - -; #FUNCTION# ==================================================================================================================== -; Name ..........: _Process_GetPath -; Description ...: Get the path of a process along with its arguments (if any) -; Syntax ........: _Process_GetPath($vProcess) -; Parameters ....: $vProcess - The PID or name of the process. -; Return values .: Success: The path of process with its arguments -; Failure: False & sets @error to 1 -; Author ........: TheDcoder -; Remarks .......: The return value is in this format: X:\Process.exe -Argument1 -ArgumentN... -; Example .......: No -; =============================================================================================================================== -Func _Process_GetPath($vProcess) - Local Const $eiCharsToTrim = 12 - If Not IsInt($vProcess) Then $vProcess = _Process_GetPID($vProcess) ; Convert process name to PID - Local $sCommandline = "wmic" ; Declare the commandline string - $sCommandline &= ' process' - $sCommandline &= ' where "' & "processid='" & $vProcess & "'" & '"' - $sCommandline &= ' get commandline /format:list' - Local $sOutput = _Process_RunCommand($PROCESS_RUNWAIT, $sCommandline) ; Run the command... - ; Thanks to rojo for this command at stackowerflow: http://stackoverflow.com/a/32609300/3815591 - $sOutput = StringStripWS($sOutput, $STR_STRIPLEADING + $STR_STRIPTRAILING) ; Remove whitespaces attached to the string - If $sOutput = "No Instance(s) Available." Then Return SetError(1, 0, False) ; If process was not found... - Local $sCommand = StringTrimLeft($sOutput, $eiCharsToTrim) ; Trim the Commandline= - Return $sCommand ; Return -EndFunc - -; #FUNCTION# ==================================================================================================================== -; Name ..........: _Process_GetHandle -; Description ...: Gets the handle of a process, will be used later to retrive the exit code -; Syntax ........: _Process_GetHandle($vProcess) -; Parameters ....: $vProcess - The PID or name of the process. -; Return values .: Success: Process handle -; Failure: 0 & Sets @error to non-zero -; Author ........: PsaltyDS -; Modified ......: TheDcoder: Comments, "If...Else...EndIf" to "If...Then", Return value for failure & Name of the function -; Example .......: No -; =============================================================================================================================== -Func _Process_GetHandle($vProcess) - If Not IsInt($vProcess) Then $vProcess = _Process_GetPID($vProcess) ; Get the PID of the process if its not a PID ;) - Local $avRET = DllCall("kernel32.dll", "ptr", "OpenProcess", "int", $PROCESS_QUERY_INFORMATION, "int", 0, "int", $vProcess) ; Get the process handle - If @error Then Return SetError(1, 0, 0) ; If the process does not exists... - Return $avRET[0] ; Return handle -EndFunc - -; #FUNCTION# ==================================================================================================================== -; Name ..........: _Process_CloseHandle -; Description ...: Closes the Process Handle of a process -; Syntax ........: _Process_CloseHandle($hProcessHandle) -; Parameters ....: $hProcessHandle - A Process Handle. -; Return values .: Success: True -; Failure: False & sets @error to non-zero -; Author ........: PsaltyDS -; Modified ......: TheDcoder: Comments, "If...Else...EndIf" to "If...Then", Return values & Name of the function -; Example .......: No -; =============================================================================================================================== -Func _Process_CloseHandle($hProcessHandle) - DllCall("kernel32.dll", "int", "CloseHandle", "ptr", $hProcessHandle) ; Close the handle - If @error Then Return SetError(@error, 0, False) ; If invalid handle... - Return True ; Return True if success -EndFunc - -; #FUNCTION# ==================================================================================================================== -; Name ..........: _Process_GetExitCode -; Description ...: Gets the exit code of a process -; Syntax ........: _Process_GetExitCode($hProcessHandle[, $bCloseHandle = True]) -; Parameters ....: $hProcessHandle - A Process Handle. -; $bCloseHandle - [optional] Do you want to close the $hProcessHandle?. Default is True. -; Return values .: Success: Exit Code -; Failure: Returns 0 & sets @error to non-zero -; Author ........: PsaltyDS -; Modified ......: TheDcoder: Comments & Name of the function -; Example .......: No -; =============================================================================================================================== -Func _Process_GetExitCode($hProcessHandle, $bCloseHandle = True) - Local $t_ExitCode = DllStructCreate("int") ; Its the container for the exit code - DllCall("kernel32.dll", "int", "GetExitCodeProcess", "ptr", $hProcessHandle, "ptr", DllStructGetPtr($t_ExitCode)) ; Store the exit code in the container - If @error Then Return SetError(1, 0, 0) ; If it is a invalid $hProcessHandle then return error - If $bCloseHandle Then _Process_CloseHandle($hProcessHandle) ; Close the $hProcessHandle - Return DllStructGetData($t_ExitCode, 1) ; Return exit code from the container -EndFunc - -; #FUNCTION# ==================================================================================================================== -; Name ..........: _Process_DebugRunCommand -; Description ...: Debugs a command in CMD style, see the example. -; Syntax ........: _Process_DebugRunCommand($hProcessHandle, $iPID[, $sGuiTitle = "Command Prompt Simulator"]) -; Parameters ....: $hProcessHandle - The Process Handle. -; $iPID - The PID of the Process. -; $sGuiTitle - [optional] The title of the Debug window. Default is "Command Prompt Simulator". -; Return values .: Success: Will return the output & @extended will contain the exit code for the function -; Failure: N/A -; Author ........: TheDcoder -; Modified ......: N/A -; Remarks .......: Make sure that the Process Handle & the PID are of the same process, otherwise you get the wrong exit code :P -; Example .......: Yes, see example.au3 -; =============================================================================================================================== -Func _Process_DebugRunCommand($hProcessHandle, $iPID, $sGuiTitle = "Command Prompt Simulator") - Local $aGrayCmdColor[3] = [197, 197, 197] ; CMD Text Color's combination in RGB - Local Const $iGrayCmdColor = _ColorSetRGB($aGrayCmdColor) ; Get the RGB code of CMD Text Color - Local $hGUI = GUICreate($sGuiTitle, 639, 299, -1, -1, $WS_OVERLAPPEDWINDOW) ; Create the GUI - Local $idEdit = GUICtrlCreateEdit("", 0, 0, 639, 299, BitOR($WS_HSCROLL, $WS_VSCROLL, $ES_MULTILINE, $ES_READONLY, $ES_AUTOVSCROLL), 0) ; Create the Edit control :) - Global $g__hEdit = GUICtrlGetHandle($idEdit) ; Get the edit control's handle - GUICtrlSetBkColor($idEdit, $COLOR_BLACK) ; Set the background color - GUICtrlSetColor($idEdit, $iGrayCmdColor) ; Set the text color - GUICtrlSetFont($idEdit, 8, 0, 0, "Fixedsys") - GUIRegisterMsg($WM_SIZE, "__Process_WM_SIZE") ; Register the resizing function - GUISetState(@SW_SHOW, $hGUI) ; Reveal the GUI - _GUICtrlEdit_AppendText($g__hEdit, "The Process: " & _Process_GetPath($iPID) & @CRLF) ; Append the process information - Local $sOutput = "", $sPartialOutput = "" ; Declare the output variable - While ProcessExists($iPID) ; Loop until the process finishes - $sPartialOutput = StdoutRead($iPID) ; Record the output - $sOutput &= $sPartialOutput - _GUICtrlEdit_AppendText($g__hEdit, $sPartialOutput) ; Append the output - Sleep(250) ; Don't kill the CPU - WEnd - $sPartialOutput = StdoutRead($iPID) ; Record the output - $sOutput &= $sPartialOutput - _GUICtrlEdit_AppendText($g__hEdit, $sPartialOutput) ; Append any remaining chunks of output - Local $iExitCode = _Process_GetExitCode($hProcessHandle) - _GUICtrlEdit_AppendText($g__hEdit, @CRLF & @CRLF & "Debug Complete! The Exit Code was: " & $iExitCode) ; Display the exit code - ; Same steps as in the above loop - Local $nMsg = 0 - While 1 ; Wait for user to close the window - $nMsg = GUIGetMsg() - Switch $nMsg - Case $GUI_EVENT_CLOSE - ExitLoop - EndSwitch - WEnd - GUIDelete($hGUI) ; Delete the GUI - Return SetExtended($iExitCode, $sOutput) ; Return True -EndFunc - -Func __Process_WM_SIZE($hWnd, $iMsg, $wParam, $lParam) - Local $iWidth = _WinAPI_LoWord($lParam) - Local $iHeight = _WinAPI_HiWord($lParam) - - _WinAPI_MoveWindow($g__hEdit, 2, 2, $iWidth - 4, $iHeight - 4) - - Return 0 - #forceref $hWnd, $iMsg, $wParam -EndFunc ; Thanks Mat :) \ No newline at end of file diff --git a/ProxAllium.au3 b/ProxAllium.au3 deleted file mode 100644 index 81d41ff..0000000 --- a/ProxAllium.au3 +++ /dev/null @@ -1,832 +0,0 @@ -#NoTrayIcon - -#Region AutoIt3Wrapper Directives -#AutoIt3Wrapper_Icon=icon.ico -#AutoIt3Wrapper_Outfile=Builds\ProxAllium.exe -#AutoIt3Wrapper_Res_Description=ProxAllium - Tor Proxy Bundle -#AutoIt3Wrapper_Res_Fileversion=0.4.3.0 -#AutoIt3Wrapper_Res_ProductVersion=0.4.3.0 -#AutoIt3Wrapper_Res_LegalCopyright=Dcoding The Web -#AutoIt3Wrapper_Run_Au3Stripper=y -#Au3Stripper_Parameters=/sf /sv /mo /rm -#EndRegion AutoIt3Wrapper Directives - -#Region Includes -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "Tor.au3" -#include "IniReadWrite.au3" -#EndRegion Includes - -#Region Multi-Instance Handler -Handle_MultipleInstance() -#EndRegion Multi-Instance Handler - -#Region Variable Initialization -Global $g_aTorProcess[2] -Global $g_aTorVersion[0] - -#Region Read Configuration -Global Const $CONFIG_INI = @ScriptDir & '\config.ini' - -Global $g_sTorPath = IniReadWrite($CONFIG_INI, "tor", "path", 'Tor\tor.exe') -Global $g_sObfs4Path = IniReadWrite($CONFIG_INI, "tor", "obfs4_path", 'Tor\PluggableTransports\obfs4\obfs4proxy.exe') -Global $g_sSnowflakePath = IniReadWrite($CONFIG_INI, "tor", "snowflake_path", 'Tor\PluggableTransports\snowflake-client.exe') -Global $g_sSnowflakeArgs = IniReadWrite($CONFIG_INI, "tor", "snowflake_args", '-url=https://snowflake-broker.torproject.net.global.prod.fastly.net/ -front=cdn.sstatic.net -ice=stun:stun.voip.blackberry.com:3478,stun:stun.altar.com.pl:3478,stun:stun.antisip.com:3478,stun:stun.bluesip.net:3478,stun:stun.dus.net:3478,stun:stun.epygi.com:3478,stun:stun.sonetel.com:3478,stun:stun.sonetel.net:3478,stun:stun.stunprotocol.org:3478,stun:stun.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.voys.nl:3478') -Global $g_sTorConfigFile = IniReadWrite($CONFIG_INI, "tor", "config_file", 'config.torrc') -Global $g_sTorDataDirPath = IniReadWrite($CONFIG_INI, "tor", "data_dir", 'Tor Data') -Global $g_sTorGeoIPv4File = IniReadWrite($CONFIG_INI, "tor", "geoip4_file", 'Tor\geoip') -Global $g_sTorGeoIPv6File = IniReadWrite($CONFIG_INI, "tor", "geoip6_file", 'Tor\geoip6') -Global $g_iOutputPollInterval = Int(IniReadWrite($CONFIG_INI, "proxallium", "output_poll_interval", "100")) - -Global $g_sTorConfig_Port = IniReadWrite($CONFIG_INI, "tor_config", "port", "9050") -Global $g_sTorConfig_TunnelPort = IniRead($CONFIG_INI, "tor_config", "tunnel_port", "") -Global $g_sTorConfig_ControlPort = IniReadWrite($CONFIG_INI, "tor_config", "control_port", "9051") -Global $g_sTorConfig_ControlPass = IniReadWrite($CONFIG_INI, "tor_config", "control_pass", String(Random(100000, 999999, 1))) -Global $g_bTorConfig_OnlyLocalhost = (IniReadWrite($CONFIG_INI, "tor_config", "localhost_only", "true") = "true") -Global $g_sTorConfig_ExitNodeCC = IniRead($CONFIG_INI, "tor_config", "exit_node_country_code", "") - -Global $g_sTorConfig_ProxyType = IniRead($CONFIG_INI, "proxy", "type", "") -Global $g_sTorConfig_ProxyHost = IniRead($CONFIG_INI, "proxy", "host", "") -Global $g_sTorConfig_ProxyPort = IniRead($CONFIG_INI, "proxy", "port", "") -Global $g_sTorConfig_ProxyUser = IniRead($CONFIG_INI, "proxy", "user", "") -Global $g_sTorConfig_ProxyPass = IniRead($CONFIG_INI, "proxy", "pass", "") - -Global $g_bTorConfig_BridgesEnabled = (IniRead($CONFIG_INI, "bridges", "enabled", "false") = "true") -Global $g_sTorConfig_BridgesPath = IniRead($CONFIG_INI, "bridges", "path", $g_sTorDataDirPath & '\bridges.txt') - -Global $g_bTorConfig_AutoStart = (IniRead($CONFIG_INI, "startup", "auto_start", "false") = "true") -Global $g_sTorConfig_AutoStartShortcut = IniRead($CONFIG_INI, "startup", "auto_start_shortcut", "") -Global $g_bTorConfig_StartMinimized = (IniRead($CONFIG_INI, "startup", "start_minimized", "false") = "true") -#EndRegion Read Configuration - -#EndRegion Variable Initialization - -#Region Tray Creation -Opt("TrayMenuMode", 1 + 2) ; No default menu and automatic checkmarks -Opt("TrayOnEventMode", 1) ; OnEvent mode -Opt("TrayAutoPause", 0) ; No Auto-Pause - -Tray_Initialize() - -Func Tray_Initialize() - TraySetClick(16) ; Will display the menu when releasing the secondary mouse button - TraySetOnEvent($TRAY_EVENT_PRIMARYDOWN, "GUI_ToggleMainWindow") - TrayItemSetState(TrayCreateItem("ProxAllium"), $TRAY_DISABLE) - TrayCreateItem("") - Global $g_idTrayMainWinToggle = TrayCreateItem('...') - TrayItemSetOnEvent($g_idTrayMainWinToggle, "GUI_ToggleMainWindow") - Global $g_idTrayTorOutputToggle = TrayCreateItem("Show Tor Output") - TrayItemSetOnEvent($g_idTrayTorOutputToggle, "GUI_ToggleTorOutputWindow") - TrayCreateItem("") - Local $idOptions = TrayCreateMenu("Options") - Global $g_idTrayOptionBridges = TrayCreateItem("Bridges", $idOptions) - TrayItemSetOnEvent($g_idTrayOptionBridges, "Tray_HandleBridgeOption") - TrayCreateItem("", $idOptions) - Global $g_idTrayOptionRegenConfig = TrayCreateItem("Regenerate Tor configuration", $idOptions) - TrayItemSetOnEvent($g_idTrayOptionRegenConfig, "GUI_RegenerateTorrc") - Global $g_idTrayOptionRefreshCircuit = TrayCreateItem("New Tor Circuit for future connections", $idOptions) - TrayItemSetOnEvent($g_idTrayOptionRefreshCircuit, "GUI_RefreshCircuit") - TrayCreateItem("") - Global $g_idTrayToggleTor = TrayCreateItem("Stop Tor") - TrayItemSetOnEvent($g_idTrayToggleTor, "Tor_Toggle") - TrayCreateItem("") - TrayItemSetOnEvent(TrayCreateItem("Exit"), "GUI_MainWindowExit") - TraySetState($TRAY_ICONSTATE_SHOW) - TraySetToolTip("ProxAllium") -EndFunc - -Func Tray_HandleBridgeOption() - Call("GUI_BridgeHandler", $g_idTrayOptionBridges) -EndFunc -#EndRegion Tray Creation - -#Region GUI Creation -Opt("GUIOnEventMode", 1) -GUI_CreateMainWindow() -GUI_LogOut("Starting ProxAllium... Please wait :)") -GUI_CreateTorOutputWindow() -GUI_CreateBridges() - -Func GUI_CreateMainWindow() - Global $g_hMainGUI = GUICreate("ProxAllium", 580, 370) - GUISetOnEvent($GUI_EVENT_CLOSE, "GUI_ToggleMainWindow", $g_hMainGUI) - GUICtrlCreateMenu("ProxAllium") - GUICtrlSetState(-1, $GUI_DISABLE) - Local $idMenuView = GUICtrlCreateMenu("View") - GUICtrlCreateMenuItem("Hide Main Window", $idMenuView) - GUICtrlSetOnEvent(-1, "GUI_ToggleMainWindow") - Global $g_idMainGUI_MenuToggleTorOutput = GUICtrlCreateMenuItem("Show Tor Output", $idMenuView) - GUICtrlSetOnEvent(-1, "GUI_ToggleTorOutputWindow") - Local $idMenuOptions = GUICtrlCreateMenu("Options") - Global $g_idMainGUI_MenuBridges = GUICtrlCreateMenuItem("Bridges", $idMenuOptions) - GUICtrlSetOnEvent(-1, "GUI_BridgeHandler") - GUICtrlCreateMenuItem("", $idMenuOptions) - Global $g_idMainGUI_MenuRegenConfig = GUICtrlCreateMenuItem("Regenerate Tor configuration", $idMenuOptions) - GUICtrlSetOnEvent(-1, "GUI_RegenerateTorrc") - Global $g_idMainGUI_MenuRefreshCircuit = GUICtrlCreateMenuItem("New Tor Circuit for future connections", $idMenuOptions) - GUICtrlSetOnEvent(-1, "GUI_RefreshCircuit") - GUICtrlCreateMenuItem("", $idMenuOptions) - Local $idMenuStartup = GUICtrlCreateMenu("Startup", $idMenuOptions) - Global $g_idMainGUI_MenuAutoStart = GUICtrlCreateMenuItem("Automatically start with Windows", $idMenuStartup) - GUICtrlSetOnEvent(-1, "GUI_AutoStart") - If $g_bTorConfig_AutoStart Then GUICtrlSetState(-1, $GUI_CHECKED) - Global $g_idMainGUI_MenuStartMinimized = GUICtrlCreateMenuItem("Start Minimized", $idMenuStartup) - If $g_bTorConfig_StartMinimized Then GUICtrlSetState(-1, $GUI_CHECKED) - GUICtrlSetOnEvent(-1, "GUI_StartMinimized") - GUICtrlCreateMenuItem("", $idMenuOptions) - Global $g_idMainGUI_MenuRunSetup = GUICtrlCreateMenuItem("Run Tor setup again", $idMenuOptions) - GUICtrlSetOnEvent(-1, "Core_SetupTor") - GUICtrlCreateGroup("Proxy Details", 5, 5, 570, 117) - GUICtrlCreateLabel("Hostname:", 10, 27, 60, 15) - Global $g_idMainGUI_Hostname = GUICtrlCreateInput("localhost", 73, 22, 497, 20, $ES_READONLY, $WS_EX_CLIENTEDGE) - GUICtrlSetBkColor(-1, $COLOR_WHITE) - GUICtrlCreateLabel("IP Address:", 10, 52, 60, 15) - Global $g_idMainGUI_IPAddress = GUICtrlCreateInput("127.0.0.1", 73, 47, 497, 20, $ES_READONLY, $WS_EX_CLIENTEDGE) - GUICtrlSetBkColor(-1, $COLOR_WHITE) - GUICtrlCreateLabel("Port:", 10, 77, 60, 15) - Global $g_idMainGUI_Port = GUICtrlCreateInput('...', 73, 72, 497, 20, $ES_READONLY, $WS_EX_CLIENTEDGE) - GUICtrlSetBkColor(-1, $COLOR_WHITE) - GUICtrlCreateLabel("Proxy Type:", 10, 102, 60, 15) - GUICtrlCreateInput("SOCKS5", 73, 97, 497, 20, $ES_READONLY, $WS_EX_CLIENTEDGE) - GUICtrlSetBkColor(-1, $COLOR_WHITE) - GUICtrlCreateGroup("Tor Details", 5, 125, 570, 64) - GUICtrlCreateLabel("Tor PID:", 10, 144, 60, 15) - Global $g_idMainGUI_TorPID = GUICtrlCreateInput("Not running", 73, 139, 497, 20, $ES_READONLY, $WS_EX_CLIENTEDGE) - GUICtrlSetBkColor(-1, $COLOR_WHITE) - GUICtrlCreateLabel("Tor Version:", 10, 169, 60, 15) - Global $g_idMainGUI_TorVersion = GUICtrlCreateInput('(Yet to be determined)', 73, 164, 497, 20, $ES_READONLY, $WS_EX_CLIENTEDGE) - GUICtrlSetBkColor(-1, $COLOR_WHITE) - GUICtrlCreateGroup("Control Panel", 5, 192, 570, 42) - GUICtrlCreateLabel("Status:", 10, 213, 33, 15) - Global $g_idMainGUI_Status = GUICtrlCreateInput('Initializing', 48, 208, 438, 20, BitOr($ES_CENTER, $ES_READONLY), $WS_EX_CLIENTEDGE) - GUICtrlSetBkColor(-1, $COLOR_WHITE) - Global $g_idMainGUI_ToggleButton = GUICtrlCreateButton('...', 489, 207, 82, 22) - GUICtrlSetState(-1, $GUI_DISABLE) - GUICtrlSetOnEvent(-1, "Tor_Toggle") - Global $g_idMainGUI_Log = GUICtrlCreateEdit("", 5, 238, 570, 107, BitOR($ES_READONLY, $ES_MULTILINE, $WS_VSCROLL, $ES_AUTOVSCROLL)) - Global $g_hMainGUI_Log = GUICtrlGetHandle($g_idMainGUI_Log) - GUICtrlSetFont($g_idMainGUI_Log, 9, Default, Default, "Consolas") - GUICtrlSetBkColor($g_idMainGUI_Log, $COLOR_WHITE) - GUI_Reset() - GUI_ToggleMainWindow() -EndFunc - -Func GUI_LogOut($sText, $bEOL = True) - If $bEOL Then $sText &= @CRLF - _GUICtrlEdit_AppendText($g_hMainGUI_Log, $sText) - ConsoleWrite($sText) -EndFunc - -Func GUI_SetStatus($sStatus = '...') - GUICtrlSetData($g_idMainGUI_Status, $sStatus) -EndFunc - -Func GUI_CreateTorOutputWindow() - Local Const $eiGuiWidth = 580, $eiGuiHeight = 280 - Global $g_hTorGUI = GUICreate("Tor Output", $eiGuiWidth, $eiGuiHeight, Default, Default, $WS_OVERLAPPEDWINDOW) - GUISetOnEvent($GUI_EVENT_CLOSE, "GUI_ToggleTorOutputWindow") - Global $g_idTorOutput = GUICtrlCreateEdit("", 0, 0, $eiGuiWidth, $eiGuiHeight, BitOR($ES_READONLY, $ES_MULTILINE, $WS_VSCROLL, $ES_AUTOVSCROLL)) - Global $g_hTorOutput = GUICtrlGetHandle($g_idTorOutput) ; Get the handle of the Edit control for future use in the Tor Output Handler - GUICtrlSetFont($g_idTorOutput, 9, Default, Default, "Consolas") - GUICtrlSetBkColor($g_idTorOutput, $COLOR_BLACK) - Local $aGrayCmdColor[3] = [197, 197, 197] ; CMD Text Color's combination in RGB - Local Const $iGrayCmdColor = _ColorSetRGB($aGrayCmdColor) ; Get the RGB code of CMD Text Color - GUICtrlSetColor($g_idTorOutput, $iGrayCmdColor) -EndFunc - -Func GUI_CreateBridges() - Global $g_hBridgesGUI = GUICreate("Bridges", 515, 245, -1, -1, -1, -1, $g_hMainGUI) - GUISetOnEvent($GUI_EVENT_CLOSE, GUI_BridgeHandler, $g_hBridgesGUI) - GUICtrlCreateLabel("Bridges Status: ", 5, 13, 78, 17) - Global $g_idBridgeStatus = GUICtrlCreateLabel("", 78, 13, 47, 17) - Global $g_idBridgesToggle = GUICtrlCreateButton("", 128, 4, 59, 24) - Global $g_idBridgesSave = GUICtrlCreateButton("Save", 411, 4, 100, 24) - Global $g_idBridgesEdit = GUICtrlCreateEdit("", 5, 32, 505, 208) - - GUICtrlSetFont($g_idBridgeStatus, 8.5, $FW_BOLD) - GUICtrlSetFont($g_idBridgesEdit, 9, Default, Default, "Consolas") - - GUICtrlSetOnEvent($g_idBridgesToggle, GUI_BridgeHandler) - GUICtrlSetOnEvent($g_idBridgesSave, GUI_BridgeHandler) - - Local $sBridges = FileRead($g_sTorConfig_BridgesPath) - If Not @error Then GUICtrlSetData($g_idBridgesEdit, $sBridges) - GUICtrlSetTip($g_idBridgesEdit, "Paste your bridge lines here (one per line)", "Bridges", $TIP_INFOICON) - - GUI_BridgeHandler($g_idBridgesToggle) ; Initialize the GUI -EndFunc -#EndRegion GUI Functions - -#Region Main Script -Tor_Initialize() -If Not @error Then Tor_Start() - -Core_Idle() -#EndRegion Main Script - -#Region Functions - -#Region GUI Handlers Functions -Func GUI_MainWindowExit() - Local $iMsgBoxFlags = $MB_YESNO + $MB_ICONQUESTION - Local $sMsgBoxTitle = "Close ProxAllium" - Local $sMsgBoxMsg = "Do you really want to close ProxAllium?" - Local $iButtonID = MsgBox($iMsgBoxFlags, $sMsgBoxTitle, $sMsgBoxMsg) - If $iButtonID = $IDNO Then Return - If IsTorRunning() Then Tor_Stop() - Exit -EndFunc - -Func GUI_ToggleTorOutputWindow() - Local Static $bHidden = True - If $bHidden Then - $bHidden = Not (GUISetState(@SW_SHOWNORMAL, $g_hTorGUI) = 1) - If Not $bHidden Then - TrayItemSetText($g_idTrayTorOutputToggle, "Hide Tor Output") - GUICtrlSetData($g_idMainGUI_MenuToggleTorOutput, "Hide Tor Output") - EndIf - Return - EndIf - $bHidden = (GUISetState(@SW_HIDE, $g_hTorGUI) = 1) - If $bHidden Then - TrayItemSetText($g_idTrayTorOutputToggle, "Show Tor Output") - GUICtrlSetData($g_idMainGUI_MenuToggleTorOutput, "Show Tor Output") - EndIf -EndFunc - -Func GUI_ToggleMainWindow() - Local Static $bHidden = ($g_bTorConfig_StartMinimized ? False : True) - If $bHidden Then - $bHidden = Not (GUISetState(@SW_SHOWNORMAL, $g_hMainGUI) = 1) - If Not $bHidden Then TrayItemSetText($g_idTrayMainWinToggle, "Hide Main Window") - Else - $bHidden = (GUISetState(@SW_HIDE, $g_hMainGUI) = 1) - If $bHidden Then TrayItemSetText($g_idTrayMainWinToggle, "Show Main Window") - EndIf -EndFunc - -Func GUI_BridgeHandler($iCtrlID = Default) - Local Static $bNotInitialized = True - If $bNotInitialized Then - $g_bTorConfig_BridgesEnabled = ($g_bTorConfig_BridgesEnabled ? False : True) - $bNotInitialized = False - EndIf - Local Static $bModified - Switch (IsDeclared("iCtrlID") = $DECLARED_LOCAL ? $iCtrlID : @GUI_CtrlId) - Case $GUI_EVENT_CLOSE - If $bModified Or (_GUICtrlEdit_GetModify($g_idBridgesEdit)) Then - If MsgBox($MB_ICONQUESTION + $MB_YESNO + $MB_DEFBUTTON2, "Unsaved changes", "You have made some changes, are you sure that you want to exit without saving them to disk?") = $IDNO Then Return - EndIf - GUISetState(@SW_HIDE, $g_hBridgesGUI) - Case $g_idMainGUI_MenuBridges, $g_idTrayOptionBridges - _GUICtrlEdit_SetModify($g_idBridgesEdit, False) - $bModified = False - GUISetState(@SW_SHOW, $g_hBridgesGUI) - Case $g_idBridgesToggle - $bModified = True - If $g_bTorConfig_BridgesEnabled Then - $g_bTorConfig_BridgesEnabled = False - GUICtrlSetData($g_idBridgeStatus, "Disabled") - GUICtrlSetData($g_idBridgesToggle, "Enable") - GUICtrlSetColor($g_idBridgeStatus, $COLOR_RED) - Else - $g_bTorConfig_BridgesEnabled = True - GUICtrlSetData($g_idBridgeStatus, "Enabled") - GUICtrlSetData($g_idBridgesToggle, "Disable") - GUICtrlSetColor($g_idBridgeStatus, $COLOR_GREEN) - EndIf - Case $g_idBridgesSave - Local $hFile = FileOpen($g_sTorConfig_BridgesPath, $FO_OVERWRITE + $FO_CREATEPATH) - If $hFile = -1 Then - MsgBox($MB_ICONERROR, "Failed to open", "Failed to open/create the bridges files for writing!") - Return - EndIf - If FileWrite($hFile, GUICtrlRead($g_idBridgesEdit)) = 0 Then - MsgBox($MB_ICONERROR, "Failed to write", "Failed to write to the bridges files!") - Return - EndIf - $bModified = False - _GUICtrlEdit_SetModify($g_idBridgesEdit, False) - IniWrite($CONFIG_INI, "bridges", "enabled", StringLower($g_bTorConfig_BridgesEnabled)) - MsgBox($MB_ICONINFORMATION, "Saved", "Settings for bridges have been save successfully!") - EndSwitch -EndFunc - -Func GUI_RegenerateTorrc() - GUI_LogOut("Regenerating Tor configuration... ", False) - Core_GenTorrc() - If @error Then - GUI_LogOut("Failed! (Error Code: " & @error & ')') - Else - GUI_LogOut("Done!") - Local $sMessage = "ProxAllium has generated a new configuration, do you want to restart Tor make the changes take effect?" - If IsTorRunning() And MsgBox($MB_ICONQUESTION + $MB_YESNO, "Do you want to restart Tor?", $sMessage) = $IDYES Then - Tor_Stop() - Tor_Start() - EndIf - EndIf -EndFunc - -Func GUI_RefreshCircuit() - GUI_LogOut("Switching to clean circuits... ", False) - _Tor_SwitchCircuit($g_aTorProcess) - If @error Then - GUI_LogOut('Failed to create clean circuits! ' & StringFormat('(Error Code: %i and Extended Code: %i)', @error, @extended)) - Else - GUI_LogOut("Done!") - EndIf -EndFunc - -Func GUI_AutoStart() - Local $iReturn - If $g_bTorConfig_AutoStart Then - $iReturn = FileDelete($g_sTorConfig_AutoStartShortcut) - If $iReturn = 0 Then - MsgBox($MB_ICONERROR, "Failed to remove startup", "Failed to remove shortcut in the Startup folder!") - Else - $g_bTorConfig_AutoStart = False - IniDelete($CONFIG_INI, "startup", "auto_start") - IniDelete($CONFIG_INI, "startup", "auto_start_shortcut") - GUICtrlSetState($g_idMainGUI_MenuAutoStart, $GUI_UNCHECKED) - MsgBox($MB_ICONINFORMATION, "Successfully removed from startup", "ProxAllium will no longer start with Windows") - EndIf - Else - Local $sStartupFolder = _WinAPI_ShellGetKnownFolderPath($FOLDERID_Startup) - $sShortcutPath = $sStartupFolder & '\ProxAllium.lnk' - If FileExists($sShortcutPath) Then $sShortcutPath = _TempFile($sStartupFolder, "ProxAllium_", '.lnk') - $iReturn = FileCreateShortcut(@ScriptFullPath, $sShortcutPath, @WorkingDir) - If $iReturn = 0 Then - MsgBox($MB_ICONERROR, "Cannot add to startup", "Failed to create a shortcut in the Startup folder!") - Else - $g_bTorConfig_AutoStart = True - IniWrite($CONFIG_INI, "startup", "auto_start", "true") - $g_sTorConfig_AutoStartShortcut = $sShortcutPath - IniWrite($CONFIG_INI, "startup", "auto_start_shortcut", $sShortcutPath) - GUICtrlSetState($g_idMainGUI_MenuAutoStart, $GUI_CHECKED) - MsgBox($MB_ICONINFORMATION, "Successfully added to startup", "ProxAllium will start with Windows from now!") - EndIf - EndIf -EndFunc - -Func GUI_StartMinimized() - If $g_bTorConfig_StartMinimized Then - $g_bTorConfig_StartMinimized = False - IniDelete($CONFIG_INI, "startup", "start_minimized") - GUICtrlSetState($g_idMainGUI_MenuStartMinimized, $GUI_UNCHECKED) - Else - $g_bTorConfig_StartMinimized = True - IniWrite($CONFIG_INI, "startup", "start_minimized", "true") - GUICtrlSetState($g_idMainGUI_MenuStartMinimized, $GUI_CHECKED) - EndIf -EndFunc - -Func GUI_Reset() - GUICtrlSetData($g_idMainGUI_Port, $g_sTorConfig_Port & ' (As defined in the settings)') - GUICtrlSetData($g_idMainGUI_TorPID, "Not running") - TrayItemSetText($g_idTrayToggleTor, "Start Tor") - GUICtrlSetData($g_idMainGUI_ToggleButton, "Start") -EndFunc -#EndRegion GUI Handlers - -#Region Event Handler Functions -Func Handle_MultipleInstance() - If _Singleton(StringReplace(@ScriptFullPath, '\', '/'), 1) = 0 Then - Local $iMsgBoxParams = $MB_ICONWARNING + $MB_YESNO + $MB_DEFBUTTON2 - Local $sMsgBoxMsg = "ProxAllium seems to be already running, do you still want to create a new instance?" - Local $iUserChoice = MsgBox($iMsgBoxParams, "ProxAllium is already running!", $sMsgBoxMsg) - If $iUserChoice = $IDYES Then Return - Exit - EndIf -EndFunc - -Func Handle_TorOutput() - Local $aCallbackFuncs = [Handle_OpenSockets, Handle_Bootstrap, Handle_WarningAndError] - Local $sPartialTorOutput = "" - Local $aPartialTorOutput[0] - Local $bRemoveCallback, $sRemovalList - While IsTorRunning() ; Loop until Tor is dead - Sleep($g_iOutputPollInterval) ; Don't kill the CPU - $sPartialTorOutput = StdoutRead($g_aTorProcess[$TOR_PROCESS_PID]) - If $sPartialTorOutput = "" Then ContinueLoop - _GUICtrlEdit_AppendText($g_hTorOutput, $sPartialTorOutput) - $aPartialTorOutput = StringSplit(StringStripWS($sPartialTorOutput, $STR_STRIPTRAILING), @CRLF, $STR_ENTIRESPLIT) - For $iLine = 1 To $aPartialTorOutput[0] - For $iFunc = 0 To UBound($aCallbackFuncs) - 1 - $bRemoveCallback = $aCallbackFuncs[$iFunc](StringSplit($aPartialTorOutput[$iLine], ' ')) - If $bRemoveCallback Then $sRemovalList &= $iFunc & ';' - Next - If Not $sRemovalList = "" Then - _ArrayDelete($aCallbackFuncs, StringTrimRight($sRemovalList, 1)) - $sRemovalList = "" - EndIf - Next - WEnd - Local $iExitCode = _Process_GetExitCode($g_aTorProcess[$TOR_PROCESS_HANDLE]) - GUI_SetStatus("Stopped") - Local $bUnexpected = Not IsMgcNumPresent($GUI_DISABLE, GUICtrlGetState($g_idMainGUI_ToggleButton)) - If $bUnexpected Then - _Tor_Stop($g_aTorProcess) - GUI_LogOut("Tor has exited unexpectedly with exit code: " & $iExitCode) - TrayTip("Tor exited unexpectedly!", "Tor has exited with exit code: " & $iExitCode, 10, $TIP_ICONEXCLAMATION) - Else - GUICtrlSetState($g_idMainGUI_ToggleButton, $GUI_ENABLE) - GUI_LogOut("Tor exited with exit code: " & $iExitCode) - TrayTip("Tor has exited", "Tor has exited with exit code: " & $iExitCode, 10, $TIP_ICONASTERISK + $TIP_NOSOUND) - EndIf - GUI_Reset() -EndFunc - -Func Handle_WarningAndError(ByRef $aTorOutput) - If $aTorOutput[0] < 4 Then Return - If ($aTorOutput[4] = '[warn]') Or ($aTorOutput[3] = '[err]') Then - If $aTorOutput[5] = "Path" Then Return - GUI_LogOut(_ArrayToString($aTorOutput, ' ', 5)) - EndIf -EndFunc - -Func Handle_OpenSockets(ByRef $aTorOutput) - If ($aTorOutput[0] < 9) Or ($aTorOutput[5] <> "Opening") Then Return - Local Enum $IP, $PORT - Local $aAddress = StringSplit($aTorOutput[($aTorOutput[6] = "HTTP" ? 10 : 9)], ':', $STR_NOCOUNT) - Local Static $bSocksInit = False - Local Static $bControlInit = False - Switch $aTorOutput[6] - Case "Socks" - GUICtrlSetData($g_idMainGUI_Port, $aAddress[$PORT]) - $bSocksInit = True - Case "HTTP" - _GUICtrlEdit_AppendText($g_idMainGUI_Port, ' (HTTP Tunnel Port: ' & $aAddress[$PORT] & ')') - Case "Control" - Core_InitConnectionToController($g_sTorConfig_ControlPort) - $bControlInit = True - EndSwitch - If $bSocksInit And $bControlInit Then - $bSocksInit = False - $bControlInit = False - Return True - EndIf -EndFunc - -Func Handle_Bootstrap(ByRef $aTorOutput) - If Not ($aTorOutput[0] >= 7 And $aTorOutput[5] = "Bootstrapped") Then Return - Local $iPercentage = Int($aTorOutput[6]) - If $iPercentage = 0 Then GUI_LogOut("Trying to build a circuit, please wait...") - Local $sText = _ArrayToString($aTorOutput, ' ', 5) - GUI_SetStatus($sText) - GUI_LogOut($sText) - If $iPercentage = 100 Then - GUI_SetStatus("Running") - GUI_LogOut("Successfully built a circuit, Tor is now ready for use!") - TrayTip("Tor is ready", "Tor has successfully built a circuit, you can now start using the proxy!", 10, $TIP_ICONASTERISK) - Return True - EndIf -EndFunc -#EndRegion Misc. Functions - -#Region Core Functions -Func Core_WaitForExit($sLogText = "") - If Not $sLogText = "" Then GUI_LogOut($sLogText) - GUI_LogOut("ProxAllium now ready to exit...") - GUI_LogOut("Close the window by clicking X to exit ProxAllium!") - Core_Idle() -EndFunc - -Func Core_Idle() - Do - If IsTorRunning() Then Handle_TorOutput() - Sleep($g_iOutputPollInterval) - Until False -EndFunc - -Func Core_GenTorrc() - Local $hTorrc = FileOpen($g_sTorConfigFile, $FO_APPEND + $FO_CREATEPATH) - If @error Then Return SetError(1, 0, False) - FileSetPos($hTorrc, 0, $FILE_BEGIN) - Local $aTorrc = FileReadToArray($hTorrc) - Local $sCustomConfig - If Not @error Then - For $iLine = 0 To @extended - 1 - If StringLeft($aTorrc[$iLine], 2) = '#~' Then - $sCustomConfig = _ArrayToString($aTorrc, @CRLF, $iLine + 1) - ExitLoop - EndIf - Next - EndIf - FileSetPos($hTorrc, 0, $FILE_BEGIN) - FileWriteLine($hTorrc, '## Configuration file automatically generated by ProxAllium') - FileWriteLine($hTorrc, '## This file was generated on ' & _Now()) - FileWriteLine($hTorrc, "") - FileWriteLine($hTorrc, '## Open SOCKS proxy on the following port') - FileWriteLine($hTorrc, 'SOCKSPort ' & $g_sTorConfig_Port) - FileWriteLine($hTorrc, "") - If Not $g_sTorConfig_TunnelPort = "" Then - FileWriteLine($hTorrc, '## HTTP Tunnel Proxy') - FileWriteLine($hTorrc, "HTTPTunnelPort " & $g_sTorConfig_TunnelPort) - FileWriteLine($hTorrc, "") - EndIf - FileWriteLine($hTorrc, '## Open the Tor controller interface on the following port') - FileWriteLine($hTorrc, 'ControlPort ' & $g_sTorConfig_ControlPort) - FileWriteLine($hTorrc, 'HashedControlPassword ' & _Tor_GenHash($g_sTorConfig_ControlPass)[0]) - FileWriteLine($hTorrc, "") - If $g_bTorConfig_OnlyLocalhost Then - FileWriteLine($hTorrc, '## Only accept connections from localhost') - FileWriteLine($hTorrc, 'SOCKSPolicy accept 127.0.0.1') - FileWriteLine($hTorrc, 'SOCKSPolicy accept6 [::1]') - FileWriteLine($hTorrc, 'SOCKSPolicy reject *') - FileWriteLine($hTorrc, "") - EndIf - FileWriteLine($hTorrc, '## GeoIP Files') - FileWriteLine($hTorrc, 'GeoIPFile ' & $g_sTorGeoIPv4File) - FileWriteLine($hTorrc, 'GeoIPv6File ' & $g_sTorGeoIPv6File) - FileWriteLine($hTorrc, "") - FileWriteLine($hTorrc, '## Data Directory') - FileWriteLine($hTorrc, 'DataDirectory ' & $g_sTorDataDirPath) - FileWriteLine($hTorrc, "") - If Not $g_sTorConfig_ProxyType = "" Then - FileWriteLine($hTorrc, "## Proxy Settings for Tor (not Tor's proxy settings)") - Local $sProxySettings - Switch $g_sTorConfig_ProxyType - Case "http" - $sProxySettings &= "HTTPProxy " & $g_sTorConfig_ProxyHost - $sProxySettings &= ($g_sTorConfig_ProxyPort = "") ? "" : (':' & $g_sTorConfig_ProxyPort) - $sProxySettings &= @CRLF - If Not $g_sTorConfig_ProxyUser = "" Then $sProxySettings &= "HTTPProxyAuthenticator " & $g_sTorConfig_ProxyUser & ':' & $g_sTorConfig_ProxyPass & @CRLF - - Case "https" - $sProxySettings &= "HTTPSProxy " & $g_sTorConfig_ProxyHost - $sProxySettings &= ($g_sTorConfig_ProxyPort = "") ? "" : (':' & $g_sTorConfig_ProxyPort) - $sProxySettings &= @CRLF - If Not $g_sTorConfig_ProxyUser = "" Then $sProxySettings &= "HTTPSProxyAuthenticator " & $g_sTorConfig_ProxyUser & ':' & $g_sTorConfig_ProxyPass & @CRLF - - Case "socks4" - $sProxySettings &= "Socks4Proxy " & $g_sTorConfig_ProxyHost - $sProxySettings &= ($g_sTorConfig_ProxyPort = "") ? "" : (':' & $g_sTorConfig_ProxyPort) - $sProxySettings &= @CRLF - - Case "socks5" - $sProxySettings &= "Socks5Proxy " & $g_sTorConfig_ProxyHost - $sProxySettings &= ($g_sTorConfig_ProxyPort = "") ? "" : (':' & $g_sTorConfig_ProxyPort) - $sProxySettings &= @CRLF - If Not $g_sTorConfig_ProxyUser = "" Then $sProxySettings &= "Socks5ProxyUsername " & $g_sTorConfig_ProxyUser & @CRLF - If Not $g_sTorConfig_ProxyPass = "" Then $sProxySettings &= "Socks5ProxyPassword " & $g_sTorConfig_ProxyPass & @CRLF - - Case Else - $sProxySettings &= '## Unknown proxy type detected!? Cannot generate config :(' - EndSwitch - FileWriteLine($hTorrc, $sProxySettings) - FileWriteLine($hTorrc, "") - EndIf - If Not $g_sTorConfig_ExitNodeCC = "" Then - FileWriteLine($hTorrc, '## Country of the Exit Node') - FileWriteLine($hTorrc, 'ExitNodes {' & $g_sTorConfig_ExitNodeCC & '}') - FileWriteLine($hTorrc, "StrictNodes 1") - FileWriteLine($hTorrc, "") - EndIf - If $g_bTorConfig_BridgesEnabled Then - FileWriteLine($hTorrc, '## Bridges') - FileWriteLine($hTorrc, 'UseBridges 1') - If FileExists($g_sObfs4Path) Then - FileWriteLine($hTorrc, 'ClientTransportPlugin obfs2,obfs3,obfs4,scramblesuit exec ' & $g_sObfs4Path) - EndIf - If FileExists($g_sSnowflakePath) Then - ; https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/-/tree/main/client - FileWriteLine($hTorrc, 'ClientTransportPlugin snowflake exec ' & $g_sSnowflakePath & ' ' & $g_sSnowflakeArgs) - EndIf - Local $aBridges = StringSplit(StringStripCR(GUICtrlRead($g_idBridgesEdit)), @LF) - For $iBridge = 1 To $aBridges[0] - If StringIsSpace($aBridges[$iBridge]) Then ContinueLoop ; Skip blank lines - If StringLeft($aBridges[$iBridge], 1) = '#' Then ContinueLoop ; Skip comments - FileWriteLine($hTorrc, 'Bridge ' & $aBridges[$iBridge]) - Next - FileWriteLine($hTorrc, "") - EndIf - FileWriteLine($hTorrc, '###########################################################') - FileWriteLine($hTorrc, '###### STORE YOUR CUSTOM CONFIGURATION ENTRIES BELOW ######') - FileWriteLine($hTorrc, '##### THEY WILL BE PRESERVED ACROSS CHANGES IN CONFIG #####') - FileWriteLine($hTorrc, '###########################################################') - FileWriteLine($hTorrc, '#~ I (this line) am used to identify the start of custom entries, so please do not touch me :)') - FileWriteLine($hTorrc, $sCustomConfig) - FileSetEnd($hTorrc) - FileClose($hTorrc) -EndFunc - -Func Core_InitConnectionToController($iPort) - _Tor_Controller_Connect($g_aTorProcess, $g_sTorConfig_ControlPort) - If @error Then - GUI_LogOut('Failed to connect to Tor contoller! ' & StringFormat('(Error Code: %i and Extended Code: %i)', @error, @extended)) - Return SetError(1, 0, False) - EndIf - _Tor_Controller_Authenticate($g_aTorProcess, $TOR_CONTROLLER_AUTH_HASH, $g_sTorConfig_ControlPass) - If @error Then - GUI_LogOut('Failed to authenticate with Tor contoller! ' & StringFormat('(Error Code: %i and Extended Code: %i)', @error, @extended)) - Return SetError(2, 0, False) - EndIf - GUI_LogOut('Successfully connected to the controller!') - _Tor_Controller_TakeOwnership($g_aTorProcess) - If @error Then - GUI_LogOut('Failed to take ownership of Tor instance ' & StringFormat('(Error Code: %i and Extended Code: %i)', @error, @extended)) - SetExtended(1, True) - EndIf - Return True -EndFunc - -Func Core_SetupTor($bIntro = True) - If Not IsDeclared("bIntro") = $DECLARED_LOCAL Then $bIntro = False - - Local $iMsgBoxFlags, $sMsgBoxTitle, $sMsgBoxMsg - $iMsgBoxFlags = $MB_ICONINFORMATION + $MB_YESNO - $sMsgBoxTitle = "Setup Tor" - If $bIntro Then - $sMsgBoxMsg = "It looks Tor is not configured properly in ProxAllium yet, most likely this is your first run. Do not worry, ProxAllium can guide you through the process!" & @CRLF & @CRLF - EndIf - $sMsgBoxMsg &= "Do you want to continue with the setup process?" - If MsgBox($iMsgBoxFlags, $sMsgBoxTitle, $sMsgBoxMsg) = $IDNO Then Return False - - Local $bUseTB = False - $iMsgBoxFlags = $MB_ICONQUESTION + $MB_YESNO - $sMsgBoxMsg = "Do you have Tor Browser installed?" - If MsgBox($iMsgBoxFlags, $sMsgBoxTitle, $sMsgBoxMsg) = $IDYES Then - $bUseTB = True - Else - $iMsgBoxFlags = $MB_ICONQUESTION + $MB_YESNO - $sMsgBoxMsg = "It is also possible to just use Tor, but I recommend installing the Tor Browser as it automatically updates your copy of Tor when you update the browser and it also adds support for bridges." & @CRLF - $sMsgBoxMsg &= @CRLF & 'Do you want to install Tor Browser and use Tor from it? Choose "No" to continue with only Tor.' - $bUseTB = MsgBox($iMsgBoxFlags, $sMsgBoxTitle, $sMsgBoxMsg) = $IDYES - If $bUseTB Then MsgBox($MB_ICONINFORMATION, $sMsgBoxTitle, "Please download and install the latest version of Tor Browser and click OK to continue.") - EndIf - - Local $sTorFolder, $bFoundTor = False - If $bUseTB Then - Do - $sTorFolder = FileSelectFolder("Please select the folder containing Tor Browser", "", 0, @DesktopDir & '\Tor Browser') - If @error Then Return False - $sTorFolder = $sTorFolder & '\Browser\TorBrowser\Tor' - If FileExists($sTorFolder & '\tor.exe') Then - $bFoundTor = True - EndIf - If Not $bFoundTor Then MsgBox($MB_ICONERROR, "Tor not found", 'Cannot find tor.exe in this folder, please try again and make sure you have selected the installation directory (and not the "Browser" folder inside it).') - Until $bFoundTor - Else - $iMsgBoxFlags = $MB_ICONQUESTION + $MB_YESNO - $sMsgBoxMsg = 'Do you want to download Tor? If you already have a copy of Tor in your computer, then choose "No".' - If MsgBox($iMsgBoxFlags, $sMsgBoxTitle, $sMsgBoxMsg) = $IDYES Then - $iMsgBoxFlags = $MB_ICONINFORMATION - $sMsgBoxMsg = 'The URL (https://www.torproject.org/download/tor) for the page which contains the link to download the "Tor Expert Bundle" has been copied to your clipboard.' & @CRLF - $sMsgBoxMsg &= @CRLF & "Please download it and extract the files to a permanent location (a sub-folder in ProxAllium's folder should be perfect), Click OK when you are done." - ClipPut('https://www.torproject.org/download/tor') - MsgBox($iMsgBoxFlags, $sMsgBoxTitle, $sMsgBoxMsg) - EndIf - Do - $sTorFolder = FileSelectFolder("Please select the folder containing Tor", "") - If @error Then Return False - If FileExists($sTorFolder & '\Tor\tor.exe') Then - $sTorFolder = $sTorFolder & '\Tor' - $bFoundTor = True - ElseIf FileExists($sTorFolder & '\tor.exe') Then - $bFoundTor = True - EndIf - If Not $bFoundTor Then MsgBox($MB_ICONERROR, "Tor not found", "Cannot find tor.exe in this folder, please make sure you have selected the right folder and try again.") - Until $bFoundTor - EndIf - - If $bFoundTor Then - $g_sTorPath = $sTorFolder & '\tor.exe' - IniWrite($CONFIG_INI, "tor", "path", $g_sTorPath) - If $bUseTB Then - Local $sObfs4 = $sTorFolder & '\PluggableTransports\obfs4proxy.exe' - If FileExists($sObfs4) Then - $g_sObfs4Path = $sObfs4 - IniWrite($CONFIG_INI, "tor", "obfs4_path", $g_sObfs4Path) - EndIf - Local $sSnowflake = $sTorFolder & '\PluggableTransports\snowflake-client.exe' - If FileExists($sSnowflake) Then - $g_sSnowflakePath = $sSnowflake - IniWrite($CONFIG_INI, "tor", "snowflake_path", $g_sSnowflakePath) - IniWrite($CONFIG_INI, "tor", "snowflake_args", $g_sSnowflakeArgs) - - Local $hBridges = FileOpen($g_sTorConfig_BridgesPath, $FO_APPEND + $FO_CREATEPATH) - If $hBridges <> -1 Then - FileWriteLine($hBridges, '# Uncomment the line below to use snowflake bridge transport') - FileWriteLine($hBridges, '# snowflake 192.0.2.3:1') - FileClose($hBridges) - - GUIDelete($g_hBridgesGUI) - GUI_CreateBridges() - EndIf - EndIf - EndIf - EndIf - - $iMsgBoxFlags = $MB_ICONINFORMATION - $sMsgBoxMsg = 'Setup process is complete!' - MsgBox($iMsgBoxFlags, $sMsgBoxTitle, $sMsgBoxMsg) - - Return $bFoundTor -EndFunc - -Func IsTorRunning() - Return ProcessExists($g_aTorProcess[$TOR_PROCESS_PID]) <> 0 -EndFunc -#EndRegion Core Functions - -#Region Tor Functions -Func Tor_Initialize() - GUI_SetStatus("Initializing Tor...") - GUICtrlSetData($g_idMainGUI_TorVersion, "Detecting...") - Local $aTorVersion = _Tor_SetPath($g_sTorPath) - Local $iError = @error - GUI_SetStatus() - If Not $iError Then - $g_aTorVersion = $aTorVersion - GUI_LogOut("Detected Tor version: " & $g_aTorVersion[$TOR_VERSION]) - GUICtrlSetData($g_idMainGUI_TorVersion, $g_aTorVersion[$TOR_VERSION]) - If Not FileExists($g_sTorConfigFile) Then - GUI_LogOut("Cannot find Tor configuration file, generating one now... ", False) - Core_GenTorrc() - If @error Then Core_WaitForExit("Failed to create configuration file!") - GUI_LogOut("Successfully generated Tor configuration file!") - EndIf - Return True - EndIf - GUICtrlSetData($g_idMainGUI_TorVersion, '...') - Switch $iError - Case $TOR_ERROR_GENERIC - GUI_LogOut("Cannot find Tor!") - If Core_SetupTor() Then - Local $vReturn = Tor_Initialize() - Return SetError(@error, 0, $vReturn) - EndIf - Case $TOR_ERROR_VERSION - GUI_LogOut("Unable to identify Tor's version!") - EndSwitch - Return SetError($iError) -EndFunc - -Func Tor_Start() - GUICtrlSetState($g_idMainGUI_ToggleButton, $GUI_DISABLE) - GUI_SetStatus("Starting Tor...") - GUI_LogOut("Starting Tor... ", False) - Local $aTorProcess = _Tor_Start($g_sTorConfigFile) - Local $iError = @error - GUICtrlSetState($g_idMainGUI_ToggleButton, $GUI_ENABLE) - If $iError Then - GUI_SetStatus() - Switch $iError - Case $TOR_ERROR_PROCESS - GUI_LogOut("Unable to start Tor!") - - Case $TOR_ERROR_CONFIG - GUI_LogOut("Invalid Tor configuration, please check your custom entries.") - EndSwitch - Return SetError($iError, 0, False) - EndIf - $g_aTorProcess = $aTorProcess - TrayItemSetText($g_idTrayToggleTor, "Stop Tor") - GUICtrlSetData($g_idMainGUI_ToggleButton, "Stop") - GUI_SetStatus("Waiting for Tor...") - GUI_LogOut("Started Tor with PID: " & $g_aTorProcess[$TOR_PROCESS_PID]) - GUICtrlSetData($g_idMainGUI_TorPID, $g_aTorProcess[$TOR_PROCESS_PID]) - GUICtrlSetData($g_idTorOutput, "") ; Reset the Tor Output - Return True -EndFunc - -Func Tor_Stop() - GUICtrlSetState($g_idMainGUI_ToggleButton, $GUI_DISABLE) - GUI_LogOut("Trying to stop Tor... ", False) - GUI_SetStatus("Stopping Tor...") - If Not ProcessExists($g_aTorProcess[$TOR_PROCESS_PID]) Then - GUI_LogOut("but Tor is already stopped!") - Return True - EndIf - _Tor_Stop($g_aTorProcess) - If @error Then - Local $iError = @extended - GUI_LogOut("Failed to stop Tor (Error Code: " & $iError & ')') - Return SetError($iError, 0, False) - EndIf - GUI_LogOut("Successfully stopped Tor!") - Return True -EndFunc - -Func Tor_Toggle() - If IsTorRunning() Then - Tor_Stop() - Else - Tor_Start() - EndIf -EndFunc -#EndRegion Tor Functions - -#EndRegion Functions diff --git a/README.adoc b/README.adoc deleted file mode 100644 index b0f7958..0000000 --- a/README.adoc +++ /dev/null @@ -1,5 +0,0 @@ -= ProxAllium - -image:https://img.shields.io/badge/license-MIT-blue.svg[link="https://raw.githubusercontent.com/DcodingTheWeb/ProxAllium/master/LICENSE"] image:https://img.shields.io/github/issues/DcodingTheWeb/ProxAllium.svg[link="https://github.com/DcodingTheWeb/ProxAllium/issues"] image:https://img.shields.io/github/release/DcodingTheWeb/ProxAllium/all.svg[link="https://github.com/DcodingTheWeb/ProxAllium/releases"] image:https://img.shields.io/badge/Chat-on%20Gitter-%2346BC99[alt=Chat on Gitter,link=https://gitter.im/ProxAllium/chat] - -Tor Proxy Bundle for Windows. ProxAllium is an open-source wrapper for Tor. Visit the https://proxallium.tuxfamily.org/[website] for more details, don't forget to check the https://proxallium.tuxfamily.org/screenshots[screenshots]! diff --git a/README.md b/README.md new file mode 100644 index 0000000..3733498 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# ProxAllium + +This is a total C rewrite of the older legacy ProxAllium which is written in AutoIt. The goal is make ProxAllium available in both Linux and Windows with a CLI and GUI interface. diff --git a/Tor.au3 b/Tor.au3 deleted file mode 100644 index 1128860..0000000 --- a/Tor.au3 +++ /dev/null @@ -1,445 +0,0 @@ -#include-once -#include -#include -#include -#include "ProcessEx.au3" - -#AutoIt3Wrapper_Au3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w- 4 -w 5 -w 6 -w- 7 - -; #INDEX# ======================================================================================================================= -; Title ............: Tor UDF. -; AutoIt Version ...: 3.3.14.1 -; Description ......: UDF for Tor, meant to be used by ProxAllium. Not the best Tor UDF around ;) -; Author(s) ........: Damon Harris (TheDcoder). -; This UDF Uses ....: Process UDF (439a393) - https://git.io/vXmF6 -; Links ............: GitHub - https://github.com/DcodingTheWeb/ProxAllium/blob/master/Tor.au3 -; =============================================================================================================================== - -; #CURRENT# ===================================================================================================================== -; _Tor_CheckVersion - Check the version of Tor. -; _Tor_Controller_Authenticate - Authenticate with the Tor controller -; _Tor_Controller_CheckReplyForError - Check for errors in a reply/response from the controller -; _Tor_Controller_Connect - Connect to Tor's TCP controller interface -; _Tor_Controller_SendRaw - Send raw commands to the controller interface -; _Tor_Controller_TakeOwnership - Take ownership of the Tor process (Tor closes if it loses the connection) -; _Tor_Controller_WaitForMsg - Wait for a message to arrive completely and get it -; _Tor_GenHash - Generate a hash for use with Tor -; _Tor_Find - Lists the tor executables and geoip files. -; _Tor_SetPath - Sets Tor.exe's path, it will be used by the UDF in the rest of the functions. -; _Tor_Start - Starts Tor -; _Tor_Stop - Stops Tor -; _Tor_SwitchCircuit - Switch Tor to clean circuits so new application requests don't share any circuits with old ones -; _Tor_VerifyConfig - Check if the configuration is valid. -; =============================================================================================================================== - -; #CONSTANTS# =================================================================================================================== -Global Const $TOR_ERROR_GENERIC = 1 ; Reserved for generic errors. -Global Const $TOR_ERROR_PROCESS = 2 ; Error related to Tor.exe's process. -Global Const $TOR_ERROR_VERSION = 3 ; Error related to version. -Global Const $TOR_ERROR_CONFIG = 4 ; Error related to configuration. -Global Const $TOR_ERROR_NETWORK = 5 ; Error related to networking (TCP). -Global Const $TOR_ERROR_CONTROLLER = 6 ; Error related to the Tor controller. - -Global Enum $TOR_VERSION, $TOR_VERSION_NUMBER, $TOR_VERSION_GIT ; Associated with $aTorVersion returned by _Tor_CheckVersion -Global Enum $TOR_PROCESS_PID, $TOR_PROCESS_HANDLE, $TOR_PROCESS_SOCKET ; Associated with $aTorProcess returned by _Tor_Start -Global Enum $TOR_CONTROLLER_AUTH_NONE, $TOR_CONTROLLER_AUTH_HASH ; Methods of authentication with Tor controller -Global Enum $TOR_FIND_VERSION, $TOR_FIND_PATH ; Associated with $aList returned by _Tor_Find -Global Enum $TOR_FIND_TORLIST, $TOR_FIND_GEOIP, $TOR_FIND_GEOIP6 ; Associated with arrays found inside $aList returned by _Tor_Find -; =============================================================================================================================== - -; #VARIABLES# =================================================================================================================== -Global $g__sTorPath = "" ; Path to Tor.exe -; =============================================================================================================================== - -TCPStartup() -OnAutoItExitRegister(__Tor_OnExitTCPShutdown) - -; #FUNCTION# ==================================================================================================================== -; Name ..........: _Tor_CheckVersion -; Description ...: Check the version of Tor. -; Syntax ........: _Tor_CheckVersion([$sTorPath = $g__sTorPath]) -; Parameters ....: $sTorPath - [optional] Path of Tor's executable. Default is $g__sTorPath. -; Return values .: Success: $aTorVersion with 3 elements: -; $aTorVersion[$TOR_VERSION] - Will contain the full version string, see remarks for the format. -; $aTorVersion[$TOR_VERSION_NUMBER] - Will contain the version number in this format: x.x.x.x -; $aTorVersion[$TOR_VERSION_GIT] - Will contain Git's truncated hash of the commit. -; Failure: False and @error set to: -; $TOR_ERROR_PROCESS - If it is an invalid Tor path. -; $TOR_ERROR_VERSION - If unable to determine version, @extended is set to StringRegExp's @error. -; Author ........: Damon Harris (TheDcoder) -; Remarks .......: $TOR_VERSION Format : x.x.x.x (git-a1b2c3d4e5f6g7h8) -; Example: 0.2.9.10 (git-1f6c8eda0073f464) -; The git hash may not be present at all times. -; Example .......: No -; =============================================================================================================================== -Func _Tor_CheckVersion($sTorPath = $g__sTorPath) - Local $sOutput = _Process_RunCommand($PROCESS_RUNWAIT, $sTorPath & ' --version') - If @error Then Return SetError($TOR_ERROR_PROCESS, @error, False) - Local $aTorVersion[3] - Local $aRegEx = StringRegExp($sOutput, '(\d*\.\d*\.\d*\.\d*)(?: \(git-([a-z0-9]{16})\))?', $STR_REGEXPARRAYFULLMATCH) - If @error Then Return SetError($TOR_ERROR_VERSION, @error, False) - $aTorVersion[$TOR_VERSION] = $aRegEx[0] - $aTorVersion[$TOR_VERSION_NUMBER] = $aRegEx[1] - If UBound($aRegEx) = 3 Then $aTorVersion[$TOR_VERSION_GIT] = $aRegEx[2] - Return $aTorVersion -EndFunc - -; #FUNCTION# ==================================================================================================================== -; Name ..........: _Tor_Controller_Authenticate -; Description ...: Authenticate with the Tor controller -; Syntax ........: _Tor_Controller_Authenticate(Byref $aTorProcess[, $iMethod = $TOR_CONTROLLER_AUTH_NONE[, $vPassword = ""]]) -; Parameters ....: $aTorProcess - [in/out] $aTorProcess from _Tor_Start. -; $iMethod - [optional] One of the $TOR_CONTROLLER_AUTH constants. Default is $TOR_CONTROLLER_AUTH_NONE. -; $vPassword - [optional] Password. Default is "" (None). -; Return values .: Success: True -; Failure: @error is set to: -; $TOR_ERROR_NETWORK - If there was a network error, @extended is set to TCPSend or TCPRecv's error. -; $TOR_ERROR_CONTROLLER - If Tor replied with an unexpected response, the response string is returned. -; Author ........: Damon Harris (TheDcoder) -; Remarks .......: This should be the second step after _Tor_Controller_Connect -; Example .......: No -; =============================================================================================================================== -Func _Tor_Controller_Authenticate(ByRef $aTorProcess, $iMethod = $TOR_CONTROLLER_AUTH_NONE, $vPassword = "") - Local $sRawCommand = "AUTHENTICATE" - If $iMethod = $TOR_CONTROLLER_AUTH_HASH Then $sRawCommand &= ' "' & $vPassword & '"' - _Tor_Controller_SendRaw($aTorProcess, $sRawCommand) - If @error Then Return SetError($TOR_ERROR_NETWORK, @extended, False) - Local $sResponse = _Tor_Controller_WaitForMsg($aTorProcess) - If @error Then Return SetError($TOR_ERROR_NETWORK, @extended, False) - _Tor_Controller_CheckReplyForError($sResponse) - If Not @error Then Return True - Return SetError($TOR_ERROR_CONTROLLER, 0, $sResponse) -EndFunc - -; #FUNCTION# ==================================================================================================================== -; Name ..........: _Tor_Controller_CheckReplyForError -; Description ...: Check for errors in a reply/response from the controller -; Syntax ........: _Tor_Controller_CheckReplyForError($sReply) -; Parameters ....: $sReply - The reply or response from the controller server. -; Return values .: Success: True -; Failure: False and @error set to $TOR_ERROR_GENERIC, @extended is set to 1 if error is fatal. -; Special: @extended is set to 2 and @error is not set, this happens if the status is unknown. -; Author ........: Damon Harris (TheDcoder) -; Example .......: No -; =============================================================================================================================== -Func _Tor_Controller_CheckReplyForError($sReply) - Local $aReply = StringSplit($sReply, ' ') - Local $sStatusCode = $aReply[1] - Switch StringLeft($sStatusCode, 1) - Case "2" ; All OK - Return True - Case "4" ; Temporary Negative (Non-fatal error) - Return SetError($TOR_ERROR_GENERIC, 0, False) - Case "5" ; Permanent Negetive (Fatal error) - Return SetError($TOR_ERROR_GENERIC, 1, False) - Case Else ; Unknown error status (error???) - Return SetExtended(2, False) - EndSwitch -EndFunc - -; #FUNCTION# ==================================================================================================================== -; Name ..........: _Tor_Controller_Connect -; Description ...: Connect to Tor's TCP controller interface -; Syntax ........: _Tor_Controller_Connect(Byref $aTorProcess, $iPort[, $sAddress = '127.0.0.1']) -; Parameters ....: $aTorProcess - [in/out] $aTorProcess from _Tor_Start. -; $iPort - The port where the controller interface is listening. -; $sAddress - [optional] IP Address of the host. Default is '127.0.0.1'. -; Return values .: Success: True -; Failure: False and @error is set to TCPConnect's @error -; Author ........: Damon Harris (TheDcoder) -; Remarks .......: Autentication should be done before beginning the communication -; Example .......: No -; =============================================================================================================================== -Func _Tor_Controller_Connect(ByRef $aTorProcess, $iPort, $sAddress = '127.0.0.1') - Local $iSocket = TCPConnect($sAddress, $iPort) - If @error Then Return SetError(@error, 0, False) - $aTorProcess[$TOR_PROCESS_SOCKET] = $iSocket - Return True -EndFunc - -; #FUNCTION# ==================================================================================================================== -; Name ..........: _Tor_Controller_SendRaw -; Description ...: Send raw commands to the controller interface -; Syntax ........: _Tor_Controller_SendRaw($aTorProcess, $sRawCommand[, $bAutoCRLF = True]) -; Parameters ....: $aTorProcess - $aTorProcess from _Tor_Start. -; $sRawCommand - The string containing the raw command, CRLF is optional by default. -; $bAutoCRLF - [optional] If True, CRLF is automatically appended before sending the command. Default is True. -; Return values .: Success: True -; Failure: False and @error is set to $TOR_ERROR_NETWORK & @extended is set to TCPSend's @error -; Author ........: Damon Harris (TheDcoder) -; Example .......: No -; =============================================================================================================================== -Func _Tor_Controller_SendRaw(ByRef $aTorProcess, $sRawCommand, $bAutoCRLF = True) - If $bAutoCRLF Then $sRawCommand &= @CRLF - TCPSend($aTorProcess[$TOR_PROCESS_SOCKET], $sRawCommand) - If @error Then Return SetError($TOR_ERROR_NETWORK, @error, False) - Return True -EndFunc - -; #FUNCTION# ==================================================================================================================== -; Name ..........: _Tor_Controller_TakeOwnership -; Description ...: Take ownership of the Tor process (Tor closes if it loses the connection) -; Syntax ........: _Tor_Controller_TakeOwnership($aTorProcess) -; Parameters ....: $aTorProcess - [in/out] $aTorProcess from _Tor_Start. -; Return values .: Success: True -; Failure: False, @error set to: -; $TOR_ERROR_GENERIC - If controller sent a reply indicating an error and @extended is -; set to _Tor_Controller_CheckReplyForError's @extended -; $TOR_ERROR_NETWORK - If a network error occurs, @extended is set to TCPSend/TCPRecv's @error -; Author ........: Damon Harris (TheDcoder) -; Example .......: No -; =============================================================================================================================== -Func _Tor_Controller_TakeOwnership($aTorProcess) - _Tor_Controller_SendRaw($aTorProcess, 'TAKEOWNERSHIP') - If @error Then Return SetError($TOR_ERROR_NETWORK, @extended, False) - Local $sReply = _Tor_Controller_WaitForMsg($aTorProcess) - If @error Then Return SetError($TOR_ERROR_NETWORK, @extended, False) - _Tor_Controller_CheckReplyForError($sReply) - If @error Then Return SetError($TOR_ERROR_GENERIC, @extended, False) - Return True -EndFunc - -; #FUNCTION# ==================================================================================================================== -; Name ..........: _Tor_Controller_WaitForMsg -; Description ...: Wait for a message to arrive completely and get it -; Syntax ........: _Tor_Controller_WaitForMsg(Byref $aTorProcess[, $iTimeout = 0[, $bTrimCRLF = True]]) -; Parameters ....: $aTorProcess - [in/out] $aTorProcess from _Tor_Start. -; $iTimeout - [optional] Timeout in milliseconds. Default is 0 (no timeout). -; $bTrimCRLF - [optional] Trim the trailing CRLF in the message. Default is True. -; Return values .: Success: $sMessage -; Failure: $sMessage (can be blank or contain partial content) and @error is set to: -; $TOR_ERROR_NETWORK - If TCPRecv set an error, @extended is set to TCPRecv's @error -; $TOR_ERROR_GENERIC - If $iTimeout is reached -; Author ........: Damon Harris (TheDcoder) -; Example .......: No -; =============================================================================================================================== -Func _Tor_Controller_WaitForMsg(ByRef $aTorProcess, $iTimeout = 0, $bTrimCRLF = True) - Local $sMessage - If $iTimeout > 0 Then Local $hTimer = TimerInit() - Do - $sMessage &= TCPRecv($aTorProcess[$TOR_PROCESS_SOCKET], 2) - If @error Then Return SetError($TOR_ERROR_NETWORK, @error, $sMessage) - If ($iTimeout > 0) And (TimerDiff($hTimer) >= $iTimeout) Then Return SetError($TOR_ERROR_GENERIC, 0, $sMessage) - Sleep(10) - Until (StringRight($sMessage, 2) = @CRLF) - Return ($bTrimCRLF ? StringTrimRight($sMessage, 2) : $sMessage) -EndFunc - -; #FUNCTION# ==================================================================================================================== -; Name ..........: _Tor_Find -; Description ...: Lists the tor executables and geoip files. -; Syntax ........: _Tor_Find($vFolders) -; Parameters ....: $vFolders - $vFolders to search. Can be an array or a string delimited by a pipe charecter (|) -; Return values .: Success: $aList, See remarks for format. -; Failure: False and @error set to $TOR_ERROR_GENERIC -; Author ........: Damon Harris (TheDcoder) -; Remarks .......: 1. $aList is an array with 3 elements: -; $aList[$TOR_FIND_TORLIST] - This element contains the list of tor executables -; $aList[$TOR_FIND_GEOIP] - This element contains the list of GeoIP files -; $aList[$TOR_FIND_GEOIP6] - This element contains the list of GeoIP6 files -; Each of the elements are made up of 2 columns -; $TOR_FIND_VERSION - This column contains the version of the found file -; $TOR_FIND_PATH - This column contains the path fo the found file -; 2. This function can take some time to return. -; 3. Arrays inside $aList are not sorted! -; Example .......: No -; =============================================================================================================================== -Func _Tor_Find($vFolders) - If IsString($vFolders) Then $vFolders = StringSplit($vFolders, '|', $STR_NOCOUNT) - Local $aFiles[0] - For $sFolder In $vFolders - _ArrayConcatenate($aFiles, _FileListToArrayRec($sFolder, "tor.exe;geoip;geoip6", $FLTAR_FILES, $FLTAR_RECUR, $FLTAR_NOSORT, $FLTAR_FULLPATH), 1) - Next - If UBound($aFiles) = 0 Then Return SetError($TOR_ERROR_GENERIC, 0, False) - Local $aTorList[0][2] - Local $aGeoIP[0][2] - Local $aGeoIPv6[0][2] - Local $aPath - Local $aTorVersion[0] - Local $aGeoFileDate[0] - For $sFile In $aFiles - $aPath = _PathSplit($sFile, $vFolders, $vFolders, $vFolders, $vFolders) ; $vFolders is just used as a dummy here - Switch $aPath[3] - Case "tor" - $aTorVersion = _Tor_CheckVersion($sFile) - If Not @error Then _ArrayAdd($aTorList, $aTorVersion[$TOR_VERSION_NUMBER] & '|' & $sFile) - - Case "geoip", "geoip6" - $aGeoFileDate = StringRegExp(FileReadLine($sFile), '([A-Z][a-z]*) ([\d]{1,2}) (\d{4})', $STR_REGEXPARRAYMATCH) - If Not @error Then - Switch $aPath[3] - Case "geoip" - _ArrayAdd($aGeoIP, _ArrayToString($aGeoFileDate, ' ') & '|' & $sFile) - Case "geoip6" - _ArrayAdd($aGeoIPv6, _ArrayToString($aGeoFileDate, ' ') & '|' & $sFile) - EndSwitch - EndIf - EndSwitch - Next - Local $aList[3] = [$aTorList, $aGeoIP, $aGeoIPv6] - Return $aList -EndFunc - -; #FUNCTION# ==================================================================================================================== -; Name ..........: _Tor_GenHash -; Description ...: Generate a hash for use with Tor -; Syntax ........: _Tor_GenHash($sString) -; Parameters ....: $sString - The string for which will the hash be calculated. -; Return values .: Success: $aHash (See Remarks) -; Failure: False and @error is set to: -; $TOR_ERROR_PROCESS - If Tor didn't launch or run successfully -; $TOR_ERROR_GENERIC - If the hash was not found in the output -; Author ........: Damon Harris (TheDcoder) -; Remarks .......: $aHash is an array with 3 elements: -; $aHash[0] - Contains the full hash (16:660537E3E1CD49996044A3BF558097A981F539FEA2F9DA662B4626C1C2) -; $aHash[1] - Contains the salt of the hash (660537E3E1CD4999) -; $aHash[2] - Contains the salted hash (44A3BF558097A981F539FEA2F9DA662B4626C1C2) -; Example .......: No -; =============================================================================================================================== -Func _Tor_GenHash($sString) - Local $sOutput = _Process_RunCommand($PROCESS_RUNWAIT, $g__sTorPath & ' --hash-password "' & $sString & '"') - If @error Then Return SetError($TOR_ERROR_PROCESS, @error, False) - Local $aHash = StringRegExp($sOutput, '16:([A-Z0-9]{16})60([A-Z0-9]{40})', $STR_REGEXPARRAYFULLMATCH) - If @error Then Return SetError($TOR_ERROR_GENERIC, @error, False) - Return $aHash -EndFunc - -; #FUNCTION# ==================================================================================================================== -; Name ..........: _Tor_SetPath -; Description ...: Sets Tor.exe's path, it will be used by the UDF in the rest of the functions. -; Syntax ........: _Tor_SetPath($sTorPath[, $bVerify = True]) -; Parameters ....: $sTorPath - Path of Tor.exe, can be relative or short. See Remarks. -; $bVerify - [optional] If set to False, no checkes are performed. Default is True. -; Return values .: Success: $aTorVersion from _Tor_CheckVersion or True if $bVerify is False. -; Failure: False and @error set to: -; $TOR_ERROR_GENERIC - If $sTorPath does not exist -; $TOR_ERROR_VERSION - If _Tor_CheckVersion failed to check Tor's version, @extended is set to _Tor_CheckVersion's @error. -; Author ........: Damon Harris (TheDcoder) -; Remarks .......: 1. The $sTorPath will always be converted to a long and absolute path before getting assinged. -; 2. The existing path assigned to Tor.exe will not change if _Tor_SetPath fails. -; 3. Set $bVerify to False to skip the version check, you will never get failure if you use this method. -; Example .......: No -; =============================================================================================================================== -Func _Tor_SetPath($sTorPath, $bVerify = True) - If Not $bVerify Then - $g__sTorPath = $sTorPath - Return True - EndIf - If Not FileExists($sTorPath) Then Return SetError($TOR_ERROR_GENERIC, 0, False) - Local $sOldTorPath = $g__sTorPath - $g__sTorPath = $sTorPath - Local $aTorVersion = _Tor_CheckVersion() - If @error Then - $g__sTorPath = $sOldTorPath - Return SetError($TOR_ERROR_VERSION, @error, False) - EndIf - Return $aTorVersion -EndFunc - -; #FUNCTION# ==================================================================================================================== -; Name ..........: _Tor_Start -; Description ...: Starts Tor -; Syntax ........: _Tor_Start($sConfig) -; Parameters ....: $sConfig - Path to the config/torrc file. -; Return values .: Success: $aTorProcess, See Remarks. -; Failure: $sCommand used to execute Tor and @error set to: -; $TOR_ERROR_PROCESS - If there was a problem starting the process -; $TOR_ERROR_CONFIG - If there was a problem during verification of the $sConfig -; Author ........: Damon Harris (TheDcoder) -; Remarks .......: $aTorProcess's Format: -; $aTorProcess[$TOR_PROCESS_HANDLE] - Contains the process handle of tor.exe -; $aTorProcess[$TOR_PROCESS_PID] - Contains the PID of tor.exe -; $aTorProcess[$TOR_PROCESS_SOCKET] - Reserved for the TCP socket, used by _Tor_Controller functions -; Example .......: No -; =============================================================================================================================== -Func _Tor_Start($sConfig) - _Tor_VerifyConfig($sConfig) - If @error Then Return SetError($TOR_ERROR_CONFIG, @error, False) - Local $aTorProcess[3] - Local $sCommand = '"' & $g__sTorPath & '" --allow-missing-torrc --defaults-torrc "" -f "' & $sConfig & '"' - $aTorProcess[$TOR_PROCESS_HANDLE] = _Process_RunCommand($PROCESS_RUN, $sCommand, @ScriptDir) - If @error Then Return SetError($TOR_ERROR_PROCESS, @error, $sCommand) - $aTorProcess[$TOR_PROCESS_PID] = @extended - Return $aTorProcess -EndFunc - -; #FUNCTION# ==================================================================================================================== -; Name ..........: _Tor_Stop -; Description ...: Stops Tor -; Syntax ........: _Tor_Stop(Byref $aTorProcess) -; Parameters ....: $aTorProcess - [in/out] $aTorProcess from _Tor_Start. -; Return values .: Success: True and $aTorProcess is modified, See Remarks. -; Failure: False, @error set to: -; $TOR_ERROR_GENERIC - If $aTorProcess is invalid (does not contain 3 elements). -; $TOR_ERROR_PROCESS - If ProcessClose fails, @extended is set to ProcessClose's @error -; Author ........: Damon Harris (TheDcoder) -; Remarks .......: Tor is sent the shutdown signal first (using TCP) and if it fails, it is closed forcibly by ProcessClose -; $aTorProcess[$TOR_PROCESS_PID] and $aTorProcess[$TOR_PROCESS_HANDLE] are set to 0 which help avoid conflict -; Related .......: _Tor_Start -; Example .......: No -; =============================================================================================================================== -Func _Tor_Stop(ByRef $aTorProcess) - If UBound($aTorProcess) <> 3 Then Return SetError($TOR_ERROR_GENERIC, 0, False) - _Tor_Controller_SendRaw($aTorProcess, 'SIGNAL SHUTDOWN') - If Not @error Then - Local $sResponse = _Tor_Controller_WaitForMsg($aTorProcess) - If Not @error Then - _Tor_Controller_CheckReplyForError($sResponse) - If Not @error Then Return - EndIf - Else - ProcessClose($aTorProcess[$TOR_PROCESS_PID]) ; Force closure - If @error Then Return SetError($TOR_ERROR_PROCESS, @error, False) - EndIf - $aTorProcess[$TOR_PROCESS_PID] = 0 - _Process_CloseHandle($aTorProcess[$TOR_PROCESS_HANDLE]) - $aTorProcess[$TOR_PROCESS_HANDLE] = 0 - Return True -EndFunc - -; #FUNCTION# ==================================================================================================================== -; Name ..........: _Tor_SwitchCircuit -; Description ...: Switch Tor to clean circuits so new application requests don't share any circuits with old ones -; Syntax ........: _Tor_SwitchCircuit(Byref $aTorProcess) -; Parameters ....: $aTorProcess - [in/out] $aTorProcess from _Tor_Start. -; Return values .: Success: True -; Failure: False, @error set to: -; $TOR_ERROR_GENERIC - If controller sent a reply indicating an error and @extended is -; set to _Tor_Controller_CheckReplyForError's @extended -; $TOR_ERROR_NETWORK - If a network error occurs, @extended is set to TCPSend/TCPRecv's @error -; Author ........: Damon Harris (TheDcoder) -; Remarks .......: Tor may rate-limit this action so use it responsibly -; Example .......: No -; =============================================================================================================================== -Func _Tor_SwitchCircuit(ByRef $aTorProcess) - _Tor_Controller_SendRaw($aTorProcess, 'SIGNAL NEWNYM') - If @error Then Return SetError($TOR_ERROR_NETWORK, @extended, False) - Local $sReply = _Tor_Controller_WaitForMsg($aTorProcess) - If @error Then Return SetError($TOR_ERROR_NETWORK, @extended, False) - _Tor_Controller_CheckReplyForError($sReply) - If @error Then Return SetError($TOR_ERROR_GENERIC, @extended, False) - Return True -EndFunc - -; #FUNCTION# ==================================================================================================================== -; Name ..........: _Tor_VerifyConfig -; Description ...: Check if the configuration is valid. -; Syntax ........: _Tor_VerifyConfig($sConfig) -; Parameters ....: $sConfig - a Path to the config/torrc file. -; Return values .: Success: True -; Failure: False and @error set to $TOR_ERROR_CONFIG -; Author ........: Damon Harris (TheDcoder) -; Remarks .......: This function just perfroms a bare-minimum check -; Example .......: No -; =============================================================================================================================== -Func _Tor_VerifyConfig($sConfig) - Local $sOutput = _Process_RunCommand($PROCESS_RUNWAIT, '"' & $g__sTorPath & '" --verify-config --allow-missing-torrc --defaults-torrc "" -f "' & $sConfig & '"', @ScriptDir) - If @error Then Return SetError($TOR_ERROR_PROCESS, @error, False) - Local $aOutput = StringSplit(StringStripWS($sOutput, $STR_STRIPTRAILING), @CRLF, $STR_ENTIRESPLIT) - If $aOutput[$aOutput[0]] = "Configuration was valid" Then Return True - Return SetError($TOR_ERROR_CONFIG, 0, False) -EndFunc - -Func __Tor_OnExitTCPShutdown() - TCPShutdown() -EndFunc diff --git a/allium b/allium new file mode 160000 index 0000000..263f9f7 --- /dev/null +++ b/allium @@ -0,0 +1 @@ +Subproject commit 263f9f724913fdba14f586b08f3bbe6027bb8d22 diff --git a/config.adoc b/config.adoc deleted file mode 100644 index c2df409..0000000 --- a/config.adoc +++ /dev/null @@ -1,153 +0,0 @@ -= ProxAllium Configuration - -== Introduction - -This document will outline all of the available configuration options in ProxAllium. The defaults are pretty good so an average user can do without reading this, but advanced users may want to access one of the more advanced features and change the defaults to suit their needs. - -It goes without saying that you should know what you are doing, otherwise you may have unexpected consequences! - -== Config File - -ProxAllium uses a single `config.ini` file which is stored alongside the binary, it uses the reasonably simple https://en.wikipedia.org/wiki/INI_file#Format[INI] format to store your preferences. - -Don't worry about getting the format to follow the rules outlined in the wiki, AutoIt's INI parser is quite flexible and will be able to process your output as long it is readable by a human. Try taking the automatically generated key/value pairs as an example. - -NOTE: Don't forget to regenerate Tor configuration if you change anything which effects Tor! - -== Options - -This part will describe all of the options/keys/properties a section might contain. - -=== `proxallium` - -|=== -|Key |Value |Default - -| `output_poll_interval` -| The delay between checking for output from Tor in milliseconds -| `100` - -|=== - -=== `tor` - -|=== -|Key |Value |Default - -| `path` -| Path to `tor.exe` -| `Tor\tor.exe` - -| `obfs4_path` -| Path to `obfs4.exe` (pluggable transport for bridges) -| `Tor\PluggableTransports\obfs4\obfs4proxy.exe` - -| `snowflake_path` -| Path to Snowflake pluggable transport (bridge) -| `Tor\PluggableTransports\obfs4\snowflake-client.exe` - -| `snowflake_args` -| Arguments to the Snowflake client -| Refer to the https://gitlab.torproject.org/tpo/anti-censorship/pluggable-transports/snowflake/-/tree/main/client[official docs] for up-to-date information - -| `config_file` -| Path for the generated `torrc` file -| `config.torrc` - -| `data_dir` -| Path to the directory used by Tor to store data -| `Tor Data` - -| `geoip4_file` and/or `geoip6_file` -| Paths to the GeoIP files -| `Tor\geoip` and/or `Tor\geoip6` - -|=== - -=== `tor_config` - -|=== -|Key |Value |Default - -| `port` -| Port for Tor's SOCKS5 proxy -| `9050` - -| `tunnel_port` -| Port for the HTTP tunnel proxy, use `auto` if you want Tor to pick the port -| _None_ - -| `control_port` -| Port for Tor's controller, used to control Tor -| `9051` - -| `control_pass` -| Password for controller authentication -| String of random 6 digit number - -| `localhost_only` -| Only allow proxy connection from your computer -| `true` - -| `exit_node_country_code` -| https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Current_codes[2-letter country code] of the exit node -| _None_ - -|=== - -=== `proxy` - -IMPORTANT: These settings are for Tor to connect to the nodes, not for Tor's proxy! - -|=== -|Key |Value - -| `type` -| Type of the proxy (`http` or `https` or `socks4` or `socks5`) - -| `host` -| Address of the proxy's host (I.P or Name) - -| `port` -| Port to connect at the host - -| `user` -| (*Only for SOCKS5*) Username - -| `pass` -| (*Only for SOCKS5*) Password - -|=== - -=== `bridges` - -TIP: You can change these settings via GUI! Use `Options` -> `Bridges` option in the menu - -|=== -|Key |Value - -| `enabled` -| `true` if enabled or `false` if not - -| `path` -| Path to a text file with the bridge lines - -|=== - -=== `startup` - -TIP: These settings can be interactively modified via GUI in the `Options` -> `Startup` menu! - -|=== -|Key |Value - -| `auto_start` -| `true` if auto-start is enabled or `false` if not - -| `auto_start_shortcut` -| (*DON'T MODIFY, INTERNAL USE ONLY*) Path of the startup shortcut - -| `start_minimized` -| `true` if you want to start minimized or `false` if not - -|=== diff --git a/help.adoc b/help.adoc deleted file mode 100644 index 9484492..0000000 --- a/help.adoc +++ /dev/null @@ -1,78 +0,0 @@ -= Documentation for ProxAllium -:doctype: book -:nofooter: -:toc: left - -== Introduction -ProxAllium is a Free and Open Source front-end for Tor which makes it *easier* for normal everyday people to make more out of Tor! -With ProxAllium, you can circumvent censorship and be secure while using public internet hotspots (you can also be anonymous but only upto some extent). - -Just run ProxAllium and now you have a working Tor circuit for you to use! - -You can consult to the <> for more information. - -== Installation -ProxAllium is fully portable, it does not require any _setup_ to be done and it does not mess with anything outside its own folder! - -Just use any file archiver (http://7-zip.org/[7-zip] is recommended) to extract the `.7z` file onto your computer, you can extract it to anywhere, it is your choice. -The `7z` archive/package contains a folder called `ProxAllium` and within it, you can find ProxAllium itself and other necessary files. - -Now you can start using ProxAllium by executing `ProxAllium.exe`! Easy, isn't it? - -== Mailing List (Email Updates) - -CAUTION: *I am no longer actively posting to the mailing list, so I do not recommend anyone to register, sorry.* - -Now you can get e-mail notifications for new releases and updates from https://listengine.tuxfamily.org/proxallium.tuxfamily.org/news/[ProxAllium's Mailing List]! - -=== Subscribing -To subscribe, send a mail with `subscribe` as the subject to `news-request@proxallium.tuxfamily.org`, then reply to the confirmation mail sent by `listmaster@tuxfamily.org`. If for some reason you are not able to subscribe, you can https://github.com/DcodingTheWeb/ProxAllium/wiki/FAQ#i-have-a-question-where-can-i-ask[contact me] asking to add your e-mail to the mailing list... I won't bite by the way! - -=== Precautions and Information -. Your Email is **private** and is **not distributed** to anyone! -. You will receive emails updates from `mailman@proxallium.tuxfamily.org`, so make sure that it is in your whitelist/address book/contacts. You don't want to find those important notifications in your spam folder! -. **Do no reply to email notifications**! They will not reach anyone, the mailing list only accepts emails from administrators -. To unsubscribe, just follow the same procedure as <> except use `unsubscribe` as the subject of the email - - -== FAQ -=== What does it do? -ProxAllium's goal is to make using https://www.torproject.org/about/overview.html.en[Tor] (Not to be confused with https://www.torproject.org/projects/torbrowser.html.en[Tor Browser]) easier for normal everyday users. It's basically a front-end for Tor, except that it tries to be more than that. - -=== How is it different from Tor Browser (Bundle)? -It is not a replacement for the `TBB`, ProxAllium does not come with any browser! You should configure your own browser to work with `Tor`. Don't worry because it's really easy! You just have to use the proxy created by `Tor`. The method for using the proxy created by Tor is the same as using a traditional https://en.wikipedia.org/wiki/SOCKS[SOCKS proxy]. - -=== Where do I download ProxAllium? -You can find the 7-zip packages at the https://github.com/DcodingTheWeb/ProxAllium/releases[Releases] page. - -=== How do I make it start on startup? -Use the `Automatically start with Windows` option (in `Menu -> Options -> Startup`). - -=== I have a question, where can I ask? -You can consult to the "link:https://proxallium.tuxfamily.org/chat/[Chat]" page on ProxAllium's website. - -== Credits & Acknowledgments -=== Programming Language -Thanks to https://github.com/jonathanbennett73[Jonathan Bennett] & AutoIt Team for creating a wonderful scripting language called AutoIt! All of ProxAllium's code is 100% pure http://www.autoitscript.com/autoit3/[AutoIt]. - -=== Tor -Thanks to https://en.wikipedia.org/wiki/The_Tor_Project,_Inc[The Tor Project] for creating a wonderful thing called https://www.torproject.org/[Tor]. Tor enables millions of people to be anonymous and circumvent censorship! - -=== ProxAllium's Icon -The icon for ProxAllium is a combined effort from many talented graphic artists... that excludes me. - -* Onion Icon made by http://www.flaticon.com/authors/roundicons[Roundicons] from www.flaticon.com -* Computer Icon made by http://www.flaticon.com/authors/madebyoliver[Madebyoliver] from www.flaticon.com -* World Server Icon made by http://www.flaticon.com/authors/prosymbols[Prosymbols] from www.flaticon.com -* Double Headed Arrow Icon made by http://www.flaticon.com/authors/freepik[Freepik] from www.flaticon.com - -All of these icons were compiled into one by me. - -https://www.icoconverter.com/ was used to create the final `ico` file! - - -=== Infrastructure -Thanks to https://github.com[GitHub] (Code and Issue Tracker Hosting), https://www.tuxfamily.org/[Tux Family] (https://www.tuxfamily.org/en/about[Whole array of services to FOSS projects]) and https://www.oftc.net/[OFTC] (IRC Network) for providing such generous services! - -=== You! -For using ProxAllium! diff --git a/icon.ico b/icon.ico deleted file mode 100644 index aeef57e..0000000 Binary files a/icon.ico and /dev/null differ diff --git a/interrupt.h b/interrupt.h new file mode 100644 index 0000000..c890f66 --- /dev/null +++ b/interrupt.h @@ -0,0 +1,18 @@ +#ifndef INTERRUPT_H +#define INTERRUPT_H + +#include +#include + +volatile sig_atomic_t interrupted = false; + +void handle_signal(int sig_num) { + interrupted = true; +} + +void init_interrupt_catcher() { + signal(SIGINT, handle_signal); + signal(SIGTERM, handle_signal); +} + +#endif diff --git a/log.c b/log.c new file mode 100644 index 0000000..e2fdef6 --- /dev/null +++ b/log.c @@ -0,0 +1,47 @@ +#include +#include +#include "log.h" + +void log_output(const char *format, ...) { + va_list args; + + va_start(args, format); + int buffer_size = log_calc_buf_size(format, args); + va_end(args); + + va_start(args, format); + log_output_raw_var(format, buffer_size, args); + va_end(args); + + log_output_text("\n"); +} + +void log_output_raw(const char *format, ...) { + va_list args; + + va_start(args, format); + int buffer_size = log_calc_buf_size(format, args); + va_end(args); + + va_start(args, format); + log_output_raw_var(format, buffer_size, args); + va_end(args); +} + +int log_calc_buf_size(const char *format, va_list args) { + // Calculate required size to store the formatted string + return vsnprintf(NULL, 0, format, args) + 1; +} + +void log_output_raw_var(const char *format, int buffer_size, va_list args) { + // Store the formatted string + char string[buffer_size]; + vsnprintf(string, buffer_size, format, args); + + // Pass the string for output + log_output_text(string); +} + +void log_output_text(const char *string) { + fputs(string, stdout); +} diff --git a/log.h b/log.h new file mode 100644 index 0000000..0af67a3 --- /dev/null +++ b/log.h @@ -0,0 +1,12 @@ +#include + +#ifndef LOG_H +#define LOG_H + +void log_output(const char *format, ...); +void log_output_raw(const char *format, ...); +int log_calc_buf_size(const char *format, va_list args); +void log_output_raw_var(const char *format, int buffer_size, va_list args); +void log_output_text(const char *string); + +#endif diff --git a/proxallium.c b/proxallium.c new file mode 100644 index 0000000..0ce2600 --- /dev/null +++ b/proxallium.c @@ -0,0 +1,288 @@ +#define __STDC_WANT_LIB_EXT1__ + +#include +#include +#include +#include +#include +#include +#include +#include "allium/allium.h" + +#include "log.h" +#include "utils.h" +#include "interrupt.h" + +struct { + unsigned int port; + bool localhost_only; +} options = { + 9050, + true +}; + + +struct OutputHandler { + bool (*function)(char *); + bool finished; +}; + +void process_cmdline_options(int argc, char *argv[]); +noreturn void print_help(bool error, char *program_name); +void proxallium_main(void); +bool proxallium_gui_main(void); +void proxallium_cleanup(void); +void proxallium_process_line(char *line); +char *proxallium_gen_torrc(); +bool tor_start(void); +bool handler_bootstrap(char *line); +bool handler_warnings_and_errors(char *line); + +struct TorInstance *tor_instance; + +// Output handlers +struct OutputHandler handlers[] = { + {handler_bootstrap, false}, + {handler_warnings_and_errors, false} +}; +size_t handlers_num = sizeof handlers / sizeof(struct OutputHandler); + +int main(int argc, char *argv[]) { + // Process command-line arguments + process_cmdline_options(argc, argv); + + // Initialize interrupt catcher + init_interrupt_catcher(); + + // Start Tor + tor_start(); + + // Handle main loop + proxallium_main(); + + // Clean up and exit + free(tor_instance); + return EXIT_SUCCESS; +} + +void process_cmdline_options(int argc, char *argv[]) { + struct option long_options[] = { + {"port", required_argument, NULL, 'p'}, + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'v'}, + {NULL, 0, NULL, 0} + }; + int option; + while ((option = getopt_long(argc, argv, "p:hv", long_options, NULL)) != -1) { + switch (option) { + long port; + case 'p': + port = strtol(optarg, NULL, 0); + if (errno == ERANGE || port < 0 || port > UINT_MAX) { + printf("Port is out of range! Please use something between 0 and %u\n", UINT_MAX); + exit(EXIT_FAILURE); + } + options.port = port; + break; + case 'h': + case '?': + print_help(option == '?', argv[0]); + break; + case 'v': + puts( + "ProxAllium " VERSION "\n" + "\n" + "Copyright (c) 2019, Dcoding The Web" + ); + exit(EXIT_SUCCESS); + } + } +} + +void noreturn print_help(bool error, char *program_name) { + if (!error) puts( + "ProxAllium - front-end and controller for Tor" + ); + printf("\nUsage: %s [OPTION]...\n", program_name); + puts( + "\n" + "Options:\n" + " -p, --port Port for Tor's proxy to bind\n" + " -h, --help Show this help text\n" + " -v, --version Print the version\n" + "\n" + "Report bugs at the GitHub repository " + ); + exit(error ? EXIT_FAILURE : EXIT_SUCCESS); +} + +void proxallium_main() { + bool stopping = false; + + // Main event loop + while (true) { + enum allium_status status = allium_get_status(tor_instance, 100); + if (status == DATA_AVAILABLE) { + char *line = allium_read_stdout_line(tor_instance); + proxallium_process_line(line); + } else if (interrupted || status == STOPPED) { + if (interrupted) { + if (!stopping) { + log_output("Caught signal, attempting to exiting cleanly..."); + allium_stop(tor_instance); + } else { + log_output("Caught second signal, stopping by force!"); + allium_kill(tor_instance); + } + interrupted = false; + } else if (status == STOPPED) { + break; + } + } + } + proxallium_cleanup(); +} + +void proxallium_cleanup() { + log_output("\nFinished reading Tor's output! Tor exited with exit code %i.", allium_get_exit_code(tor_instance)); + allium_clean(tor_instance); +} + +void proxallium_process_line(char *line) { + for (int handler = 0; handler < handlers_num; handler++) { + if (!handlers[handler].finished) + handlers[handler].finished = handlers[handler].function(line); + } +} + +char *proxallium_gen_torrc() { + // Temp variables to store format strings and their sizes + char *format_string; + int string_size; + + // Socks Port + format_string = "SocksPort %u\n"; + string_size = snprintf(NULL, 0, format_string, options.port); + char socks_port[string_size + 1]; + snprintf(socks_port, string_size + 1, format_string, options.port); + + // Only allow connections from localhost explicitly for safety + char *localhost_explicit = options.localhost_only ? + "SOCKSPolicy accept 127.0.0.1\n" + "SOCKSPolicy accept6 [::1]\n" + "SOCKSPolicy reject *\n" + : ""; + + // Generate the final string with all of the configuration + char *config_sections[] = { + socks_port, + localhost_explicit, + NULL + }; + + // Calculate the total required size for the string + size_t total_size = 1; + for (char **section = config_sections; *section != NULL; ++section) { + total_size += strlen(*section); + } + + // Allocate space for the string and populate it + char *torrc = malloc(total_size); + if (!torrc) return NULL; + torrc[0] = '\0'; + for (char **section = config_sections; *section != NULL; ++section) { + strcat(torrc, *section); + } + + return torrc; +} + +bool tor_start() { + // Create a new instance of Tor + tor_instance = allium_new_instance("tor"); + if (!tor_instance) { + log_output("Failed to allocate a new instance of Tor!"); + return EXIT_FAILURE; + } + + // Generate the tor config according to the options + char *config = proxallium_gen_torrc(); + if (!config) { + log_output("Failed to generate configuration for Tor!"); + return EXIT_FAILURE; + } + + // Start Tor + if (!allium_start(tor_instance, config, NULL)) { + log_output("Failed to start Tor!"); + return false; + } + + log_output("Started Tor with PID %lu!", tor_instance->pid); +} + +bool handler_bootstrap(char *output) { + unsigned int percentage; + + char *compare_string, *message, *segment = output; + size_t segment_len; + unsigned int segment_num = 0; + while (true) { + // Get the next segment of text + segment = segstr(segment, &segment_len, ' ', &segment_num); + if (!segment) return false; + + switch (segment_num) { + case 5: // Identify if we are bootstrapping + compare_string = "Bootstrapped"; + if (strncmp(segment, compare_string, segment_len) != 0) return false; + message = segment; + break; + case 6: // Get the percentage + if (sscanf(segment, "%3u%%:", &percentage) == 0) return false; + break; + } + + // Check if we got all of the information we needed + if (segment_num == 6) break; + } + + if (percentage == 0) log_output("Trying to establish a connection and build a circuit, please wait..."); + log_output("%s", message); + if (percentage == 100) { + log_output( + "##################################################\n" + "# You can now connect to the Tor proxy hosted at:\n" + "# IP Address: 127.0.0.1\n" + "# Port : %u\n" + "# Proxy Type: SOCKS5\n" + "##################################################" + , options.port); + return true; + } + + return false; +} + +bool handler_warnings_and_errors(char *output) { + char *segment = output; + size_t segment_len; + unsigned int segment_num = 0; + bool warning, error; + while (segment = segstr(segment, &segment_len, ' ', &segment_num)) { + if (segment_num == 4) { + // Check for warning or error + warning = segequstr(segment, segment_len, "[warn]"); + error = warning ? false : segequstr(segment, segment_len, "[err]"); + + // No warning and error + if (!warning && !error) break; + } else if (segment_num == 5) { + // Print the error or warning + log_output("%s: %s", warning ? "Warning" : "Error", segment); + break; + } + } + + return false; +} diff --git a/utils.c b/utils.c new file mode 100644 index 0000000..f299a79 --- /dev/null +++ b/utils.c @@ -0,0 +1,61 @@ +#include +#include "utils.h" + +/// @brief Get delimiter-separated segments from a string in a non-destructive method. +/// @details A useful function which can be used for parsing in a loop in a safe manner. +/// @author Damon Harris (TheDcoder@protonmail.com) +/// @param [in] str Current segment or start of the string. +/// @param [in,out] seg_len Length of the segment current segment, value does not matter if seg_num is set to 0. +/// @param delim Character used for separation (delimiter). +/// @param [in,out] seg_num Number of the current segment, set to 0 before first call. +/// @returns Pointer to the start of the next segment, seg_len is set to the length of the segment and seg_num is incremented by 1. +/// NULL if there is no next segment, note that NULL is never returned on the first call (even if an empty string is passed). +/// @remarks seg_num only has significance if its value is 0, the reason is for the function to be able to detect the initial call +/// so that it doesn't skip the first segment. seg_len can be any value on the first call since it is not used to calculate +/// the start of the next segment. +/// +/// I was inspired by the lack of a helper function which I can use for parsing/tokenizing a string which is both stateless +/// and non-destructive (strtok_s is better than strtok but still modifies the supplied string). The best alternative was to +/// strchr and keep track of other stuff manually, this function tries to give out as much information as possible while keeping +/// the overall concept simple. The length and position (number) of the segment should be enough to get you started on parsing :) +char *segstr(const char *str, size_t *seg_len, char delim, unsigned int *seg_num) { + if (*seg_num != 0) { + // Check if we have reached the last segment + str += *seg_len; + if (str[0] == '\0') return NULL; + + // Proceed to the next segment + ++str; + } + + // Increment the segment number + ++*seg_num; + + // Find the delimiter + char *delim_start = strchr(str, delim); + + // Calculate the length of the segment + if (delim_start) { + // Difference between the delimiter and the start of the segment + *seg_len = delim_start - str; + } else { + // We have reached the last segment + // There is no delimiter, so use the remaining length + *seg_len = strlen(str); + } + + // Return the segment + return (char *) str; +} + +/// @brief Check a segment for equality with a string +/// @author Jan Alexander Steffens (jan.steffens@gmail.com) +/// @param seg Segment to test for equality. +/// @param seg_len Length of the segment. +/// @param str String to match with the segment. +/// @returns `true` if `str` is equal to `seg`, otherwise `false`. +/// @remarks This function was made as a convenience alternative to `strncmp`. +/// I would like to thank heftig from the ##c IRC channel at freenode for coming up with the code based on my concept! +bool segequstr(char *seg, size_t seg_len, char *str) { + return strncmp(seg, str, seg_len) == 0 && str[seg_len] == '\0'; +} diff --git a/utils.h b/utils.h new file mode 100644 index 0000000..82103aa --- /dev/null +++ b/utils.h @@ -0,0 +1,9 @@ +#ifndef UTILS_H +#define UTILS_H + +#include + +char *segstr(const char *str, size_t *seg_len, char delim, unsigned int *seg_num); +bool segequstr(char *seg, size_t seg_len, char *str); + +#endif