zencleaner 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- zencleaner-1.0.0/LICENSE +21 -0
- zencleaner-1.0.0/MANIFEST.in +15 -0
- zencleaner-1.0.0/PKG-INFO +90 -0
- zencleaner-1.0.0/README.md +62 -0
- zencleaner-1.0.0/pyproject.toml +45 -0
- zencleaner-1.0.0/setup.cfg +4 -0
- zencleaner-1.0.0/zencleaner/__init__.py +1 -0
- zencleaner-1.0.0/zencleaner/cleaner.py +387 -0
- zencleaner-1.0.0/zencleaner/cleaner_forensic.py +160 -0
- zencleaner-1.0.0/zencleaner/cleaner_string.py +30 -0
- zencleaner-1.0.0/zencleaner/cleaner_system.py +257 -0
- zencleaner-1.0.0/zencleaner/cli.py +123 -0
- zencleaner-1.0.0/zencleaner/hwid.py +51 -0
- zencleaner-1.0.0/zencleaner/keygen_app.py +352 -0
- zencleaner-1.0.0/zencleaner/license_db.py +440 -0
- zencleaner-1.0.0/zencleaner/server.py +298 -0
- zencleaner-1.0.0/zencleaner/templates/index.html +1420 -0
- zencleaner-1.0.0/zencleaner/trace_scanner.py +890 -0
- zencleaner-1.0.0/zencleaner/webhook_logger.py +121 -0
- zencleaner-1.0.0/zencleaner.egg-info/PKG-INFO +90 -0
- zencleaner-1.0.0/zencleaner.egg-info/SOURCES.txt +23 -0
- zencleaner-1.0.0/zencleaner.egg-info/dependency_links.txt +1 -0
- zencleaner-1.0.0/zencleaner.egg-info/entry_points.txt +3 -0
- zencleaner-1.0.0/zencleaner.egg-info/requires.txt +2 -0
- zencleaner-1.0.0/zencleaner.egg-info/top_level.txt +1 -0
zencleaner-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ZenCleaner
|
|
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.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
include LICENSE
|
|
2
|
+
include README.md
|
|
3
|
+
recursive-include zencleaner/templates *
|
|
4
|
+
recursive-include zencleaner/static *
|
|
5
|
+
global-exclude *.py[cod] __pycache__
|
|
6
|
+
global-exclude *.exe *.spec
|
|
7
|
+
prune build
|
|
8
|
+
prune dist
|
|
9
|
+
prune node_modules
|
|
10
|
+
prune .pw_browsers
|
|
11
|
+
prune .pytest_cache
|
|
12
|
+
prune .test_lic
|
|
13
|
+
prune .venv
|
|
14
|
+
prune tests
|
|
15
|
+
prune zenkeygen-cs
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: zencleaner
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: ZenCleaner - type 'zencleaner' in your terminal to open a localhost web UI that actually cleans your PC.
|
|
5
|
+
Author: ZenCleaner
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/zencleaner/zencleaner
|
|
8
|
+
Keywords: pc-cleaner,windows,privacy,temp-files,localhost,flask,system-cleaner
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Environment :: Web Environment
|
|
11
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: System :: Systems Administration
|
|
21
|
+
Classifier: Topic :: Utilities
|
|
22
|
+
Requires-Python: >=3.9
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: flask>=3.0
|
|
26
|
+
Requires-Dist: flask-cors>=4.0
|
|
27
|
+
Dynamic: license-file
|
|
28
|
+
|
|
29
|
+
# ZenCleaner ๐งน
|
|
30
|
+
|
|
31
|
+
> **`pip install zencleaner`** โ type **`zencleaner`** in your terminal โ a localhost web UI opens โ click buttons โ it actually cleans your PC.
|
|
32
|
+
|
|
33
|
+
The website is just the remote control. The real work happens **on your own PC** via a tiny local server bound to `127.0.0.1` โ nothing is sent to the internet.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Quick start (Windows)
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install zencleaner
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Open a **new** terminal and type:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
zencleaner
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Your browser opens automatically at `http://127.0.0.1:8765` with the ZenCleaner web UI.
|
|
50
|
+
|
|
51
|
+
## What it can clean
|
|
52
|
+
|
|
53
|
+
| Task | What it does |
|
|
54
|
+
|---|---|
|
|
55
|
+
| Temp Files | `%TEMP%`, `C:\Windows\Temp` |
|
|
56
|
+
| Prefetch | `C:\Windows\Prefetch` (admin only) |
|
|
57
|
+
| Recycle Bin | Empty recycle bin |
|
|
58
|
+
| Registry MRU | RunMRU, RecentDocs, ComDlg32 (safe keys only) |
|
|
59
|
+
| DNS Cache | `ipconfig /flushdns` |
|
|
60
|
+
| Clean All | All of the above at once |
|
|
61
|
+
|
|
62
|
+
## Command-line options
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
zencleaner --help
|
|
66
|
+
|
|
67
|
+
--port PORT Port to run on (default 8765)
|
|
68
|
+
--no-browser Don't auto-open the browser
|
|
69
|
+
--host HOST Bind address (default 127.0.0.1 โ localhost only)
|
|
70
|
+
--no-elevate Skip the Windows UAC admin prompt
|
|
71
|
+
--no-auto-kill Don't kill an old ZenCleaner already on this port
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Admin rights
|
|
75
|
+
|
|
76
|
+
Some tasks (Prefetch, Registry, Forensic) need Windows Admin. On startup ZenCleaner shows a **UAC prompt** โ accept it for full power, or cancel/click `--no-elevate` and the UI still works with admin-only tasks disabled.
|
|
77
|
+
|
|
78
|
+
## Security
|
|
79
|
+
|
|
80
|
+
- Server binds to `127.0.0.1` only โ **nobody on your network or the internet can reach it**.
|
|
81
|
+
- No telemetry, no data collection, no outbound calls.
|
|
82
|
+
- Every clean action is a real Python function running locally on your machine.
|
|
83
|
+
|
|
84
|
+
## Stop it
|
|
85
|
+
|
|
86
|
+
Press `Ctrl+C` in the terminal. The localhost site stops instantly.
|
|
87
|
+
|
|
88
|
+
## License
|
|
89
|
+
|
|
90
|
+
MIT โ see [LICENSE](LICENSE)
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# ZenCleaner ๐งน
|
|
2
|
+
|
|
3
|
+
> **`pip install zencleaner`** โ type **`zencleaner`** in your terminal โ a localhost web UI opens โ click buttons โ it actually cleans your PC.
|
|
4
|
+
|
|
5
|
+
The website is just the remote control. The real work happens **on your own PC** via a tiny local server bound to `127.0.0.1` โ nothing is sent to the internet.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Quick start (Windows)
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install zencleaner
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Open a **new** terminal and type:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
zencleaner
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Your browser opens automatically at `http://127.0.0.1:8765` with the ZenCleaner web UI.
|
|
22
|
+
|
|
23
|
+
## What it can clean
|
|
24
|
+
|
|
25
|
+
| Task | What it does |
|
|
26
|
+
|---|---|
|
|
27
|
+
| Temp Files | `%TEMP%`, `C:\Windows\Temp` |
|
|
28
|
+
| Prefetch | `C:\Windows\Prefetch` (admin only) |
|
|
29
|
+
| Recycle Bin | Empty recycle bin |
|
|
30
|
+
| Registry MRU | RunMRU, RecentDocs, ComDlg32 (safe keys only) |
|
|
31
|
+
| DNS Cache | `ipconfig /flushdns` |
|
|
32
|
+
| Clean All | All of the above at once |
|
|
33
|
+
|
|
34
|
+
## Command-line options
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
zencleaner --help
|
|
38
|
+
|
|
39
|
+
--port PORT Port to run on (default 8765)
|
|
40
|
+
--no-browser Don't auto-open the browser
|
|
41
|
+
--host HOST Bind address (default 127.0.0.1 โ localhost only)
|
|
42
|
+
--no-elevate Skip the Windows UAC admin prompt
|
|
43
|
+
--no-auto-kill Don't kill an old ZenCleaner already on this port
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Admin rights
|
|
47
|
+
|
|
48
|
+
Some tasks (Prefetch, Registry, Forensic) need Windows Admin. On startup ZenCleaner shows a **UAC prompt** โ accept it for full power, or cancel/click `--no-elevate` and the UI still works with admin-only tasks disabled.
|
|
49
|
+
|
|
50
|
+
## Security
|
|
51
|
+
|
|
52
|
+
- Server binds to `127.0.0.1` only โ **nobody on your network or the internet can reach it**.
|
|
53
|
+
- No telemetry, no data collection, no outbound calls.
|
|
54
|
+
- Every clean action is a real Python function running locally on your machine.
|
|
55
|
+
|
|
56
|
+
## Stop it
|
|
57
|
+
|
|
58
|
+
Press `Ctrl+C` in the terminal. The localhost site stops instantly.
|
|
59
|
+
|
|
60
|
+
## License
|
|
61
|
+
|
|
62
|
+
MIT โ see [LICENSE](LICENSE)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "zencleaner"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "ZenCleaner - type 'zencleaner' in your terminal to open a localhost web UI that actually cleans your PC."
|
|
9
|
+
authors = [{name="ZenCleaner"}]
|
|
10
|
+
readme = "README.md"
|
|
11
|
+
requires-python = ">=3.9"
|
|
12
|
+
license = {text = "MIT"}
|
|
13
|
+
keywords = ["pc-cleaner", "windows", "privacy", "temp-files", "localhost", "flask", "system-cleaner"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Environment :: Web Environment",
|
|
17
|
+
"Intended Audience :: End Users/Desktop",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Operating System :: Microsoft :: Windows",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.9",
|
|
22
|
+
"Programming Language :: Python :: 3.10",
|
|
23
|
+
"Programming Language :: Python :: 3.11",
|
|
24
|
+
"Programming Language :: Python :: 3.12",
|
|
25
|
+
"Programming Language :: Python :: 3.13",
|
|
26
|
+
"Topic :: System :: Systems Administration",
|
|
27
|
+
"Topic :: Utilities",
|
|
28
|
+
]
|
|
29
|
+
dependencies = [
|
|
30
|
+
"flask>=3.0",
|
|
31
|
+
"flask-cors>=4.0",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[project.urls]
|
|
35
|
+
Homepage = "https://github.com/zencleaner/zencleaner"
|
|
36
|
+
|
|
37
|
+
[project.scripts]
|
|
38
|
+
zencleaner = "zencleaner.cli:main"
|
|
39
|
+
zenkeygen = "zencleaner.keygen_app:main"
|
|
40
|
+
|
|
41
|
+
[tool.setuptools.packages.find]
|
|
42
|
+
include = ["zencleaner*"]
|
|
43
|
+
|
|
44
|
+
[tool.setuptools.package-data]
|
|
45
|
+
zencleaner = ["templates/*", "static/*"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.0.0"
|
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ZenCleaner forensic cleaner - all 20 buttons + string cleaner
|
|
3
|
+
Each function returns {success, message, details}
|
|
4
|
+
"""
|
|
5
|
+
import os, shutil, subprocess, sys, glob, sqlite3, pathlib, re, json, time
|
|
6
|
+
import ctypes
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
def is_admin():
|
|
10
|
+
try:
|
|
11
|
+
if ctypes.windll.shell32.IsUserAnAdmin() != 0:
|
|
12
|
+
return True
|
|
13
|
+
except: pass
|
|
14
|
+
try:
|
|
15
|
+
subprocess.check_call(["net","session"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
16
|
+
return True
|
|
17
|
+
except: return False
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def clean_memory_address(process_id, memory_address, length=100):
|
|
21
|
+
try:
|
|
22
|
+
process_id = int(process_id)
|
|
23
|
+
length = max(1, int(length))
|
|
24
|
+
except (TypeError, ValueError):
|
|
25
|
+
return {"success": False, "message": "Process ID and length must be numeric.", "details": {}}
|
|
26
|
+
|
|
27
|
+
try:
|
|
28
|
+
if isinstance(memory_address, str):
|
|
29
|
+
value = memory_address.strip()
|
|
30
|
+
if value.lower().startswith("0x"):
|
|
31
|
+
base = 16
|
|
32
|
+
value = value[2:]
|
|
33
|
+
else:
|
|
34
|
+
base = 10
|
|
35
|
+
address = int(value, base)
|
|
36
|
+
else:
|
|
37
|
+
address = int(memory_address)
|
|
38
|
+
except (TypeError, ValueError):
|
|
39
|
+
return {"success": False, "message": "Memory address is invalid. Use a decimal or hex value.", "details": {}}
|
|
40
|
+
|
|
41
|
+
try:
|
|
42
|
+
kernel32 = ctypes.windll.kernel32
|
|
43
|
+
handle = kernel32.OpenProcess(0x0010 | 0x0008 | 0x0400, False, process_id)
|
|
44
|
+
if not handle:
|
|
45
|
+
return {"success": False, "message": f"Unable to open process {process_id}.", "details": {"process_id": process_id}}
|
|
46
|
+
|
|
47
|
+
buffer = (ctypes.c_byte * length)()
|
|
48
|
+
bytes_read = ctypes.c_size_t()
|
|
49
|
+
if not kernel32.ReadProcessMemory(handle, ctypes.c_void_p(address), buffer, length, ctypes.byref(bytes_read)):
|
|
50
|
+
kernel32.CloseHandle(handle)
|
|
51
|
+
return {"success": False, "message": "ReadProcessMemory failed. Access may be denied or the address is invalid.", "details": {"process_id": process_id, "address": hex(address), "length": length}}
|
|
52
|
+
|
|
53
|
+
zeroes = (ctypes.c_byte * length)()
|
|
54
|
+
if not kernel32.WriteProcessMemory(handle, ctypes.c_void_p(address), zeroes, length, None):
|
|
55
|
+
kernel32.CloseHandle(handle)
|
|
56
|
+
return {"success": False, "message": "WriteProcessMemory failed. The process may not allow writes.", "details": {"process_id": process_id, "address": hex(address), "length": length}}
|
|
57
|
+
|
|
58
|
+
kernel32.CloseHandle(handle)
|
|
59
|
+
return {
|
|
60
|
+
"success": True,
|
|
61
|
+
"message": f"Memory cleared at {hex(address)} for process {process_id}.",
|
|
62
|
+
"details": {"process_id": process_id, "address": hex(address), "length": length},
|
|
63
|
+
}
|
|
64
|
+
except Exception as exc:
|
|
65
|
+
return {"success": False, "message": str(exc), "details": {"process_id": process_id, "address": hex(address), "length": length}}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def clean_string(text, opts=None):
|
|
69
|
+
from .cleaner_string import string_clean
|
|
70
|
+
return string_clean(text, opts or {})
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def clean_name(name):
|
|
74
|
+
if name is None:
|
|
75
|
+
return {"success": False, "message": "Please provide a file or executable name.", "details": {}}
|
|
76
|
+
|
|
77
|
+
target = str(name).strip()
|
|
78
|
+
if not target:
|
|
79
|
+
return {"success": False, "message": "Please provide a file or executable name.", "details": {}}
|
|
80
|
+
|
|
81
|
+
target = os.path.basename(target)
|
|
82
|
+
if not target:
|
|
83
|
+
return {"success": False, "message": "Please provide a valid file or executable name.", "details": {}}
|
|
84
|
+
|
|
85
|
+
candidate_base = target.lower()
|
|
86
|
+
candidate_stem = os.path.splitext(candidate_base)[0]
|
|
87
|
+
candidate_names = {candidate_base}
|
|
88
|
+
if candidate_stem:
|
|
89
|
+
candidate_names.add(candidate_stem)
|
|
90
|
+
if not candidate_base.endswith(".exe"):
|
|
91
|
+
candidate_names.add(f"{candidate_base}.exe")
|
|
92
|
+
if candidate_stem and not candidate_stem.endswith(".exe"):
|
|
93
|
+
candidate_names.add(f"{candidate_stem}.exe")
|
|
94
|
+
search_terms = tuple(sorted({candidate_base, candidate_stem} - {""}))
|
|
95
|
+
|
|
96
|
+
roots = []
|
|
97
|
+
for env_name in ["DESKTOP", "USERPROFILE", "HOME", "TEMP", "TMP", "LOCALAPPDATA", "APPDATA", "PROGRAMDATA"]:
|
|
98
|
+
value = os.environ.get(env_name)
|
|
99
|
+
if value:
|
|
100
|
+
roots.append(value)
|
|
101
|
+
roots.extend([
|
|
102
|
+
os.path.join(os.environ.get("USERPROFILE", ""), "Desktop"),
|
|
103
|
+
os.path.join(os.environ.get("USERPROFILE", ""), "Downloads"),
|
|
104
|
+
os.path.join(os.environ.get("USERPROFILE", ""), "Documents"),
|
|
105
|
+
os.path.join(os.environ.get("LOCALAPPDATA", ""), "Temp"),
|
|
106
|
+
r"C:\Windows\Temp",
|
|
107
|
+
r"C:\Temp",
|
|
108
|
+
r"C:\Program Files",
|
|
109
|
+
r"C:\Program Files (x86)",
|
|
110
|
+
r"C:\Users",
|
|
111
|
+
r"C:\Windows",
|
|
112
|
+
])
|
|
113
|
+
roots = list(dict.fromkeys([r for r in roots if r]))
|
|
114
|
+
|
|
115
|
+
removed = []
|
|
116
|
+
seen = set()
|
|
117
|
+
|
|
118
|
+
def matches_candidate(filename):
|
|
119
|
+
lower_name = filename.lower()
|
|
120
|
+
if lower_name in candidate_names:
|
|
121
|
+
return True
|
|
122
|
+
if candidate_stem and candidate_stem in lower_name:
|
|
123
|
+
return True
|
|
124
|
+
return False
|
|
125
|
+
|
|
126
|
+
def delete_path(path):
|
|
127
|
+
if path in seen:
|
|
128
|
+
return False
|
|
129
|
+
try:
|
|
130
|
+
if os.path.isdir(path):
|
|
131
|
+
shutil.rmtree(path)
|
|
132
|
+
else:
|
|
133
|
+
os.remove(path)
|
|
134
|
+
seen.add(path)
|
|
135
|
+
removed.append(path)
|
|
136
|
+
return True
|
|
137
|
+
except OSError:
|
|
138
|
+
return False
|
|
139
|
+
|
|
140
|
+
def contains_target_string(path):
|
|
141
|
+
try:
|
|
142
|
+
if not os.path.isfile(path):
|
|
143
|
+
return False
|
|
144
|
+
if os.path.getsize(path) > 2 * 1024 * 1024:
|
|
145
|
+
return False
|
|
146
|
+
with open(path, "rb") as handle:
|
|
147
|
+
data = handle.read()
|
|
148
|
+
except OSError:
|
|
149
|
+
return False
|
|
150
|
+
|
|
151
|
+
needle = candidate_base.encode("utf-8", "ignore")
|
|
152
|
+
lower = data.lower()
|
|
153
|
+
if needle in lower:
|
|
154
|
+
return True
|
|
155
|
+
for term in search_terms:
|
|
156
|
+
term_bytes = term.encode("utf-8", "ignore")
|
|
157
|
+
if term_bytes and term_bytes in lower:
|
|
158
|
+
return True
|
|
159
|
+
return False
|
|
160
|
+
|
|
161
|
+
try:
|
|
162
|
+
process_name = os.path.splitext(target)[0]
|
|
163
|
+
subprocess.run(["taskkill", "/F", "/IM", f"{process_name}.exe"], capture_output=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=False)
|
|
164
|
+
except Exception:
|
|
165
|
+
pass
|
|
166
|
+
|
|
167
|
+
for root in roots:
|
|
168
|
+
if not os.path.isdir(root):
|
|
169
|
+
continue
|
|
170
|
+
for current_root, dirnames, filenames in os.walk(root):
|
|
171
|
+
for dirname in list(dirnames):
|
|
172
|
+
full_path = os.path.join(current_root, dirname)
|
|
173
|
+
if matches_candidate(dirname):
|
|
174
|
+
delete_path(full_path)
|
|
175
|
+
for filename in filenames:
|
|
176
|
+
full_path = os.path.join(current_root, filename)
|
|
177
|
+
if matches_candidate(filename):
|
|
178
|
+
delete_path(full_path)
|
|
179
|
+
continue
|
|
180
|
+
if contains_target_string(full_path):
|
|
181
|
+
delete_path(full_path)
|
|
182
|
+
continue
|
|
183
|
+
|
|
184
|
+
try:
|
|
185
|
+
import winreg
|
|
186
|
+
registry_roots = [
|
|
187
|
+
(winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Explorer\RecentDocs"),
|
|
188
|
+
(winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU"),
|
|
189
|
+
(winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\OpenSavePidlMRU"),
|
|
190
|
+
(winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\LastVisitedPidlMRU"),
|
|
191
|
+
(winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist"),
|
|
192
|
+
(winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Explorer\WordWheelQuery"),
|
|
193
|
+
(winreg.HKEY_CURRENT_USER, r"Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\BagMRU"),
|
|
194
|
+
(winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\Windows\CurrentVersion\Run"),
|
|
195
|
+
]
|
|
196
|
+
for hive, path in registry_roots:
|
|
197
|
+
try:
|
|
198
|
+
key = winreg.OpenKey(hive, path, 0, winreg.KEY_READ)
|
|
199
|
+
index = 0
|
|
200
|
+
while True:
|
|
201
|
+
try:
|
|
202
|
+
name, value, _ = winreg.EnumValue(key, index)
|
|
203
|
+
index += 1
|
|
204
|
+
combined = f"{name} {value}".lower()
|
|
205
|
+
if candidate_base in combined or any(term and term in combined for term in search_terms):
|
|
206
|
+
try:
|
|
207
|
+
winreg.DeleteValue(key, name)
|
|
208
|
+
except Exception:
|
|
209
|
+
pass
|
|
210
|
+
except OSError:
|
|
211
|
+
break
|
|
212
|
+
winreg.CloseKey(key)
|
|
213
|
+
except OSError:
|
|
214
|
+
pass
|
|
215
|
+
except Exception:
|
|
216
|
+
pass
|
|
217
|
+
|
|
218
|
+
if not removed:
|
|
219
|
+
return {"success": False, "message": f"No matching file or trace for '{target}' was found.", "details": {"removed": 0, "target": target}}
|
|
220
|
+
|
|
221
|
+
return {"success": True, "message": f"Name cleanup complete: {len(removed)} match(es) removed for '{target}'.", "details": {"removed": len(removed), "target": target, "paths": removed[:20]}}
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def clean_temp():
|
|
225
|
+
return clean_windows_temp()
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def clean_recycle_bin():
|
|
229
|
+
try:
|
|
230
|
+
result = subprocess.run(
|
|
231
|
+
["powershell", "-NoProfile", "-Command", "Clear-RecycleBin -Force -ErrorAction SilentlyContinue"],
|
|
232
|
+
capture_output=True,
|
|
233
|
+
text=True,
|
|
234
|
+
timeout=20,
|
|
235
|
+
)
|
|
236
|
+
if result.returncode in (0, 1):
|
|
237
|
+
return {"success": True, "message": "Recycle Bin cleared.", "details": {}}
|
|
238
|
+
detail = (result.stderr or result.stdout).strip() or "Recycle Bin cleanup failed."
|
|
239
|
+
return {"success": False, "message": detail, "details": {}}
|
|
240
|
+
except Exception as exc:
|
|
241
|
+
return {"success": False, "message": str(exc), "details": {}}
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def clean_registry_junk():
|
|
245
|
+
import winreg
|
|
246
|
+
cleaned = 0
|
|
247
|
+
safe_paths = [
|
|
248
|
+
r"Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU",
|
|
249
|
+
r"Software\Microsoft\Windows\CurrentVersion\Explorer\RecentDocs",
|
|
250
|
+
r"Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\LastVisitedPidlMRU",
|
|
251
|
+
r"Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\OpenSavePidlMRU",
|
|
252
|
+
r"Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\OpenSaveMRU",
|
|
253
|
+
r"Software\Microsoft\Windows\CurrentVersion\Explorer\WordWheelQuery",
|
|
254
|
+
]
|
|
255
|
+
for path in safe_paths:
|
|
256
|
+
try:
|
|
257
|
+
cleaned += _clean_reg_values(winreg.HKEY_CURRENT_USER, path)[0]
|
|
258
|
+
winreg.DeleteKey(winreg.HKEY_CURRENT_USER, path)
|
|
259
|
+
except Exception:
|
|
260
|
+
pass
|
|
261
|
+
return {"success": True, "message": f"Registry junk cleared: {cleaned} entries removed.", "details": {"cleaned": cleaned}}
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def quick_health_scan():
|
|
265
|
+
temp_mb = 0.0
|
|
266
|
+
for folder in [
|
|
267
|
+
os.environ.get("TEMP", ""),
|
|
268
|
+
os.environ.get("TMP", ""),
|
|
269
|
+
r"C:\Windows\Temp",
|
|
270
|
+
os.path.join(os.environ.get("LOCALAPPDATA", ""), "Temp"),
|
|
271
|
+
]:
|
|
272
|
+
if not folder or not os.path.isdir(folder):
|
|
273
|
+
continue
|
|
274
|
+
for root, _, files in os.walk(folder):
|
|
275
|
+
for filename in files:
|
|
276
|
+
try:
|
|
277
|
+
temp_mb += os.path.getsize(os.path.join(root, filename)) / (1024 * 1024)
|
|
278
|
+
except OSError:
|
|
279
|
+
pass
|
|
280
|
+
free_gb = shutil.disk_usage("C:\\").free / (1024 ** 3)
|
|
281
|
+
return {"temp_mb": round(temp_mb, 1), "free_gb": round(free_gb, 2), "is_admin": is_admin()}
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def _del_files(pattern, recursive=False):
|
|
285
|
+
c=0; f=0; sz=0
|
|
286
|
+
import glob as _g
|
|
287
|
+
for p in _g.glob(pattern, recursive=recursive):
|
|
288
|
+
try:
|
|
289
|
+
if os.path.isfile(p):
|
|
290
|
+
sz+=os.path.getsize(p); os.remove(p); c+=1
|
|
291
|
+
elif os.path.isdir(p):
|
|
292
|
+
sz+=sum(os.path.getsize(os.path.join(r,fn)) for r,_,fs in os.walk(p) for fn in fs if os.path.exists(os.path.join(r,fn)))
|
|
293
|
+
shutil.rmtree(p); c+=1
|
|
294
|
+
except: f+=1
|
|
295
|
+
return c,f,sz
|
|
296
|
+
|
|
297
|
+
def _clean_reg_values(hive, path):
|
|
298
|
+
import winreg
|
|
299
|
+
cleaned=0
|
|
300
|
+
try:
|
|
301
|
+
key=winreg.OpenKey(hive, path, 0, winreg.KEY_ALL_ACCESS)
|
|
302
|
+
vals=[]
|
|
303
|
+
i=0
|
|
304
|
+
try:
|
|
305
|
+
while True: vals.append(winreg.EnumValue(key,i)[0]); i+=1
|
|
306
|
+
except OSError: pass
|
|
307
|
+
for v in vals:
|
|
308
|
+
try: winreg.DeleteValue(key,v); cleaned+=1
|
|
309
|
+
except: pass
|
|
310
|
+
winreg.CloseKey(key)
|
|
311
|
+
return cleaned, None
|
|
312
|
+
except FileNotFoundError: return 0, "not found"
|
|
313
|
+
except PermissionError as e: return 0, str(e)
|
|
314
|
+
except Exception as e: return 0, str(e)
|
|
315
|
+
|
|
316
|
+
def _del_reg_tree(hive, path):
|
|
317
|
+
import winreg
|
|
318
|
+
cleaned=0
|
|
319
|
+
try:
|
|
320
|
+
key=winreg.OpenKey(hive, path, 0, winreg.KEY_READ|winreg.KEY_WRITE)
|
|
321
|
+
subs=[]
|
|
322
|
+
i=0
|
|
323
|
+
try:
|
|
324
|
+
while True: subs.append(winreg.EnumKey(key,i)); i+=1
|
|
325
|
+
except OSError: pass
|
|
326
|
+
winreg.CloseKey(key)
|
|
327
|
+
for s in subs:
|
|
328
|
+
_del_reg_tree(hive, path+"\\"+s)
|
|
329
|
+
try: winreg.DeleteKey(hive, path); cleaned+=1
|
|
330
|
+
except: pass
|
|
331
|
+
except FileNotFoundError: pass
|
|
332
|
+
except Exception: pass
|
|
333
|
+
return cleaned
|
|
334
|
+
|
|
335
|
+
def clean_dns_cache():
|
|
336
|
+
try:
|
|
337
|
+
subprocess.run(["ipconfig","/flushdns"], capture_output=True, timeout=10)
|
|
338
|
+
return {"success":True,"message":"DNS cache flushed.","details":{}}
|
|
339
|
+
except Exception as e: return {"success":False,"message":str(e),"details":{}}
|
|
340
|
+
|
|
341
|
+
def clean_prefetch():
|
|
342
|
+
if not is_admin(): return {"success":False,"message":"Prefetch requires Admin.","details":{}}
|
|
343
|
+
folder=r"C:\Windows\Prefetch"
|
|
344
|
+
if not os.path.isdir(folder): return {"success":False,"message":"Prefetch folder not found.","details":{}}
|
|
345
|
+
c,f,_=_del_files(os.path.join(folder,"*"))
|
|
346
|
+
return {"success":True,"message":f"Prefetch cleaned: {c} files, {f} skipped.","details":{"cleaned":c,"failed":f}}
|
|
347
|
+
|
|
348
|
+
def clean_windows_temp():
|
|
349
|
+
c_tot=0; f_tot=0; sz_tot=0
|
|
350
|
+
for folder in [os.environ.get("TEMP",""), os.environ.get("TMP",""), r"C:\Windows\Temp", os.path.join(os.environ.get("LOCALAPPDATA",""),"Temp")]:
|
|
351
|
+
if not folder or not os.path.isdir(folder): continue
|
|
352
|
+
c,f,sz=_del_files(os.path.join(folder,"*"))
|
|
353
|
+
c_tot+=c; f_tot+=f; sz_tot+=sz
|
|
354
|
+
return {"success":True,"message":f"Windows Temp cleaned: {c_tot} items, {sz_tot/1024/1024:.1f} MB, {f_tot} locked.","details":{"cleaned":c_tot,"failed":f_tot}}
|
|
355
|
+
|
|
356
|
+
def clean_network_usage():
|
|
357
|
+
freed=0; note=[]
|
|
358
|
+
if is_admin():
|
|
359
|
+
try: subprocess.run(["net","stop","DPS","/y"], capture_output=True, timeout=8); time.sleep(0.5)
|
|
360
|
+
except: pass
|
|
361
|
+
for p in [r"C:\Windows\System32\sru\SRUDB.dat", r"C:\Windows\System32\sru\SRUDB.dat.bak"]:
|
|
362
|
+
try:
|
|
363
|
+
if os.path.exists(p): os.remove(p); note.append(Path(p).name+" deleted")
|
|
364
|
+
except: note.append(Path(p).name+" locked")
|
|
365
|
+
try: subprocess.run(["net","start","DPS"], capture_output=True, timeout=8)
|
|
366
|
+
except: pass
|
|
367
|
+
else: note.append("SRUDB needs Admin")
|
|
368
|
+
return {"success":True,"message":"Network Usage cleaned. "+"; ".join(note) if note else "Network Usage cleaned.","details":{}}
|
|
369
|
+
|
|
370
|
+
def clean_data_usage():
|
|
371
|
+
return clean_network_usage()
|
|
372
|
+
|
|
373
|
+
def clean_shell_bags():
|
|
374
|
+
import winreg
|
|
375
|
+
cleaned=0
|
|
376
|
+
for path in [r"Software\Microsoft\Windows\Shell\BagMRU", r"Software\Microsoft\Windows\Shell\Bags", r"Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\BagMRU", r"Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\Bags"]:
|
|
377
|
+
try: _del_reg_tree(winreg.HKEY_CURRENT_USER, path); cleaned+=1
|
|
378
|
+
except: pass
|
|
379
|
+
return {"success":True,"message":f"Shell Bags cleaned: {cleaned} keys cleared.","details":{"cleaned":cleaned}}
|
|
380
|
+
|
|
381
|
+
def clean_windows_timeline():
|
|
382
|
+
c,f,_=_del_files(os.path.join(os.environ.get("LOCALAPPDATA",""), r"ConnectedDevicesPlatform\*\ActivitiesCache.db"))
|
|
383
|
+
try:
|
|
384
|
+
import winreg
|
|
385
|
+
_clean_reg_values(winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\ActivityHistory")
|
|
386
|
+
except: pass
|
|
387
|
+
return {"success":True,"message":f"Timeline cleaned: {c} db files removed.","details":{"cleaned":c}}
|