atomicshop 2.11.49__py3-none-any.whl → 2.12.1__py3-none-any.whl
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.
Potentially problematic release.
This version of atomicshop might be problematic. Click here for more details.
- atomicshop/__init__.py +1 -1
- atomicshop/addons/mains/__pycache__/install_fibratus_windows.cpython-312.pyc +0 -0
- atomicshop/addons/mains/install_fibratus_windows.py +9 -0
- atomicshop/appointment_management.py +5 -3
- atomicshop/file_io/csvs.py +66 -12
- atomicshop/filesystem.py +46 -0
- atomicshop/mitm/statistic_analyzer.py +3 -1
- atomicshop/permissions.py +29 -0
- atomicshop/web.py +1 -0
- atomicshop/wrappers/factw/postgresql/firmware.py +1 -1
- atomicshop/wrappers/factw/rest/firmware.py +1 -1
- atomicshop/wrappers/fibratusw/__init__.py +0 -0
- atomicshop/wrappers/fibratusw/install.py +81 -0
- atomicshop/wrappers/githubw.py +60 -11
- atomicshop/wrappers/loggingw/reading.py +84 -7
- atomicshop/wrappers/msiw.py +60 -0
- {atomicshop-2.11.49.dist-info → atomicshop-2.12.1.dist-info}/METADATA +1 -1
- {atomicshop-2.11.49.dist-info → atomicshop-2.12.1.dist-info}/RECORD +21 -16
- {atomicshop-2.11.49.dist-info → atomicshop-2.12.1.dist-info}/LICENSE.txt +0 -0
- {atomicshop-2.11.49.dist-info → atomicshop-2.12.1.dist-info}/WHEEL +0 -0
- {atomicshop-2.11.49.dist-info → atomicshop-2.12.1.dist-info}/top_level.txt +0 -0
atomicshop/__init__.py
CHANGED
|
@@ -5,7 +5,7 @@ from .print_api import print_api
|
|
|
5
5
|
from .basics.lists import remove_duplicates
|
|
6
6
|
from .datetimes import convert_single_digit_to_zero_padded, create_date_range_for_year, \
|
|
7
7
|
create_date_range_for_year_month
|
|
8
|
-
from .file_io
|
|
8
|
+
from .file_io import csvs
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class AppointmentManager:
|
|
@@ -38,7 +38,8 @@ class AppointmentManager:
|
|
|
38
38
|
def read_latest_date_csv(self):
|
|
39
39
|
try:
|
|
40
40
|
# Read the csv to list of dicts.
|
|
41
|
-
csv_list, _ =
|
|
41
|
+
csv_list, _ = csvs.read_csv_to_list_of_dicts_by_header(
|
|
42
|
+
file_path=self.latest_date_to_check_filepath, raise_exception=True)
|
|
42
43
|
# It has only 1 line, so get it to dict.
|
|
43
44
|
latest_date_dict = csv_list[0]
|
|
44
45
|
|
|
@@ -100,7 +101,8 @@ class BlacklistEngine:
|
|
|
100
101
|
def read_blacklist_csv(self) -> None:
|
|
101
102
|
try:
|
|
102
103
|
# Read the csv to list of dicts.
|
|
103
|
-
csv_list, _ =
|
|
104
|
+
csv_list, _ = csvs.read_csv_to_list_of_dicts_by_header(
|
|
105
|
+
file_path=self.blacklist_dates_filepath, raise_exception=True)
|
|
104
106
|
|
|
105
107
|
daterange = None
|
|
106
108
|
# Iterate through all the rows.
|
atomicshop/file_io/csvs.py
CHANGED
|
@@ -6,14 +6,25 @@ from . import file_io
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
@read_file_decorator
|
|
9
|
-
def
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
def read_csv_to_list_of_dicts_by_header(
|
|
10
|
+
file_path: str,
|
|
11
|
+
file_mode: str = 'r',
|
|
12
|
+
encoding=None,
|
|
13
|
+
header: list = None,
|
|
14
|
+
file_object=None,
|
|
15
|
+
**kwargs
|
|
16
|
+
) -> Tuple[List, List | None]:
|
|
15
17
|
"""
|
|
16
18
|
Function to read csv file and output its contents as list of dictionaries for each row.
|
|
19
|
+
Each key of the dictionary is a header field.
|
|
20
|
+
|
|
21
|
+
Example:
|
|
22
|
+
CSV file:
|
|
23
|
+
name,age,city
|
|
24
|
+
John,25,New York
|
|
25
|
+
|
|
26
|
+
Output:
|
|
27
|
+
[{'name': 'John', 'age': '25', 'city': 'New York'}]
|
|
17
28
|
|
|
18
29
|
:param file_path: String with full file path to json file.
|
|
19
30
|
:param file_mode: string, file reading mode. Examples: 'r', 'rb'. Default is 'r'.
|
|
@@ -39,25 +50,68 @@ def read_csv_to_list(file_path: str,
|
|
|
39
50
|
return csv_list, header
|
|
40
51
|
|
|
41
52
|
|
|
42
|
-
|
|
53
|
+
@read_file_decorator
|
|
54
|
+
def read_csv_to_list_of_lists(
|
|
55
|
+
file_path: str,
|
|
56
|
+
file_mode: str = 'r',
|
|
57
|
+
encoding=None,
|
|
58
|
+
exclude_header_from_content: bool = False,
|
|
59
|
+
file_object=None,
|
|
60
|
+
**kwargs
|
|
61
|
+
) -> Tuple[List, List | None]:
|
|
62
|
+
"""
|
|
63
|
+
Function to read csv file and output its contents as list of lists for each row.
|
|
64
|
+
|
|
65
|
+
Example:
|
|
66
|
+
CSV file:
|
|
67
|
+
name,age,city
|
|
68
|
+
John,25,New York
|
|
69
|
+
|
|
70
|
+
Output:
|
|
71
|
+
[['name', 'age', 'city'], ['John', '25', 'New York']]
|
|
72
|
+
|
|
73
|
+
:param file_path: String with full file path to json file.
|
|
74
|
+
:param file_mode: string, file reading mode. Examples: 'r', 'rb'. Default is 'r'.
|
|
75
|
+
:param encoding: string, encoding of the file. Default is 'None'.
|
|
76
|
+
:param exclude_header_from_content: Boolean, if True, the header will be excluded from the content.
|
|
77
|
+
:param file_object: file object of the 'open()' function in the decorator. Decorator executes the 'with open()'
|
|
78
|
+
statement and passes to this function. That's why the default is 'None', since we get it from the decorator.
|
|
79
|
+
:param kwargs: Keyword arguments for 'read_file' function.
|
|
80
|
+
:return: list.
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
# Read CSV file to list of lists.
|
|
84
|
+
csv_reader = csv.reader(file_object)
|
|
85
|
+
|
|
86
|
+
csv_list = list(csv_reader)
|
|
87
|
+
header = csv_list[0]
|
|
88
|
+
|
|
89
|
+
if exclude_header_from_content:
|
|
90
|
+
csv_list.pop(0)
|
|
91
|
+
|
|
92
|
+
return csv_list, header
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def write_list_to_csv(file_path: str, content_list: list, mode: str = 'w') -> None:
|
|
43
96
|
"""
|
|
44
97
|
Function to write list object that each iteration of it contains dict object with same keys and different values.
|
|
45
98
|
|
|
46
|
-
:param
|
|
47
|
-
:param
|
|
99
|
+
:param file_path: Full file path to CSV file.
|
|
100
|
+
:param content_list: List object that each iteration contains dictionary with same keys and different values.
|
|
101
|
+
:param mode: String, file writing mode. Default is 'w'.
|
|
48
102
|
:return: None.
|
|
49
103
|
"""
|
|
50
104
|
|
|
51
|
-
with open(
|
|
105
|
+
with open(file_path, mode=mode) as csv_file:
|
|
52
106
|
# Create header from keys of the first dictionary in list.
|
|
53
|
-
header =
|
|
107
|
+
header = content_list[0].keys()
|
|
54
108
|
# Create CSV writer.
|
|
55
109
|
writer = csv.DictWriter(csv_file, fieldnames=header, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
|
|
56
110
|
|
|
57
111
|
# Write header.
|
|
58
112
|
writer.writeheader()
|
|
59
113
|
# Write list of dits as rows.
|
|
60
|
-
writer.writerows(
|
|
114
|
+
writer.writerows(content_list)
|
|
61
115
|
|
|
62
116
|
|
|
63
117
|
def get_header(file_path: str, print_kwargs: dict = None) -> list:
|
atomicshop/filesystem.py
CHANGED
|
@@ -6,6 +6,8 @@ import shutil
|
|
|
6
6
|
import stat
|
|
7
7
|
import errno
|
|
8
8
|
from contextlib import contextmanager
|
|
9
|
+
from typing import Literal
|
|
10
|
+
import tempfile
|
|
9
11
|
|
|
10
12
|
import psutil
|
|
11
13
|
|
|
@@ -115,6 +117,22 @@ def get_working_directory() -> str:
|
|
|
115
117
|
return str(Path.cwd())
|
|
116
118
|
|
|
117
119
|
|
|
120
|
+
def get_temp_directory() -> str:
|
|
121
|
+
"""
|
|
122
|
+
The function returns temporary directory of the system.
|
|
123
|
+
|
|
124
|
+
:return: string.
|
|
125
|
+
"""
|
|
126
|
+
|
|
127
|
+
# Get the temporary directory in 8.3 format
|
|
128
|
+
short_temp_dir = tempfile.gettempdir()
|
|
129
|
+
|
|
130
|
+
# Convert to the long path name
|
|
131
|
+
long_temp_dir = str(Path(short_temp_dir).resolve())
|
|
132
|
+
|
|
133
|
+
return long_temp_dir
|
|
134
|
+
|
|
135
|
+
|
|
118
136
|
def get_file_directory(file_path: str) -> str:
|
|
119
137
|
"""
|
|
120
138
|
The function will return directory of the file.
|
|
@@ -1273,3 +1291,31 @@ def is_file_open_by_process(file_path: str) -> bool:
|
|
|
1273
1291
|
continue
|
|
1274
1292
|
|
|
1275
1293
|
return False
|
|
1294
|
+
|
|
1295
|
+
|
|
1296
|
+
def get_download_directory(place: Literal['temp', 'script', 'working'] = 'temp', script_path: str = None) -> str:
|
|
1297
|
+
"""
|
|
1298
|
+
The function returns the default download directory based on place.
|
|
1299
|
+
|
|
1300
|
+
:param place: string,
|
|
1301
|
+
'temp', then the function will return the temporary directory.
|
|
1302
|
+
'script', then the function will return the directory of the script.
|
|
1303
|
+
'working', then the function will return the working directory.
|
|
1304
|
+
:param script_path: string, full path to the script.
|
|
1305
|
+
:return: string, full path to the default download directory.
|
|
1306
|
+
"""
|
|
1307
|
+
|
|
1308
|
+
if place == 'script' and script_path is None:
|
|
1309
|
+
raise ValueError("Script path must be specified if place is 'script'.")
|
|
1310
|
+
|
|
1311
|
+
# Get the download directory based on the operating system
|
|
1312
|
+
if place == 'script':
|
|
1313
|
+
download_directory = get_file_directory(script_path)
|
|
1314
|
+
elif place == 'working':
|
|
1315
|
+
download_directory = get_working_directory()
|
|
1316
|
+
elif place == 'temp':
|
|
1317
|
+
download_directory = get_temp_directory()
|
|
1318
|
+
else:
|
|
1319
|
+
raise ValueError("Invalid place specified.")
|
|
1320
|
+
|
|
1321
|
+
return download_directory
|
|
@@ -155,7 +155,9 @@ def analyze(main_file_path: str):
|
|
|
155
155
|
|
|
156
156
|
# Get the content from statistics files.
|
|
157
157
|
statistics_content: list = reading.get_logs(
|
|
158
|
-
config['statistic_files_path'],
|
|
158
|
+
config['statistic_files_path'],
|
|
159
|
+
pattern='statistics*.csv',
|
|
160
|
+
log_type='csv',
|
|
159
161
|
)
|
|
160
162
|
|
|
161
163
|
# Initialize loop.
|
atomicshop/permissions.py
CHANGED
|
@@ -108,3 +108,32 @@ def expand_user_path(user_name, path):
|
|
|
108
108
|
pwnam = pwd.getpwnam(user_name)
|
|
109
109
|
home_dir = pwnam.pw_dir
|
|
110
110
|
return path.replace("~", home_dir)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def unblock_file_windows(file_path):
|
|
114
|
+
"""
|
|
115
|
+
Unblock a file on Windows. This is used to unblock files downloaded from the internet.
|
|
116
|
+
When you Right-click then navigate to Properties, you will see the Unblock checkbox.
|
|
117
|
+
:param file_path:
|
|
118
|
+
:return:
|
|
119
|
+
"""
|
|
120
|
+
try:
|
|
121
|
+
subprocess.run(["powershell", "-Command", f"Unblock-File -Path '{file_path}'"], check=True)
|
|
122
|
+
print(f"Successfully unblocked the file: {file_path}")
|
|
123
|
+
except subprocess.CalledProcessError as e:
|
|
124
|
+
print(f"Failed to unblock the file: {file_path}\nError: {e}")
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def get_command_to_run_as_admin_windows(command: str) -> str:
|
|
128
|
+
"""
|
|
129
|
+
Function returns the command to run a command as administrator on Windows.
|
|
130
|
+
:param command: str, command to run.
|
|
131
|
+
:return: str, command to run as administrator.
|
|
132
|
+
"""
|
|
133
|
+
|
|
134
|
+
executable = command.split()[0]
|
|
135
|
+
command = (
|
|
136
|
+
f"powershell -Command "
|
|
137
|
+
f"\"Start-Process {executable} -ArgumentList '{' '.join(command.split()[1:])}' -Verb RunAs\"")
|
|
138
|
+
|
|
139
|
+
return command
|
atomicshop/web.py
CHANGED
|
@@ -174,6 +174,7 @@ def download(file_url: str, target_directory: str, file_name: str = None, **kwar
|
|
|
174
174
|
file_path: str = f'{target_directory}{os.sep}{file_name}'
|
|
175
175
|
|
|
176
176
|
print_api(f'Downloading: {file_url}', **kwargs)
|
|
177
|
+
print_api(f'To: {file_path}', **kwargs)
|
|
177
178
|
|
|
178
179
|
# In order to use 'urllib.request', it is not enough to 'import urllib', you need to 'import urllib.request'.
|
|
179
180
|
# Open the URL for data gathering.
|
|
File without changes
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import os.path
|
|
2
|
+
import subprocess
|
|
3
|
+
import time
|
|
4
|
+
from typing import Literal
|
|
5
|
+
|
|
6
|
+
from .. import githubw, msiw
|
|
7
|
+
from ... import filesystem
|
|
8
|
+
from ...print_api import print_api
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
DEFAULT_INSTALLATION_EXE_PATH = r"C:\Program Files\Fibratus\Bin\fibratus.exe"
|
|
12
|
+
WAIT_SECONDS_FOR_EXECUTABLE_TO_APPEAR_AFTER_INSTALLATION: float = 10
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def install_fibratus(
|
|
16
|
+
installation_file_download_directory: str = None,
|
|
17
|
+
place_to_download_file: Literal['working', 'temp', 'script'] = 'temp',
|
|
18
|
+
remove_file_after_installation: bool = False
|
|
19
|
+
):
|
|
20
|
+
"""
|
|
21
|
+
Download latest release from GitHub and install Fibratus.
|
|
22
|
+
:param installation_file_download_directory: Directory to download the installation file. If None, the download
|
|
23
|
+
directory will be automatically determined, by the 'place_to_download_file' parameter.
|
|
24
|
+
:param place_to_download_file: Where to download the installation file.
|
|
25
|
+
'working' is the working directory of the script.
|
|
26
|
+
'temp' is the temporary directory.
|
|
27
|
+
'script' is the directory of the script.
|
|
28
|
+
:param remove_file_after_installation: Whether to remove the installation file after installation.
|
|
29
|
+
:return:
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
if not installation_file_download_directory:
|
|
33
|
+
installation_file_download_directory = filesystem.get_download_directory(
|
|
34
|
+
place=place_to_download_file, script_path=__file__)
|
|
35
|
+
|
|
36
|
+
github_wrapper = githubw.GitHubWrapper(user_name='rabbitstack', repo_name='fibratus')
|
|
37
|
+
fibratus_setup_file_path: str = github_wrapper.download_latest_release(
|
|
38
|
+
target_directory=installation_file_download_directory,
|
|
39
|
+
string_pattern='*fibratus-*-amd64.msi',
|
|
40
|
+
exclude_string='slim')
|
|
41
|
+
|
|
42
|
+
# Install the MSI file
|
|
43
|
+
msiw.install_msi(
|
|
44
|
+
msi_path=fibratus_setup_file_path, exit_on_error=True, as_admin=True)
|
|
45
|
+
|
|
46
|
+
count = 0
|
|
47
|
+
while count != WAIT_SECONDS_FOR_EXECUTABLE_TO_APPEAR_AFTER_INSTALLATION:
|
|
48
|
+
if os.path.isfile(DEFAULT_INSTALLATION_EXE_PATH):
|
|
49
|
+
break
|
|
50
|
+
count += 1
|
|
51
|
+
time.sleep(1)
|
|
52
|
+
|
|
53
|
+
if count == WAIT_SECONDS_FOR_EXECUTABLE_TO_APPEAR_AFTER_INSTALLATION:
|
|
54
|
+
message = \
|
|
55
|
+
(f"Fibratus installation failed. The executable was not found after "
|
|
56
|
+
f"{str(WAIT_SECONDS_FOR_EXECUTABLE_TO_APPEAR_AFTER_INSTALLATION)} seconds.\n"
|
|
57
|
+
f"{DEFAULT_INSTALLATION_EXE_PATH}")
|
|
58
|
+
print_api(message, color="red")
|
|
59
|
+
|
|
60
|
+
result = None
|
|
61
|
+
# Check if the installation was successful
|
|
62
|
+
try:
|
|
63
|
+
result = subprocess.run([DEFAULT_INSTALLATION_EXE_PATH], capture_output=True, text=True)
|
|
64
|
+
except FileNotFoundError:
|
|
65
|
+
print_api("Fibratus executable not found.", color="red")
|
|
66
|
+
|
|
67
|
+
if result:
|
|
68
|
+
if result.returncode == 0:
|
|
69
|
+
print_api("Fibratus installed successfully. Please restart.", color="green")
|
|
70
|
+
else:
|
|
71
|
+
print_api("Fibratus installation failed.", color="red")
|
|
72
|
+
print_api(result.stderr)
|
|
73
|
+
raise Exception("Fibratus installation failed.")
|
|
74
|
+
else:
|
|
75
|
+
print_api("Fibratus executable not found.", color="red")
|
|
76
|
+
|
|
77
|
+
# Wait for the installation to finish before removing the file.
|
|
78
|
+
time.sleep(5)
|
|
79
|
+
|
|
80
|
+
if remove_file_after_installation:
|
|
81
|
+
filesystem.remove_file(fibratus_setup_file_path)
|
atomicshop/wrappers/githubw.py
CHANGED
|
@@ -3,6 +3,7 @@ import fnmatch
|
|
|
3
3
|
|
|
4
4
|
from .. import web, urls
|
|
5
5
|
from ..print_api import print_api
|
|
6
|
+
from ..basics import strings
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
class GitHubWrapper:
|
|
@@ -146,22 +147,17 @@ class GitHubWrapper:
|
|
|
146
147
|
archive_remove_first_directory=archive_remove_first_directory,
|
|
147
148
|
**kwargs)
|
|
148
149
|
|
|
149
|
-
def
|
|
150
|
+
def get_latest_release_url(
|
|
150
151
|
self,
|
|
151
|
-
target_directory: str,
|
|
152
152
|
string_pattern: str,
|
|
153
|
-
|
|
153
|
+
exclude_string: str = None,
|
|
154
154
|
**kwargs):
|
|
155
155
|
"""
|
|
156
|
-
This function will
|
|
157
|
-
leaving only the extracted folder.
|
|
158
|
-
:param target_directory: str, the target directory to download and extract the file.
|
|
156
|
+
This function will return the latest release url.
|
|
159
157
|
:param string_pattern: str, the string pattern to search in the latest release. Wildcards can be used.
|
|
160
|
-
:param
|
|
161
|
-
without first directory in the archive. Check reference in the
|
|
162
|
-
'archiver.zip.extract_archive_with_zipfile' function.
|
|
158
|
+
:param exclude_string: str, the string to exclude from the search. No wildcards can be used.
|
|
163
159
|
:param kwargs: dict, the print arguments for the 'print_api' function.
|
|
164
|
-
:return:
|
|
160
|
+
:return: str, the latest release url.
|
|
165
161
|
"""
|
|
166
162
|
|
|
167
163
|
# Get the 'assets' key of the latest release json.
|
|
@@ -172,6 +168,12 @@ class GitHubWrapper:
|
|
|
172
168
|
for single_dict in github_latest_releases_list:
|
|
173
169
|
download_urls.append(single_dict['browser_download_url'])
|
|
174
170
|
|
|
171
|
+
# Exclude urls against 'exclude_string'.
|
|
172
|
+
if exclude_string:
|
|
173
|
+
for download_url in download_urls:
|
|
174
|
+
if exclude_string in download_url:
|
|
175
|
+
download_urls.remove(download_url)
|
|
176
|
+
|
|
175
177
|
# Find urls against 'string_pattern'.
|
|
176
178
|
found_urls = fnmatch.filter(download_urls, string_pattern)
|
|
177
179
|
|
|
@@ -182,8 +184,55 @@ class GitHubWrapper:
|
|
|
182
184
|
f'{found_urls}'
|
|
183
185
|
print_api(message, color="red", error_type=True, **kwargs)
|
|
184
186
|
|
|
187
|
+
return found_urls[0]
|
|
188
|
+
|
|
189
|
+
def download_latest_release(
|
|
190
|
+
self,
|
|
191
|
+
target_directory: str,
|
|
192
|
+
string_pattern: str,
|
|
193
|
+
exclude_string: str = None,
|
|
194
|
+
**kwargs):
|
|
195
|
+
"""
|
|
196
|
+
This function will download the latest release from the GitHub repository.
|
|
197
|
+
:param target_directory: str, the target directory to download the file.
|
|
198
|
+
:param string_pattern: str, the string pattern to search in the latest release. Wildcards can be used.
|
|
199
|
+
:param exclude_string: str, the string to exclude from the search. No wildcards can be used.
|
|
200
|
+
The 'excluded_string' will be filtered before the 'string_pattern' entries.
|
|
201
|
+
:param kwargs: dict, the print arguments for the 'print_api' function.
|
|
202
|
+
:return:
|
|
203
|
+
"""
|
|
204
|
+
|
|
205
|
+
# Get the latest release url.
|
|
206
|
+
found_url = self.get_latest_release_url(string_pattern=string_pattern, exclude_string=exclude_string, **kwargs)
|
|
207
|
+
|
|
208
|
+
downloaded_file_path = web.download(file_url=found_url, target_directory=target_directory, **kwargs)
|
|
209
|
+
return downloaded_file_path
|
|
210
|
+
|
|
211
|
+
def download_and_extract_latest_release(
|
|
212
|
+
self,
|
|
213
|
+
target_directory: str,
|
|
214
|
+
string_pattern: str,
|
|
215
|
+
exclude_string: str = None,
|
|
216
|
+
archive_remove_first_directory: bool = False,
|
|
217
|
+
**kwargs):
|
|
218
|
+
"""
|
|
219
|
+
This function will download the latest release from the GitHub repository, extract the file and remove the file,
|
|
220
|
+
leaving only the extracted folder.
|
|
221
|
+
:param target_directory: str, the target directory to download and extract the file.
|
|
222
|
+
:param string_pattern: str, the string pattern to search in the latest release. Wildcards can be used.
|
|
223
|
+
:param exclude_string: str, the string to exclude from the search. No wildcards can be used.
|
|
224
|
+
:param archive_remove_first_directory: bool, sets if archive extract function will extract the archive
|
|
225
|
+
without first directory in the archive. Check reference in the
|
|
226
|
+
'archiver.zip.extract_archive_with_zipfile' function.
|
|
227
|
+
:param kwargs: dict, the print arguments for the 'print_api' function.
|
|
228
|
+
:return:
|
|
229
|
+
"""
|
|
230
|
+
|
|
231
|
+
# Get the latest release url.
|
|
232
|
+
found_url = self.get_latest_release_url(string_pattern=string_pattern, exclude_string=exclude_string, **kwargs)
|
|
233
|
+
|
|
185
234
|
web.download_and_extract_file(
|
|
186
|
-
file_url=
|
|
235
|
+
file_url=found_url,
|
|
187
236
|
target_directory=target_directory,
|
|
188
237
|
archive_remove_first_directory=archive_remove_first_directory,
|
|
189
238
|
**kwargs)
|
|
@@ -1,12 +1,84 @@
|
|
|
1
1
|
import os
|
|
2
2
|
from typing import Literal
|
|
3
|
+
from pathlib import Path
|
|
3
4
|
|
|
4
5
|
from ... import filesystem, datetimes
|
|
5
6
|
from ...file_io import csvs
|
|
6
7
|
|
|
7
8
|
|
|
9
|
+
def get_logs_paths(
|
|
10
|
+
log_files_directory_path: str = None,
|
|
11
|
+
log_file_path: str = None,
|
|
12
|
+
pattern: str = '*.*',
|
|
13
|
+
log_type: Literal['csv'] = 'csv',
|
|
14
|
+
latest_only: bool = False,
|
|
15
|
+
previous_day_only: bool = False
|
|
16
|
+
):
|
|
17
|
+
"""
|
|
18
|
+
This function gets the logs file paths from the directory. Supports rotating files to get the logs by time.
|
|
19
|
+
|
|
20
|
+
:param log_files_directory_path: Path to the log files. If specified, the function will get all the files from the
|
|
21
|
+
directory by the 'pattern'.
|
|
22
|
+
:param log_file_path: Path to the log file. If specified, the function will get the file and all the rotated logs
|
|
23
|
+
associated with this file. The 'pattern' will become the file name using the file name and extension.
|
|
24
|
+
|
|
25
|
+
Example:
|
|
26
|
+
log_file_path = 'C:/logs/test_log.csv'
|
|
27
|
+
|
|
28
|
+
# The function will get all the files that start with 'test_log' and have '.csv' extension:
|
|
29
|
+
pattern = 'test_log*.csv'
|
|
30
|
+
|
|
31
|
+
# The 'log_files_directory_path' will also be taken from the 'log_file_path':
|
|
32
|
+
log_files_directory_path = 'C:/logs'
|
|
33
|
+
:param pattern: Pattern to match the log files names.
|
|
34
|
+
Default pattern will match all the files.
|
|
35
|
+
:param log_type: Type of log to get.
|
|
36
|
+
:param latest_only: Boolean, if True, only the latest log file path will be returned.
|
|
37
|
+
:param previous_day_only: Boolean, if True, only the log file path from the previous day will be returned.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
if not log_files_directory_path and not log_file_path:
|
|
41
|
+
raise ValueError('Either "log_files_directory_path" or "log_file_path" must be specified.')
|
|
42
|
+
elif log_files_directory_path and log_file_path:
|
|
43
|
+
raise ValueError('Both "log_files_directory_path" and "log_file_path" cannot be specified at the same time.')
|
|
44
|
+
|
|
45
|
+
if log_type != 'csv':
|
|
46
|
+
raise ValueError('Only "csv" log type is supported.')
|
|
47
|
+
|
|
48
|
+
if latest_only and previous_day_only:
|
|
49
|
+
raise ValueError('Both "latest_only" and "previous_day_only" cannot be True at the same time.')
|
|
50
|
+
|
|
51
|
+
# If log file path is specified, get the pattern from the file name.
|
|
52
|
+
if log_file_path:
|
|
53
|
+
# Build the pattern.
|
|
54
|
+
log_file_name: str = Path(log_file_path).stem
|
|
55
|
+
log_file_extension: str = Path(log_file_path).suffix
|
|
56
|
+
pattern = f'{log_file_name}*{log_file_extension}'
|
|
57
|
+
|
|
58
|
+
# Get the directory path from the file path.
|
|
59
|
+
log_files_directory_path = Path(log_file_path).parent
|
|
60
|
+
|
|
61
|
+
# Get all the log file paths by the pattern.
|
|
62
|
+
logs_files: list = filesystem.get_file_paths_from_directory(
|
|
63
|
+
log_files_directory_path, file_name_check_pattern=pattern,
|
|
64
|
+
add_last_modified_time=True, sort_by_last_modified_time=True)
|
|
65
|
+
|
|
66
|
+
if latest_only:
|
|
67
|
+
logs_files = [logs_files[-1]]
|
|
68
|
+
|
|
69
|
+
if previous_day_only:
|
|
70
|
+
# Check if there is a previous day log file.
|
|
71
|
+
if len(logs_files) == 1:
|
|
72
|
+
logs_files = []
|
|
73
|
+
else:
|
|
74
|
+
logs_files = [logs_files[-2]]
|
|
75
|
+
|
|
76
|
+
return logs_files
|
|
77
|
+
|
|
78
|
+
|
|
8
79
|
def get_logs(
|
|
9
|
-
|
|
80
|
+
log_files_directory_path: str = None,
|
|
81
|
+
log_file_path: str = None,
|
|
10
82
|
pattern: str = '*.*',
|
|
11
83
|
log_type: Literal['csv'] = 'csv',
|
|
12
84
|
header_type_of_files: Literal['first', 'all'] = 'first',
|
|
@@ -17,7 +89,8 @@ def get_logs(
|
|
|
17
89
|
"""
|
|
18
90
|
This function gets the logs from the log files. Supports rotating files to get the logs by time.
|
|
19
91
|
|
|
20
|
-
:param
|
|
92
|
+
:param log_files_directory_path: Path to the log files. Check the 'get_logs_paths' function for more details.
|
|
93
|
+
:param log_file_path: Path to the log file. Check the 'get_logs_paths' function for more details.
|
|
21
94
|
:param pattern: Pattern to match the log files names.
|
|
22
95
|
Default pattern will match all the files.
|
|
23
96
|
:param log_type: Type of log to get.
|
|
@@ -36,9 +109,13 @@ def get_logs(
|
|
|
36
109
|
if remove_logs and move_to_path:
|
|
37
110
|
raise ValueError('Both "remove_logs" and "move_to_path" cannot be True/specified at the same time.')
|
|
38
111
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
112
|
+
if header_type_of_files not in ['first', 'all']:
|
|
113
|
+
raise ValueError('Only "first" and "all" header types are supported.')
|
|
114
|
+
|
|
115
|
+
# Get all the log file paths by the pattern.
|
|
116
|
+
logs_files: list = get_logs_paths(
|
|
117
|
+
log_files_directory_path=log_files_directory_path, log_file_path=log_file_path,
|
|
118
|
+
pattern=pattern, log_type=log_type)
|
|
42
119
|
|
|
43
120
|
# Read all the logs.
|
|
44
121
|
logs_content: list = list()
|
|
@@ -46,12 +123,12 @@ def get_logs(
|
|
|
46
123
|
for single_file in logs_files:
|
|
47
124
|
if log_type == 'csv':
|
|
48
125
|
if header_type_of_files == 'all':
|
|
49
|
-
csv_content, _ = csvs.
|
|
126
|
+
csv_content, _ = csvs.read_csv_to_list_of_dicts_by_header(single_file['file_path'], **print_kwargs)
|
|
50
127
|
logs_content.extend(csv_content)
|
|
51
128
|
elif header_type_of_files == 'first':
|
|
52
129
|
# The function gets empty header to read it from the CSV file, the returns the header that it read.
|
|
53
130
|
# Then each time the header is fed once again to the function.
|
|
54
|
-
csv_content, header = csvs.
|
|
131
|
+
csv_content, header = csvs.read_csv_to_list_of_dicts_by_header(single_file['file_path'], header=header, **print_kwargs)
|
|
55
132
|
# Any way the first file will be read with header.
|
|
56
133
|
logs_content.extend(csv_content)
|
|
57
134
|
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
|
|
3
|
+
from ..print_api import print_api
|
|
4
|
+
from .. import permissions
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
ERROR_CODES = {
|
|
8
|
+
'1603': 'The App is already installed or Insufficient permissions',
|
|
9
|
+
'1619': 'This installation package could not be opened. Verify that the package exists and that you can '
|
|
10
|
+
'install it manually, also check the installation command line switches'
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def install_msi(
|
|
15
|
+
msi_path,
|
|
16
|
+
silent_no_gui=True,
|
|
17
|
+
silent_progress_bar=False,
|
|
18
|
+
no_restart=True,
|
|
19
|
+
as_admin=False,
|
|
20
|
+
exit_on_error=False,
|
|
21
|
+
print_kwargs=None):
|
|
22
|
+
"""
|
|
23
|
+
Install an MSI file silently.
|
|
24
|
+
:param msi_path: str, path to the MSI file.
|
|
25
|
+
:param silent_no_gui: bool, whether to run the installation silently, without showing GUI.
|
|
26
|
+
:param silent_progress_bar: bool, whether to show a progress bar during silent installation.
|
|
27
|
+
:param no_restart: bool, whether to restart the computer after installation.
|
|
28
|
+
:param as_admin: bool, whether to run the installation as administrator.
|
|
29
|
+
:param exit_on_error: bool, whether to exit the script if the installation fails.
|
|
30
|
+
:param print_kwargs: dict, print_api kwargs.
|
|
31
|
+
:return:
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
if silent_progress_bar and silent_no_gui:
|
|
35
|
+
raise ValueError("silent_progress_bar and silent_no_gui cannot be both True.")
|
|
36
|
+
|
|
37
|
+
# Define the msiexec command
|
|
38
|
+
command = f'msiexec /i "{msi_path}"'
|
|
39
|
+
|
|
40
|
+
if silent_no_gui:
|
|
41
|
+
command = f"{command} /qn"
|
|
42
|
+
if silent_progress_bar:
|
|
43
|
+
command = f"{command} /qb"
|
|
44
|
+
if no_restart:
|
|
45
|
+
command = f"{command} /norestart"
|
|
46
|
+
|
|
47
|
+
if as_admin:
|
|
48
|
+
command = permissions.get_command_to_run_as_admin_windows(command)
|
|
49
|
+
|
|
50
|
+
# Run the command
|
|
51
|
+
result = subprocess.run(command, capture_output=True, shell=True, text=True)
|
|
52
|
+
|
|
53
|
+
# Check the result
|
|
54
|
+
if result.returncode == 0:
|
|
55
|
+
print_api("MSI Installation completed.", color="green", **(print_kwargs or {}))
|
|
56
|
+
else:
|
|
57
|
+
message = f"Installation failed. Return code: {result.returncode}\n{ERROR_CODES.get(str(result.returncode), '')}"
|
|
58
|
+
print_api(message, color="red", **(print_kwargs or {}))
|
|
59
|
+
if exit_on_error:
|
|
60
|
+
exit()
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
atomicshop/__init__.py,sha256=
|
|
1
|
+
atomicshop/__init__.py,sha256=EvosCo6MVhZ-HXgV5FtdTdD7o9rDV_EL4_xqhrsoJaw,123
|
|
2
2
|
atomicshop/_basics_temp.py,sha256=6cu2dd6r2dLrd1BRNcVDKTHlsHs_26Gpw8QS6v32lQ0,3699
|
|
3
3
|
atomicshop/_create_pdf_demo.py,sha256=Yi-PGZuMg0RKvQmLqVeLIZYadqEZwUm-4A9JxBl_vYA,3713
|
|
4
4
|
atomicshop/_patch_import.py,sha256=ENp55sKVJ0e6-4lBvZnpz9PQCt3Otbur7F6aXDlyje4,6334
|
|
5
|
-
atomicshop/appointment_management.py,sha256=
|
|
5
|
+
atomicshop/appointment_management.py,sha256=BsYH_PClTGLVazcuNjt30--hpXKYjSmHp1R1iQbM4Hc,7330
|
|
6
6
|
atomicshop/certificates.py,sha256=J-cmd6Rpq3zZyzsOH-GcdqIXdg2UwM8_E9mg7XtUph8,3787
|
|
7
7
|
atomicshop/command_line_processing.py,sha256=u5yT9Ger_cu7ni5ID0VFlRbVD46ARHeNC9tRM-_YXrQ,1038
|
|
8
8
|
atomicshop/config_init.py,sha256=z2RXD_mw9nQlAOpuGry1h9QT-2LhNscXgGAktN3dCVQ,2497
|
|
@@ -14,7 +14,7 @@ atomicshop/dns.py,sha256=bNZOo5jVPzq7OT2qCPukXoK3zb1oOsyaelUwQEyK1SA,2500
|
|
|
14
14
|
atomicshop/domains.py,sha256=Rxu6JhhMqFZRcoFs69IoEd1PtYca0lMCG6F1AomP7z4,3197
|
|
15
15
|
atomicshop/emails.py,sha256=I0KyODQpIMEsNRi9YWSOL8EUPBiWyon3HRdIuSj3AEU,1410
|
|
16
16
|
atomicshop/file_types.py,sha256=-0jzQMRlmU1AP9DARjk-HJm1tVE22E6ngP2mRblyEjY,763
|
|
17
|
-
atomicshop/filesystem.py,sha256=
|
|
17
|
+
atomicshop/filesystem.py,sha256=JVWoOSkm-lfh11nBMlrP0w_YnrTFnJ5noYLtoN5Nf5o,48809
|
|
18
18
|
atomicshop/functions.py,sha256=pK8hoCE9z61PtWCxQJsda7YAphrLH1wxU5x-1QJP-sY,499
|
|
19
19
|
atomicshop/hashing.py,sha256=Le8qGFyt3_wX-zGTeQShz7L2HL_b6nVv9PnawjglyHo,3474
|
|
20
20
|
atomicshop/http_parse.py,sha256=nrf2rZcprLqtW8HVrV7TCZ1iTBcWRRy-mXIlAOzcaJs,9703
|
|
@@ -22,7 +22,7 @@ atomicshop/inspect_wrapper.py,sha256=sGRVQhrJovNygHTydqJj0hxES-aB2Eg9KbIk3G31apw
|
|
|
22
22
|
atomicshop/ip_addresses.py,sha256=Hvi4TumEFoTEpKWaq5WNF-YzcRzt24IxmNgv-Mgax1s,1190
|
|
23
23
|
atomicshop/keyboard_press.py,sha256=1W5kRtOB75fulVx-uF2yarBhW0_IzdI1k73AnvXstk0,452
|
|
24
24
|
atomicshop/pbtkmultifile_argparse.py,sha256=aEk8nhvoQVu-xyfZosK3ma17CwIgOjzO1erXXdjwtS4,4574
|
|
25
|
-
atomicshop/permissions.py,sha256=
|
|
25
|
+
atomicshop/permissions.py,sha256=pGynX57FqFdCW2Y6dE1T0oqL7ujagMAABw7nPHxi2IQ,4094
|
|
26
26
|
atomicshop/print_api.py,sha256=DhbCQd0MWZZ5GYEk4oTu1opRFC-b31g1VWZgTGewG2Y,11568
|
|
27
27
|
atomicshop/process.py,sha256=kOLrpUb5T5QN9ZvpGOjXyo7Kivrc14A9gcw9lvNMidI,15670
|
|
28
28
|
atomicshop/process_name_cmd.py,sha256=TNAK6kQZm5JKWzEW6QLqVHEG98ZLNDQiSS4YwDk8V8c,3830
|
|
@@ -44,7 +44,7 @@ atomicshop/timer.py,sha256=KxBBgVM8po6pUJDW8TgY1UXj0iiDmRmL5XDCq0VHAfU,1670
|
|
|
44
44
|
atomicshop/urls.py,sha256=CQl1j1kjEVDlAuYJqYD9XxPF1SUSgrmG8PjlcXNEKsQ,597
|
|
45
45
|
atomicshop/uuids.py,sha256=JSQdm3ZTJiwPQ1gYe6kU0TKS_7suwVrHc8JZDGYlydM,2214
|
|
46
46
|
atomicshop/virtualization.py,sha256=LPP4vjE0Vr10R6DA4lqhfX_WaNdDGRAZUW0Am6VeGco,494
|
|
47
|
-
atomicshop/web.py,sha256=
|
|
47
|
+
atomicshop/web.py,sha256=Ks_4F02MUqGvFRC-gs2H_NHk3jf1XIzrf_Q_NFb3re4,11116
|
|
48
48
|
atomicshop/addons/PlayWrightCodegen.cmd,sha256=Z5cnllsyXD4F1W2h-WLEnyFkg5nZy0-hTGHRWXVOuW4,173
|
|
49
49
|
atomicshop/addons/ScriptExecution.cmd,sha256=8iC-uHs9MX9qUD_C2M7n9Xw4MZvwOfxT8H5v3hluVps,93
|
|
50
50
|
atomicshop/addons/a_setup_scripts/install_psycopg2_ubuntu.sh,sha256=lM7LkXQ2AxfFzDGyzSOfIS_zpg9bAD1k3JJ-qu5CdH8,81
|
|
@@ -52,11 +52,13 @@ atomicshop/addons/a_setup_scripts/install_pywintrace_0.3.cmd,sha256=lEP_o6rWcBFU
|
|
|
52
52
|
atomicshop/addons/mains/install_docker_rootless_ubuntu.py,sha256=9IPNtGZYjfy1_n6ZRt7gWz9KZgR6XCgevjqq02xk-o0,281
|
|
53
53
|
atomicshop/addons/mains/install_docker_ubuntu_main_sudo.py,sha256=JzayxeyKDtiuT4Icp2L2LyFRbx4wvpyN_bHLfZ-yX5E,281
|
|
54
54
|
atomicshop/addons/mains/install_elastic_search_and_kibana_ubuntu.py,sha256=yRB-l1zBxdiN6av-FwNkhcBlaeu4zrDPjQ0uPGgpK2I,244
|
|
55
|
+
atomicshop/addons/mains/install_fibratus_windows.py,sha256=TU4e9gdZ_zI73C40uueJ59pD3qmN-UFGdX5GFoVf6cM,179
|
|
55
56
|
atomicshop/addons/mains/install_wsl_ubuntu_lts_admin.py,sha256=PrvZ4hMuadzj2GYKRZSwyNayJUuaSnCF9nV6ORqoPdo,123
|
|
56
57
|
atomicshop/addons/mains/msi_unpacker.py,sha256=XAJdEqs-3s9JqIgHpGRL-HxLKpFMXdrlXmq2Is2Pyfk,164
|
|
57
58
|
atomicshop/addons/mains/search_for_hyperlinks_in_docx.py,sha256=HkIdo_Sz9nPbbbJf1mwfwFkyI7vkvpH8qiIkuYopN4w,529
|
|
58
59
|
atomicshop/addons/mains/FACT/factw_fact_extractor_docker_image_main_sudo.py,sha256=DDKX3Wp2SmzMCEtCIEOUbEKMob2ZQ7VEQGLEf9uYXrs,320
|
|
59
60
|
atomicshop/addons/mains/FACT/update_extract.py,sha256=H3VsdhlA7xxK5lI_nyrWUdk8GNZXbEUVR_K9cJ4ECAw,506
|
|
61
|
+
atomicshop/addons/mains/__pycache__/install_fibratus_windows.cpython-312.pyc,sha256=u92dFjDrTbZBIti9B3ttna33Jg1ZSeMYhTiupdfklt4,549
|
|
60
62
|
atomicshop/addons/mains/inits/init_to_import_all_modules.py,sha256=piyFjkqtNbM9PT2p8aGcatI615517XEQHgU9kDFwseY,559
|
|
61
63
|
atomicshop/addons/package_setup/CreateWheel.cmd,sha256=hq9aWBSH6iffYlZyaCNrFlA0vxMh3j1k8DQE8IARQuA,189
|
|
62
64
|
atomicshop/addons/package_setup/Setup in Edit mode.cmd,sha256=299RsExjR8Mup6YyC6rW0qF8lnwa3uIzwk_gYg_R_Ss,176
|
|
@@ -102,7 +104,7 @@ atomicshop/etw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
102
104
|
atomicshop/etw/dns_trace.py,sha256=RaREpwJETAMZSd1Lhbg0sO3ugBMw3y1fSKdvP5NfTqM,5189
|
|
103
105
|
atomicshop/etw/etw.py,sha256=xVJNbfCq4KgRfsDnul6CrIdAMl9xRBixZ-hUyqiB2g4,2403
|
|
104
106
|
atomicshop/file_io/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
105
|
-
atomicshop/file_io/csvs.py,sha256=
|
|
107
|
+
atomicshop/file_io/csvs.py,sha256=FwLTHFdngcgEpf-qviDrHpt7qT_QWtNGAR_RKvYZlpI,4816
|
|
106
108
|
atomicshop/file_io/docxs.py,sha256=6tcYFGp0vRsHR47VwcRqwhdt2DQOwrAUYhrwN996n9U,5117
|
|
107
109
|
atomicshop/file_io/file_io.py,sha256=FR84ihjGlr7Eqejo-_js4nBICVst31axD0bwX19S2eM,6385
|
|
108
110
|
atomicshop/file_io/jsons.py,sha256=q9ZU8slBKnHLrtn3TnbK1qxrRpj5ZvCm6AlsFzoANjo,5303
|
|
@@ -116,7 +118,7 @@ atomicshop/mitm/initialize_engines.py,sha256=UGdT5DKYNri3MNOxESP7oeSxYiUDrVilJ4j
|
|
|
116
118
|
atomicshop/mitm/initialize_mitm_server.py,sha256=aXNZlRu1_RGjC7lagvs2Q8rjQiygxYucy-U4C_SBnsk,13871
|
|
117
119
|
atomicshop/mitm/message.py,sha256=u2U2f2SOHdBNU-6r1Ik2W14ai2EOwxUV4wVfGZA098k,1732
|
|
118
120
|
atomicshop/mitm/shared_functions.py,sha256=PaK_sbnEA5zo9k2ktEOKLmvo-6wRUunxzSNRr41uXIQ,1924
|
|
119
|
-
atomicshop/mitm/statistic_analyzer.py,sha256=
|
|
121
|
+
atomicshop/mitm/statistic_analyzer.py,sha256=K6HN7iKMthpEZYmVS1aa0jpW2g5Owq4Jl-mZIQzxWYo,23542
|
|
120
122
|
atomicshop/mitm/engines/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
121
123
|
atomicshop/mitm/engines/create_module_template.py,sha256=tRjVSm1sD6FzML71Qbuwvita0qsusdFGm8NZLsZ-XMs,4853
|
|
122
124
|
atomicshop/mitm/engines/create_module_template_example.py,sha256=X5xhvbV6-g9jU_bQVhf_crZmaH50LRWz3bS-faQ18ds,489
|
|
@@ -147,7 +149,8 @@ atomicshop/wrappers/astw.py,sha256=VkYfkfyc_PJLIOxByT6L7B8uUmKY6-I8XGZl4t_z828,4
|
|
|
147
149
|
atomicshop/wrappers/configparserw.py,sha256=JwDTPjZoSrv44YKwIRcjyUnpN-FjgXVfMqMK_tJuSgU,22800
|
|
148
150
|
atomicshop/wrappers/cryptographyw.py,sha256=H5NaHHDkr97QYhUrHFO9vY218u8k3N3Zgh6bQRnicUE,13140
|
|
149
151
|
atomicshop/wrappers/ffmpegw.py,sha256=wcq0ZnAe0yajBOuTKZCCaKI7CDBjkq7FAgdW5IsKcVE,6031
|
|
150
|
-
atomicshop/wrappers/githubw.py,sha256=
|
|
152
|
+
atomicshop/wrappers/githubw.py,sha256=AQcFuT5mvDUNT_cI31MwkJ7srdhMtttF8FyXS8vs5cU,12270
|
|
153
|
+
atomicshop/wrappers/msiw.py,sha256=1kEs9T3eJYGzEpEBXaq8OZxlCnV4gnIR4zhmCsQiKvY,2201
|
|
151
154
|
atomicshop/wrappers/numpyw.py,sha256=sBV4gSKyr23kXTalqAb1oqttzE_2XxBooCui66jbAqc,1025
|
|
152
155
|
atomicshop/wrappers/olefilew.py,sha256=biD5m58rogifCYmYhJBrAFb9O_Bn_spLek_9HofLeYE,2051
|
|
153
156
|
atomicshop/wrappers/pipw.py,sha256=mu4jnHkSaYNfpBiLZKMZxEX_E2LqW5BVthMZkblPB_c,1317
|
|
@@ -193,23 +196,25 @@ atomicshop/wrappers/factw/install/pre_install_and_install_before_restart.py,sha2
|
|
|
193
196
|
atomicshop/wrappers/factw/postgresql/__init__.py,sha256=xMBn2d3Exo23IPP2F_9-SXmOlhFbwWDgS9KwozSTjA0,162
|
|
194
197
|
atomicshop/wrappers/factw/postgresql/analysis.py,sha256=2Rxzy2jyq3zEKIo53z8VkjuslKE_i5mq2ZpmJAvyd6U,716
|
|
195
198
|
atomicshop/wrappers/factw/postgresql/file_object.py,sha256=VRiCXnsd6yDbnsE-TEKYPC-gkAgFVkE6rygRrJLQShI,713
|
|
196
|
-
atomicshop/wrappers/factw/postgresql/firmware.py,sha256=
|
|
199
|
+
atomicshop/wrappers/factw/postgresql/firmware.py,sha256=wnohSnSOCmlTUCzzHIIPGkRrnownlGKgIFyhhdhNEoA,10759
|
|
197
200
|
atomicshop/wrappers/factw/postgresql/fw_files.py,sha256=P1jq4AAZa7fygWdEZtFJOnfz4tyqmPpvFzEMDKrCRkU,1291
|
|
198
201
|
atomicshop/wrappers/factw/postgresql/included_files.py,sha256=sn5YhLkrsvjhrVSA8O8YUNfbqR9STprSuQGEnHsK0jE,1025
|
|
199
202
|
atomicshop/wrappers/factw/postgresql/virtual_file_path.py,sha256=iR68A_My_ohgRcYdueMaQF9EHOgBRN3bIi8Nq59g3kc,1098
|
|
200
203
|
atomicshop/wrappers/factw/rest/__init__.py,sha256=MuzZDJ38myxmwLhNhHIsDk0DXkcNbsB_t4R4SSYl--Y,150
|
|
201
204
|
atomicshop/wrappers/factw/rest/binary_search.py,sha256=AXMFTma3awymrSlE8T1MSV8Q-PCqk586WBDlBr4TbR4,826
|
|
202
205
|
atomicshop/wrappers/factw/rest/file_object.py,sha256=E_CA9lYpUqpxPDJ8c9dAqQAkJq8NafTecKa3q3EKr40,3218
|
|
203
|
-
atomicshop/wrappers/factw/rest/firmware.py,sha256=
|
|
206
|
+
atomicshop/wrappers/factw/rest/firmware.py,sha256=MEdrupbZbjsAsCpTlSast2Y610WbXWCtuDT75rr0g3g,20387
|
|
204
207
|
atomicshop/wrappers/factw/rest/router.py,sha256=fdGok5ESBxcZHIBgM93l4yTPRGoeooQNsrPWIETieGk,710
|
|
205
208
|
atomicshop/wrappers/factw/rest/statistics.py,sha256=vznwzKP1gEF7uXz3HsuV66BU9wrp73N_eFqpFpye9Qw,653
|
|
206
209
|
atomicshop/wrappers/factw/rest/status.py,sha256=4O3xS1poafwyUiLDkhyx4oMMe4PBwABuRPpOMnMKgIU,641
|
|
210
|
+
atomicshop/wrappers/fibratusw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
211
|
+
atomicshop/wrappers/fibratusw/install.py,sha256=PLVymDe0HuOvU0r2lje8BkQAgtiOWEeRO7n-1zKuL7A,3287
|
|
207
212
|
atomicshop/wrappers/loggingw/checks.py,sha256=AGFsTsLxHQd1yAraa5popqLaGO9VM0KpcPGuSLn5ptU,719
|
|
208
213
|
atomicshop/wrappers/loggingw/formatters.py,sha256=mUtcJJfmhLNrwUVYShXTmdu40dBaJu4TS8FiuTXI7ys,7189
|
|
209
214
|
atomicshop/wrappers/loggingw/handlers.py,sha256=qm5Fbu8eDmlstMduUe5nKUlJU5IazFkSnQizz8Qt2os,5479
|
|
210
215
|
atomicshop/wrappers/loggingw/loggers.py,sha256=DHOOTAtqkwn1xgvLHSkOiBm6yFGNuQy1kvbhG-TDog8,2374
|
|
211
216
|
atomicshop/wrappers/loggingw/loggingw.py,sha256=v9WAseZXB50LluT9rIUcRvvevg2nLVKPgz3dbGejfV0,12151
|
|
212
|
-
atomicshop/wrappers/loggingw/reading.py,sha256=
|
|
217
|
+
atomicshop/wrappers/loggingw/reading.py,sha256=XKQVggjleXqS-sjY8q7o_xzMBhWDdJO0A1d4DDE2rDA,7183
|
|
213
218
|
atomicshop/wrappers/nodejsw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
214
219
|
atomicshop/wrappers/nodejsw/install_nodejs.py,sha256=QZg-R2iTQt7kFb8wNtnTmwraSGwvUs34JIasdbNa7ZU,5154
|
|
215
220
|
atomicshop/wrappers/playwrightw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -244,8 +249,8 @@ atomicshop/wrappers/socketw/socket_server_tester.py,sha256=AhpurHJmP2kgzHaUbq5ey
|
|
|
244
249
|
atomicshop/wrappers/socketw/socket_wrapper.py,sha256=aXBwlEIJhFT0-c4i8iNlFx2It9VpCEpsv--5Oqcpxao,11624
|
|
245
250
|
atomicshop/wrappers/socketw/ssl_base.py,sha256=k4V3gwkbq10MvOH4btU4onLX2GNOsSfUAdcHmL1rpVE,2274
|
|
246
251
|
atomicshop/wrappers/socketw/statistics_csv.py,sha256=t3dtDEfN47CfYVi0CW6Kc2QHTEeZVyYhc57IYYh5nmA,826
|
|
247
|
-
atomicshop-2.
|
|
248
|
-
atomicshop-2.
|
|
249
|
-
atomicshop-2.
|
|
250
|
-
atomicshop-2.
|
|
251
|
-
atomicshop-2.
|
|
252
|
+
atomicshop-2.12.1.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
|
|
253
|
+
atomicshop-2.12.1.dist-info/METADATA,sha256=TaPxIyYLWTGyaS4RhB9JdRuElraHbe0umXI6faSh9lE,10447
|
|
254
|
+
atomicshop-2.12.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
255
|
+
atomicshop-2.12.1.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
|
|
256
|
+
atomicshop-2.12.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|