├── .gitattributes ├── .gitignore ├── CsrDecode.bat ├── CsrDecode.command ├── LICENSE └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Ensure all .bat scripts use CRLF line endings 2 | # This can prevent a number of odd batch issues 3 | *.bat text eol=crlf 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | -------------------------------------------------------------------------------- /CsrDecode.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | REM Get our local path before delayed expansion - allows ! in path 3 | set "thisDir=%~dp0" 4 | 5 | setlocal enableDelayedExpansion 6 | REM Setup initial vars 7 | set "script_name=" 8 | set /a tried=0 9 | set "toask=yes" 10 | set "pause_on_error=yes" 11 | set "py2v=" 12 | set "py2path=" 13 | set "py3v=" 14 | set "py3path=" 15 | set "pypath=" 16 | set "targetpy=3" 17 | 18 | REM use_py3: 19 | REM TRUE = Use if found, use py2 otherwise 20 | REM FALSE = Use py2 21 | REM FORCE = Use py3 22 | set "use_py3=TRUE" 23 | 24 | REM We'll parse if the first argument passed is 25 | REM --install-python and if so, we'll just install 26 | set "just_installing=FALSE" 27 | 28 | REM Get the system32 (or equivalent) path 29 | call :getsyspath "syspath" 30 | 31 | REM Make sure the syspath exists 32 | if "!syspath!" == "" ( 33 | if exist "%SYSTEMROOT%\system32\cmd.exe" ( 34 | if exist "%SYSTEMROOT%\system32\reg.exe" ( 35 | if exist "%SYSTEMROOT%\system32\where.exe" ( 36 | REM Fall back on the default path if it exists 37 | set "ComSpec=%SYSTEMROOT%\system32\cmd.exe" 38 | set "syspath=%SYSTEMROOT%\system32\" 39 | ) 40 | ) 41 | ) 42 | if "!syspath!" == "" ( 43 | cls 44 | echo ### ### 45 | echo # Warning # 46 | echo ### ### 47 | echo. 48 | echo Could not locate cmd.exe, reg.exe, or where.exe 49 | echo. 50 | echo Please ensure your ComSpec environment variable is properly configured and 51 | echo points directly to cmd.exe, then try again. 52 | echo. 53 | echo Current CompSpec Value: "%ComSpec%" 54 | echo. 55 | echo Press [enter] to quit. 56 | pause > nul 57 | exit /b 1 58 | ) 59 | ) 60 | 61 | if "%~1" == "--install-python" ( 62 | set "just_installing=TRUE" 63 | goto installpy 64 | ) 65 | 66 | goto checkscript 67 | 68 | :checkscript 69 | REM Check for our script first 70 | set "looking_for=!script_name!" 71 | if "!script_name!" == "" ( 72 | set "looking_for=%~n0.py or %~n0.command" 73 | set "script_name=%~n0.py" 74 | if not exist "!thisDir!\!script_name!" ( 75 | set "script_name=%~n0.command" 76 | ) 77 | ) 78 | if not exist "!thisDir!\!script_name!" ( 79 | echo Could not find !looking_for!. 80 | echo Please make sure to run this script from the same directory 81 | echo as !looking_for!. 82 | echo. 83 | echo Press [enter] to quit. 84 | pause > nul 85 | exit /b 1 86 | ) 87 | goto checkpy 88 | 89 | :checkpy 90 | call :updatepath 91 | for /f "USEBACKQ tokens=*" %%x in (`!syspath!where.exe python 2^> nul`) do ( call :checkpyversion "%%x" "py2v" "py2path" "py3v" "py3path" ) 92 | for /f "USEBACKQ tokens=*" %%x in (`!syspath!where.exe python3 2^> nul`) do ( call :checkpyversion "%%x" "py2v" "py2path" "py3v" "py3path" ) 93 | for /f "USEBACKQ tokens=*" %%x in (`!syspath!where.exe py 2^> nul`) do ( call :checkpylauncher "%%x" "py2v" "py2path" "py3v" "py3path" ) 94 | REM Walk our returns to see if we need to install 95 | if /i "!use_py3!" == "FALSE" ( 96 | set "targetpy=2" 97 | set "pypath=!py2path!" 98 | ) else if /i "!use_py3!" == "FORCE" ( 99 | set "pypath=!py3path!" 100 | ) else if /i "!use_py3!" == "TRUE" ( 101 | set "pypath=!py3path!" 102 | if "!pypath!" == "" set "pypath=!py2path!" 103 | ) 104 | if not "!pypath!" == "" ( 105 | goto runscript 106 | ) 107 | if !tried! lss 1 ( 108 | if /i "!toask!"=="yes" ( 109 | REM Better ask permission first 110 | goto askinstall 111 | ) else ( 112 | goto installpy 113 | ) 114 | ) else ( 115 | cls 116 | echo ### ### 117 | echo # Warning # 118 | echo ### ### 119 | echo. 120 | REM Couldn't install for whatever reason - give the error message 121 | echo Python is not installed or not found in your PATH var. 122 | echo Please install it from https://www.python.org/downloads/windows/ 123 | echo. 124 | echo Make sure you check the box labeled: 125 | echo. 126 | echo "Add Python X.X to PATH" 127 | echo. 128 | echo Where X.X is the py version you're installing. 129 | echo. 130 | echo Press [enter] to quit. 131 | pause > nul 132 | exit /b 1 133 | ) 134 | goto runscript 135 | 136 | :checkpylauncher 137 | REM Attempt to check the latest python 2 and 3 versions via the py launcher 138 | for /f "USEBACKQ tokens=*" %%x in (`%~1 -2 -c "import sys; print(sys.executable)" 2^> nul`) do ( call :checkpyversion "%%x" "%~2" "%~3" "%~4" "%~5" ) 139 | for /f "USEBACKQ tokens=*" %%x in (`%~1 -3 -c "import sys; print(sys.executable)" 2^> nul`) do ( call :checkpyversion "%%x" "%~2" "%~3" "%~4" "%~5" ) 140 | goto :EOF 141 | 142 | :checkpyversion 143 | set "version="&for /f "tokens=2* USEBACKQ delims= " %%a in (`"%~1" -V 2^>^&1`) do ( 144 | REM Ensure we have a version number 145 | call :isnumber "%%a" 146 | if not "!errorlevel!" == "0" goto :EOF 147 | set "version=%%a" 148 | ) 149 | if not defined version goto :EOF 150 | if "!version:~0,1!" == "2" ( 151 | REM Python 2 152 | call :comparepyversion "!version!" "!%~2!" 153 | if "!errorlevel!" == "1" ( 154 | set "%~2=!version!" 155 | set "%~3=%~1" 156 | ) 157 | ) else ( 158 | REM Python 3 159 | call :comparepyversion "!version!" "!%~4!" 160 | if "!errorlevel!" == "1" ( 161 | set "%~4=!version!" 162 | set "%~5=%~1" 163 | ) 164 | ) 165 | goto :EOF 166 | 167 | :isnumber 168 | set "var="&for /f "delims=0123456789." %%i in ("%~1") do set var=%%i 169 | if defined var (exit /b 1) 170 | exit /b 0 171 | 172 | :comparepyversion 173 | REM Exits with status 0 if equal, 1 if v1 gtr v2, 2 if v1 lss v2 174 | for /f "tokens=1,2,3 delims=." %%a in ("%~1") do ( 175 | set a1=%%a 176 | set a2=%%b 177 | set a3=%%c 178 | ) 179 | for /f "tokens=1,2,3 delims=." %%a in ("%~2") do ( 180 | set b1=%%a 181 | set b2=%%b 182 | set b3=%%c 183 | ) 184 | if not defined a1 set a1=0 185 | if not defined a2 set a2=0 186 | if not defined a3 set a3=0 187 | if not defined b1 set b1=0 188 | if not defined b2 set b2=0 189 | if not defined b3 set b3=0 190 | if %a1% gtr %b1% exit /b 1 191 | if %a1% lss %b1% exit /b 2 192 | if %a2% gtr %b2% exit /b 1 193 | if %a2% lss %b2% exit /b 2 194 | if %a3% gtr %b3% exit /b 1 195 | if %a3% lss %b3% exit /b 2 196 | exit /b 0 197 | 198 | :askinstall 199 | cls 200 | echo ### ### 201 | echo # Python Not Found # 202 | echo ### ### 203 | echo. 204 | echo Python !targetpy! was not found on the system or in the PATH var. 205 | echo. 206 | set /p "menu=Would you like to install it now? [y/n]: " 207 | if /i "!menu!"=="y" ( 208 | REM We got the OK - install it 209 | goto installpy 210 | ) else if "!menu!"=="n" ( 211 | REM No OK here... 212 | set /a tried=!tried!+1 213 | goto checkpy 214 | ) 215 | REM Incorrect answer - go back 216 | goto askinstall 217 | 218 | :installpy 219 | REM This will attempt to download and install python 220 | REM First we get the html for the python downloads page for Windows 221 | set /a tried=!tried!+1 222 | cls 223 | echo ### ### 224 | echo # Installing Python # 225 | echo ### ### 226 | echo. 227 | echo Gathering info from https://www.python.org/downloads/windows/... 228 | powershell -command "[Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12;(new-object System.Net.WebClient).DownloadFile('https://www.python.org/downloads/windows/','%TEMP%\pyurl.txt')" 229 | REM Extract it if it's gzip compressed 230 | powershell -command "$infile='%TEMP%\pyurl.txt';$outfile='%TEMP%\pyurl.temp';try{$input=New-Object System.IO.FileStream $infile,([IO.FileMode]::Open),([IO.FileAccess]::Read),([IO.FileShare]::Read);$output=New-Object System.IO.FileStream $outfile,([IO.FileMode]::Create),([IO.FileAccess]::Write),([IO.FileShare]::None);$gzipStream=New-Object System.IO.Compression.GzipStream $input,([IO.Compression.CompressionMode]::Decompress);$buffer=New-Object byte[](1024);while($true){$read=$gzipstream.Read($buffer,0,1024);if($read -le 0){break};$output.Write($buffer,0,$read)};$gzipStream.Close();$output.Close();$input.Close();Move-Item -Path $outfile -Destination $infile -Force}catch{}" 231 | if not exist "%TEMP%\pyurl.txt" ( 232 | if /i "!just_installing!" == "TRUE" ( 233 | echo Failed to get info 234 | exit /b 1 235 | ) else ( 236 | goto checkpy 237 | ) 238 | ) 239 | echo Parsing for latest... 240 | pushd "%TEMP%" 241 | :: Version detection code slimmed by LussacZheng (https://github.com/corpnewt/gibMacOS/issues/20) 242 | for /f "tokens=9 delims=< " %%x in ('findstr /i /c:"Latest Python !targetpy! Release" pyurl.txt') do ( set "release=%%x" ) 243 | popd 244 | if "!release!" == "" ( 245 | if /i "!just_installing!" == "TRUE" ( 246 | echo Failed to get python version 247 | exit /b 1 248 | ) else ( 249 | goto checkpy 250 | ) 251 | ) 252 | echo Found Python !release! - Downloading... 253 | REM Let's delete our txt file now - we no longer need it 254 | del "%TEMP%\pyurl.txt" 255 | REM At this point - we should have the version number. 256 | REM We can build the url like so: "https://www.python.org/ftp/python/[version]/python-[version]-amd64.exe" 257 | set "url=https://www.python.org/ftp/python/!release!/python-!release!-amd64.exe" 258 | set "pytype=exe" 259 | if "!targetpy!" == "2" ( 260 | set "url=https://www.python.org/ftp/python/!release!/python-!release!.amd64.msi" 261 | set "pytype=msi" 262 | ) 263 | REM Now we download it with our slick powershell command 264 | powershell -command "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; (new-object System.Net.WebClient).DownloadFile('!url!','%TEMP%\pyinstall.!pytype!')" 265 | REM If it doesn't exist - we bail 266 | if not exist "%TEMP%\pyinstall.!pytype!" ( 267 | if /i "!just_installing!" == "TRUE" ( 268 | echo Failed to download installer 269 | exit /b 1 270 | ) else ( 271 | goto checkpy 272 | ) 273 | ) 274 | REM It should exist at this point - let's run it to install silently 275 | echo Installing... 276 | pushd "%TEMP%" 277 | if /i "!pytype!" == "exe" ( 278 | echo pyinstall.exe /quiet PrependPath=1 Include_test=0 Shortcuts=0 Include_launcher=0 279 | pyinstall.exe /quiet PrependPath=1 Include_test=0 Shortcuts=0 Include_launcher=0 280 | ) else ( 281 | set "foldername=!release:.=!" 282 | echo msiexec /i pyinstall.msi /qb ADDLOCAL=ALL TARGETDIR="%LocalAppData%\Programs\Python\Python!foldername:~0,2!" 283 | msiexec /i pyinstall.msi /qb ADDLOCAL=ALL TARGETDIR="%LocalAppData%\Programs\Python\Python!foldername:~0,2!" 284 | ) 285 | popd 286 | echo Installer finished with %ERRORLEVEL% status. 287 | REM Now we should be able to delete the installer and check for py again 288 | del "%TEMP%\pyinstall.!pytype!" 289 | REM If it worked, then we should have python in our PATH 290 | REM this does not get updated right away though - let's try 291 | REM manually updating the local PATH var 292 | call :updatepath 293 | if /i "!just_installing!" == "TRUE" ( 294 | echo. 295 | echo Done. 296 | ) else ( 297 | goto checkpy 298 | ) 299 | exit /b 300 | 301 | :runscript 302 | REM Python found 303 | cls 304 | set "args=%*" 305 | set "args=!args:"=!" 306 | if "!args!"=="" ( 307 | "!pypath!" "!thisDir!!script_name!" 308 | ) else ( 309 | "!pypath!" "!thisDir!!script_name!" %* 310 | ) 311 | if /i "!pause_on_error!" == "yes" ( 312 | if not "%ERRORLEVEL%" == "0" ( 313 | echo. 314 | echo Script exited with error code: %ERRORLEVEL% 315 | echo. 316 | echo Press [enter] to exit... 317 | pause > nul 318 | ) 319 | ) 320 | goto :EOF 321 | 322 | :undouble 323 | REM Helper function to strip doubles of a single character out of a string recursively 324 | set "string_value=%~2" 325 | :undouble_continue 326 | set "check=!string_value:%~3%~3=%~3!" 327 | if not "!check!" == "!string_value!" ( 328 | set "string_value=!check!" 329 | goto :undouble_continue 330 | ) 331 | set "%~1=!check!" 332 | goto :EOF 333 | 334 | :updatepath 335 | set "spath=" 336 | set "upath=" 337 | for /f "USEBACKQ tokens=2* delims= " %%i in (`!syspath!reg.exe query "HKCU\Environment" /v "Path" 2^> nul`) do ( if not "%%j" == "" set "upath=%%j" ) 338 | for /f "USEBACKQ tokens=2* delims= " %%i in (`!syspath!reg.exe query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v "Path" 2^> nul`) do ( if not "%%j" == "" set "spath=%%j" ) 339 | if not "%spath%" == "" ( 340 | REM We got something in the system path 341 | set "PATH=%spath%" 342 | if not "%upath%" == "" ( 343 | REM We also have something in the user path 344 | set "PATH=%PATH%;%upath%" 345 | ) 346 | ) else if not "%upath%" == "" ( 347 | set "PATH=%upath%" 348 | ) 349 | REM Remove double semicolons from the adjusted PATH 350 | call :undouble "PATH" "%PATH%" ";" 351 | goto :EOF 352 | 353 | :getsyspath 354 | REM Helper method to return a valid path to cmd.exe, reg.exe, and where.exe by 355 | REM walking the ComSpec var - will also repair it in memory if need be 356 | REM Strip double semi-colons 357 | call :undouble "temppath" "%ComSpec%" ";" 358 | 359 | REM Dirty hack to leverage the "line feed" approach - there are some odd side 360 | REM effects with this. Do not use this variable name in comments near this 361 | REM line - as it seems to behave erradically. 362 | (set LF=^ 363 | %=this line is empty=% 364 | ) 365 | REM Replace instances of semi-colons with a line feed and wrap 366 | REM in parenthesis to work around some strange batch behavior 367 | set "testpath=%temppath:;=!LF!%" 368 | 369 | REM Let's walk each path and test if cmd.exe, reg.exe, and where.exe exist there 370 | set /a found=0 371 | for /f "tokens=* delims=" %%i in ("!testpath!") do ( 372 | REM Only continue if we haven't found it yet 373 | if not "%%i" == "" ( 374 | if !found! lss 1 ( 375 | set "checkpath=%%i" 376 | REM Remove "cmd.exe" from the end if it exists 377 | if /i "!checkpath:~-7!" == "cmd.exe" ( 378 | set "checkpath=!checkpath:~0,-7!" 379 | ) 380 | REM Pad the end with a backslash if needed 381 | if not "!checkpath:~-1!" == "\" ( 382 | set "checkpath=!checkpath!\" 383 | ) 384 | REM Let's see if cmd, reg, and where exist there - and set it if so 385 | if EXIST "!checkpath!cmd.exe" ( 386 | if EXIST "!checkpath!reg.exe" ( 387 | if EXIST "!checkpath!where.exe" ( 388 | set /a found=1 389 | set "ComSpec=!checkpath!cmd.exe" 390 | set "%~1=!checkpath!" 391 | ) 392 | ) 393 | ) 394 | ) 395 | ) 396 | ) 397 | goto :EOF 398 | -------------------------------------------------------------------------------- /CsrDecode.command: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import sys, os, re 3 | 4 | csr_list = [ 5 | "CSR_ALLOW_UNTRUSTED_KEXTS", 6 | "CSR_ALLOW_UNRESTRICTED_FS", 7 | "CSR_ALLOW_TASK_FOR_PID", 8 | "CSR_ALLOW_KERNEL_DEBUGGER", 9 | "CSR_ALLOW_APPLE_INTERNAL", 10 | # "CSR_ALLOW_DESTRUCTIVE_DTRACE (name deprecated)", 11 | "CSR_ALLOW_UNRESTRICTED_DTRACE", 12 | "CSR_ALLOW_UNRESTRICTED_NVRAM", 13 | "CSR_ALLOW_DEVICE_CONFIGURATION", 14 | "CSR_ALLOW_ANY_RECOVERY_OS", 15 | "CSR_ALLOW_UNAPPROVED_KEXTS", 16 | "CSR_ALLOW_EXECUTABLE_POLICY_OVERRIDE" 17 | ] 18 | csr_dict = {} 19 | val = 1 20 | for key in csr_list: 21 | csr_dict[str(val)] = key 22 | val *= 2 23 | 24 | def cls(): 25 | os.system('cls' if os.name=='nt' else 'clear') 26 | 27 | def grab(prompt = ""): 28 | if sys.version_info >= (3, 0): 29 | return input(prompt) 30 | else: 31 | return str(raw_input(prompt)) 32 | 33 | def _check_hex(hex_string): 34 | # Remove 0x/0X 35 | hex_string = hex_string.replace("0x", "").replace("0X", "") 36 | hex_string = re.sub(r'[^0-9A-Fa-f]+', '', hex_string) 37 | return hex_string 38 | 39 | def hex_to_dec(hex_string): 40 | hex_string = _check_hex(hex_string) 41 | if not len(hex_string): 42 | return None 43 | try: 44 | dec = int(hex_string, 16) 45 | except: 46 | return None 47 | return dec 48 | 49 | def hex_to_vals(hex_string): 50 | # Convert the hex to decimal string - then start with a reversed list 51 | # and find out which values we have enabled 52 | dec = hex_to_dec(hex_string) 53 | if not dec: 54 | return [] 55 | has = [] 56 | for key in sorted(csr_dict, key=lambda x:int(x), reverse=True): 57 | if int(key) <= dec: 58 | has.append(csr_dict[str(key)]) 59 | dec -= int(key) 60 | return has 61 | 62 | def main(): 63 | cls() 64 | print("# CsrDecode #") 65 | print("") 66 | print("1. Hex To Values") 67 | print("2. Values to Hex") 68 | print("") 69 | print("Q. Quit") 70 | print("") 71 | menu = grab("Please select an option: ").lower() 72 | if not len(menu): 73 | return 74 | if menu == "q": 75 | exit() 76 | elif menu == "1": 77 | h_to_v() 78 | elif menu == "2": 79 | v_to_h() 80 | return 81 | 82 | def h_to_v(): 83 | cls() 84 | print("# CsrActiveConfig Hex To Values #") 85 | print("") 86 | while True: 87 | h = grab("Please type a CsrActiveConfig value (m for main menu): ") 88 | if not h: 89 | continue 90 | if h.lower() == "m": 91 | return 92 | elif h.lower() == "q": 93 | exit() 94 | has = hex_to_vals(h) 95 | if not len(has): 96 | print("\nNo values found.\n") 97 | else: 98 | print("\nActive values:\n\n{}\n".format("\n".join(has))) 99 | 100 | def v_to_h(): 101 | # Create a dict with all values unchecked 102 | toggle_dict = [] 103 | for x in sorted(csr_dict, key=lambda x:int(x)): 104 | toggle_dict.append({"value":int(x),"enabled":False,"name":csr_dict[x]}) 105 | while True: 106 | cls() 107 | print("# CsrActiveConfig Values To Hex #") 108 | print("") 109 | # Print them out 110 | for x,y in enumerate(toggle_dict,1): 111 | print("[{}] {}. {} - {}".format("#" if y["enabled"] else " ", x, y["name"],hex(y["value"]))) 112 | print("") 113 | # Add the values of the enabled together 114 | curr = 0 115 | for x in toggle_dict: 116 | if not x["enabled"]: 117 | continue 118 | curr += x["value"] 119 | print("Current: {}".format(hex(curr))) 120 | print("") 121 | print("A. Select All") 122 | print("N. Select None") 123 | print("M. Main Menu") 124 | print("Q. Quit") 125 | print("") 126 | print("Select options to toggle with comma-delimited lists (eg. 1,2,3,4,5)") 127 | print("") 128 | menu = grab("Please make your selection: ").lower() 129 | if not len(menu): 130 | continue 131 | if menu == "m": 132 | return 133 | elif menu == "q": 134 | exit() 135 | elif menu == "a": 136 | for x in toggle_dict: 137 | x["enabled"] = True 138 | continue 139 | elif menu == "n": 140 | for x in toggle_dict: 141 | x["enabled"] = False 142 | continue 143 | # Should be numbers 144 | try: 145 | nums = [int(x) for x in menu.replace(" ","").split(",")] 146 | for x in nums: 147 | if x < 1 or x > len(toggle_dict): 148 | # Out of bounds - skip 149 | continue 150 | toggle_dict[x-1]["enabled"] ^= True 151 | except: 152 | continue 153 | 154 | while True: 155 | main() 156 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 CorpNewt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CsrDecode 2 | Small py script to show what different CsrActiveConfig values enable/disable 3 | --------------------------------------------------------------------------------