atomicshop 2.9.13__py3-none-any.whl → 2.9.15__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.
atomicshop/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
1
  """Atomic Basic functions and classes to make developer life easier"""
2
2
 
3
3
  __author__ = "Den Kras"
4
- __version__ = '2.9.13'
4
+ __version__ = '2.9.15'
File without changes
@@ -5,9 +5,9 @@ def check_3_booleans_when_only_1_can_be_true(boolean1: tuple, boolean2: tuple, b
5
5
  (self.config['section']['default_usage'], 'default_usage'),
6
6
  (self.config['section']['create_usage'], 'create_usage'),
7
7
  (self.config['section']['custom_usage'], 'custom_usage'))
8
- :param boolean1: tuple, first entry contains the value, second contains the name of the setting.
9
- :param boolean2: tuple, first entry contains the value, second contains the name of the setting.
10
- :param boolean3: tuple, first entry contains the value, second contains the name of the setting.
8
+ :param boolean1: tuple, (value, string name of the setting you want to print to the user to be aware of).
9
+ :param boolean2: tuple, (value, string name of the setting you want to print to the user to be aware of).
10
+ :param boolean3: tuple, (value, string name of the setting you want to print to the user to be aware of).
11
11
  :return:
12
12
  """
13
13
 
atomicshop/filesystem.py CHANGED
@@ -1071,12 +1071,12 @@ def create_dict_of_path(
1071
1071
  parent_entry: str = None
1072
1072
  ):
1073
1073
  """
1074
- The function receives a path and a dictionary and adds the path to the dictionary.
1074
+ The function receives a path and a list, and adds the path to the list.
1075
1075
 
1076
1076
  Check the working example from 'create_dict_of_paths_list' function.
1077
1077
 
1078
1078
  :param path: string, path.
1079
- :param structure_dict: dictionary to add the path to.
1079
+ :param structure_list: list to add the path to.
1080
1080
  :param add_data_to_entry: any, data to add to the entry.
1081
1081
  :param add_data_key: string, key to add the data to.
1082
1082
  :param parent_entry: string, for internal use to pass the current parent entry.
@@ -112,10 +112,9 @@ def thread_worker_main(
112
112
 
113
113
  # Loading parser by domain, if there is no parser for current domain - general reference parser is loaded.
114
114
  # These should be outside any loop and initialized only once entering the thread.
115
- parser, responder, recorder = assign_class_by_domain(engines_list,
116
- client_message.server_name,
117
- reference_module=reference_module,
118
- logger=network_logger)
115
+ parser, responder, recorder = assign_class_by_domain(
116
+ engines_list, client_message.server_name, reference_module=reference_module, config=config,
117
+ logger=network_logger)
119
118
 
120
119
  # Defining client connection boolean variable to enter the loop
121
120
  client_connection_boolean: bool = True
@@ -1,5 +1,4 @@
1
1
  import os
2
- from pathlib import Path
3
2
  from typing import Literal
4
3
 
5
4
  from ... import filesystem
@@ -63,6 +63,13 @@ class ImportConfig:
63
63
  "Exiting..."
64
64
  )
65
65
 
66
+ # Check [dns] boolean configurations. ==========================================================================
67
+ check_3_booleans_when_only_1_can_be_true(
68
+ (self.config['dns']['route_to_tcp_server_only_engine_domains'], 'route_to_tcp_server_only_engine_domains'),
69
+ (self.config['dns']['route_to_tcp_server_all_domains'], 'route_to_tcp_server_all_domains'),
70
+ (self.config['dns']['regular_resolving'], 'regular_resolving')
71
+ )
72
+
66
73
  check_3_booleans_when_only_1_can_be_true(
67
74
  (self.config['certificates']['default_server_certificate_usage'], 'default_server_certificate_usage'),
68
75
  (self.config['certificates']['sni_create_server_certificate_for_each_domain'],
@@ -89,7 +89,8 @@ class ModuleCategory:
89
89
 
90
90
  # Assigning external class object by message domain received from client. If the domain is not in the list,
91
91
  # the reference general module will be assigned.
92
- def assign_class_by_domain(engines_list: list, message_domain_name: str, reference_module, logger=None):
92
+ def assign_class_by_domain(
93
+ engines_list: list, message_domain_name: str, reference_module, config, logger=None):
93
94
  # Defining return variables:
94
95
  function_parser = None
95
96
  function_responder = None
@@ -97,30 +98,33 @@ def assign_class_by_domain(engines_list: list, message_domain_name: str, referen
97
98
 
98
99
  # In case SNI came empty in the request from client, then there's no point in iterating through engine domains.
99
100
  if message_domain_name:
100
- # Checking if current domain is in engines' domain list to activate domain specific engine
101
- for function_module in engines_list:
102
- # The list: matches_list = ["domain1.com", "domain2.com", "domain3.com"]
103
- # The string: a_string = "www.domain1.com"
104
- # Checking that the message subdomain + domain contains current module's domain name
105
- # Template Should be like this: if any(x in a_string for x in matches_list):
106
-
107
- # On the other hand if you want to find if partial string is
108
- # in the list of strings: if any(a_string in x for x in matches_list):
109
- # In this case list is the same and string: a_string = domain
110
- if any(x in message_domain_name for x in function_module.domain_list):
111
- # Assigning modules by current engine of the domain
112
- function_parser = function_module.parser_class_object
113
- function_recorder = function_module.recorder_class_object
114
- # Since the responder is being initiated only once, we're assigning only the instance
115
- function_responder = function_module.responder_instance
116
-
117
- logger.info(f"Assigned Modules for [{message_domain_name}]: "
118
- f"{function_module.parser_class_object.__name__}, "
119
- f"{function_module.responder_class_object.__name__}, "
120
- f"{function_module.recorder_class_object.__name__}")
121
-
122
- # If the domain was found in the current list of class domains, we can stop the loop
123
- break
101
+ # If the engines_usage is set to True in the config file, then we'll iterate through the list of engines
102
+ # to find the domain in the list of domains of the engine.
103
+ if config['tcp']['engines_usage']:
104
+ # Checking if current domain is in engines' domain list to activate domain specific engine
105
+ for function_module in engines_list:
106
+ # The list: matches_list = ["domain1.com", "domain2.com", "domain3.com"]
107
+ # The string: a_string = "www.domain1.com"
108
+ # Checking that the message subdomain + domain contains current module's domain name
109
+ # Template Should be like this: if any(x in a_string for x in matches_list):
110
+
111
+ # On the other hand if you want to find if partial string is
112
+ # in the list of strings: if any(a_string in x for x in matches_list):
113
+ # In this case list is the same and string: a_string = domain
114
+ if any(x in message_domain_name for x in function_module.domain_list):
115
+ # Assigning modules by current engine of the domain
116
+ function_parser = function_module.parser_class_object
117
+ function_recorder = function_module.recorder_class_object
118
+ # Since the responder is being initiated only once, we're assigning only the instance
119
+ function_responder = function_module.responder_instance
120
+
121
+ logger.info(f"Assigned Modules for [{message_domain_name}]: "
122
+ f"{function_module.parser_class_object.__name__}, "
123
+ f"{function_module.responder_class_object.__name__}, "
124
+ f"{function_module.recorder_class_object.__name__}")
125
+
126
+ # If the domain was found in the current list of class domains, we can stop the loop
127
+ break
124
128
 
125
129
  # If none of the domains were found in the engine domains list, then we'll assign reference module.
126
130
  # It's enough to check only parser, since responder and recorder also will be empty.
@@ -1,8 +1,9 @@
1
1
  import os
2
2
  import threading
3
3
 
4
+ # Importing atomicshop package to get the version of the package.
4
5
  import atomicshop
5
- from atomicshop.print_api import print_api
6
+
6
7
  from .import_config import ImportConfig
7
8
  from .initialize_engines import ModuleCategory
8
9
  from .connection_thread_worker import thread_worker_main
@@ -12,6 +13,7 @@ from ..wrappers.socketw.socket_wrapper import SocketWrapper
12
13
  from ..wrappers.socketw.dns_server import DnsServer
13
14
  from ..basics import dicts_nested
14
15
  from ..wrappers.loggingw import loggingw
16
+ from ..print_api import print_api
15
17
 
16
18
 
17
19
  def initialize_mitm_server(config_static):
@@ -129,20 +131,57 @@ def initialize_mitm_server(config_static):
129
131
  logger=system_logger, stdout=False, reference_general=True)
130
132
  # === EOF Initialize Reference Module ==========================================================================
131
133
  # === Engine logging ===========================================================================================
132
- # If engines were found.
133
- if engines_list:
134
- # Printing the parsers using "start=1" for index to start counting from "1" and not "0"
135
- system_logger.info("[*] Found Engines:")
136
- for index, engine in enumerate(engines_list, start=1):
137
- system_logger.info(f"[*] {index}: {engine.engine_name} | {engine.domain_list}")
138
- system_logger.info(f"[*] Modules: {engine.parser_class_object.__name__}, "
139
- f"{engine.responder_class_object.__name__}, "
140
- f"{engine.recorder_class_object.__name__}")
141
- # If engines weren't found.
134
+ # Printing the parsers using "start=1" for index to start counting from "1" and not "0"
135
+ print_api(f"[*] Found Engines:", logger=system_logger)
136
+ for index, engine in enumerate(engines_list, start=1):
137
+ message = f"[*] {index}: {engine.engine_name} | {engine.domain_list}"
138
+ print_api(message, logger=system_logger)
139
+
140
+ message = (f"[*] Modules: {engine.parser_class_object.__name__}, "
141
+ f"{engine.responder_class_object.__name__}, "
142
+ f"{engine.recorder_class_object.__name__}")
143
+ print_api(message, logger=system_logger)
144
+
145
+ if config['dns']['enable_dns_server']:
146
+ print_api("DNS Server is enabled.", logger=system_logger)
147
+
148
+ # If engines were found and dns is set to route by the engine domains.
149
+ if engines_list and config['dns']['route_to_tcp_server_only_engine_domains']:
150
+ print_api("Engine domains will be routed by the DNS server to Built-in TCP Server.", logger=system_logger)
151
+ # If engines were found, but the dns isn't set to route to engines.
152
+ elif engines_list and not config['dns']['route_to_tcp_server_only_engine_domains']:
153
+ message = f"[*] Engine domains found, but the DNS routing is set not to use them for routing."
154
+ print_api(message, color="yellow", logger=system_logger)
155
+ elif not engines_list and config['dns']['route_to_tcp_server_only_engine_domains']:
156
+ raise ValueError("No engines were found, but the DNS routing is set to use them for routing.\n"
157
+ "Please check your DNS configuration in the 'config.ini' file.")
158
+
159
+ if config['dns']['route_to_tcp_server_all_domains']:
160
+ print_api("All domains will be routed by the DNS server to Built-in TCP Server.", logger=system_logger)
161
+
162
+ if config['dns']['regular_resolving']:
163
+ print_api(
164
+ "Regular DNS resolving is enabled. Built-in TCP server will not be routed to",
165
+ logger=system_logger, color="yellow")
142
166
  else:
143
- system_logger.info("[*] NO ENGINES WERE FOUND!")
144
- system_logger.info(f"Server will process all the incoming (domains) connections by "
145
- f"[{reference_module.engine_name}] engine.")
167
+ print_api("DNS Server is disabled.", logger=system_logger, color="yellow")
168
+
169
+ if config['tcp']['enable_tcp_server']:
170
+ print_api("TCP Server is enabled.", logger=system_logger)
171
+
172
+ if engines_list and not config['tcp']['engines_usage']:
173
+ message = \
174
+ f"Engines found, but the TCP server is set not to use them for processing. General responses only."
175
+ print_api(message, color="yellow", logger=system_logger)
176
+ elif engines_list and config['tcp']['engines_usage']:
177
+ message = f"Engines found, and the TCP server is set to use them for processing."
178
+ print_api(message, logger=system_logger)
179
+ elif not engines_list and config['tcp']['engines_usage']:
180
+ raise ValueError("No engines were found, but the TCP server is set to use them for processing.\n"
181
+ "Please check your TCP configuration in the 'config.ini' file.")
182
+ else:
183
+ print_api("TCP Server is disabled.", logger=system_logger, color="yellow")
184
+
146
185
  # === EOF Engine Logging =======================================================================================
147
186
 
148
187
  # Assigning all the engines domains to all time domains, that will be responsible for adding new domains.
@@ -178,20 +217,24 @@ def initialize_mitm_server(config_static):
178
217
  dns_server.request_domain_queue = domain_queue
179
218
  # Initiate the thread.
180
219
  threading.Thread(target=dns_server.start).start()
220
+
181
221
  # === EOF Initialize DNS module ================================================================================
222
+ # === Initialize TCP Server ====================================================================================
223
+ if config['tcp']['enable_tcp_server']:
224
+ socket_wrapper = SocketWrapper(
225
+ config=dicts_nested.merge(config, config_static.CONFIG_EXTENDED), logger=listener_logger,
226
+ statistics_logger=statistics_logger)
182
227
 
183
- socket_wrapper = SocketWrapper(
184
- config=dicts_nested.merge(config, config_static.CONFIG_EXTENDED), logger=listener_logger,
185
- statistics_logger=statistics_logger)
228
+ socket_wrapper.create_tcp_listening_socket_list()
186
229
 
187
- socket_wrapper.create_tcp_listening_socket_list()
230
+ socket_wrapper.requested_domain_from_dns_server = domain_queue
188
231
 
189
- socket_wrapper.requested_domain_from_dns_server = domain_queue
232
+ # General exception handler will catch all the exceptions that occurred in the threads and write it to the log.
233
+ try:
234
+ socket_wrapper.loop_for_incoming_sockets(function_reference=thread_worker_main, reference_args=(
235
+ network_logger, statistics_logger, engines_list, reference_module, config,))
236
+ except Exception:
237
+ message = f"Unhandled Exception occurred in 'loop_for_incoming_sockets' function"
238
+ print_api(message, error_type=True, color="red", logger=network_logger, traceback_string=True, oneline=True)
190
239
 
191
- # The general exception handler will catch all the exceptions that occurred in the threads and write it to the log.
192
- try:
193
- socket_wrapper.loop_for_incoming_sockets(function_reference=thread_worker_main, reference_args=(
194
- network_logger, statistics_logger, engines_list, reference_module, config,))
195
- except Exception:
196
- message = f"Unhandled Exception occurred in 'loop_for_incoming_sockets' function"
197
- print_api(message, error_type=True, color="red", logger=network_logger, traceback_string=True, oneline=True)
240
+ # === EOF Initialize TCP Server ================================================================================
atomicshop/process.py CHANGED
@@ -1,5 +1,4 @@
1
1
  import os
2
- import sys
3
2
  import functools
4
3
  from typing import Union
5
4
  import shlex
@@ -1,3 +1,17 @@
1
- DEFAULT_PORT: str = '9200'
2
- DEFAULT_HOST: str = 'localhost'
3
- DEFAULT_URL: str = f"http://{DEFAULT_HOST}:{DEFAULT_PORT}"
1
+ DEFAULT_ELASTIC_PORT: str = '9200'
2
+ DEFAULT_ELASTIC_HOST: str = 'localhost'
3
+ DEFAULT_ELASTIC_URL: str = f"http://{DEFAULT_ELASTIC_HOST}:{DEFAULT_ELASTIC_PORT}"
4
+
5
+ DEFAULT_KIBANA_PORT: str = '5601'
6
+ DEFAULT_KIBANA_HOST: str = 'localhost'
7
+ DEFAULT_KIBANA_URL: str = f"http://{DEFAULT_KIBANA_HOST}:{DEFAULT_KIBANA_PORT}"
8
+
9
+ ELASTIC_CONFIG_FILE: str = "/etc/elasticsearch/elasticsearch.yml"
10
+ ELASTIC_JVM_OPTIONS_FILE: str = "/etc/elasticsearch/jvm.options"
11
+ XPACK_SECURITY_SETTING_NAME: str = "xpack.security.enabled"
12
+
13
+ UBUNTU_DEPENDENCY_PACKAGES: list[str] = ['apt-transport-https', 'openjdk-11-jdk', 'wget']
14
+ UBUNTU_ELASTIC_PACKAGE_NAME: str = 'elasticsearch'
15
+ UBUNTU_ELASTIC_SERVICE_NAME: str = 'elasticsearch'
16
+ UBUNTU_KIBANA_PACKAGE_NAME: str = 'kibana'
17
+ UBUNTU_KIBANA_SERVICE_NAME: str = 'kibana'
@@ -25,7 +25,7 @@ def get_elastic_wrapper(url: str = None, overwrite: bool = False):
25
25
 
26
26
  # If no url is provided, use the default url.
27
27
  if url is None:
28
- url = config_basic.DEFAULT_URL
28
+ url = config_basic.DEFAULT_ELASTIC_URL
29
29
 
30
30
  # Get the global variable.
31
31
  global ELASTIC_WRAPPER
@@ -0,0 +1,213 @@
1
+ import sys
2
+ import time
3
+ import requests
4
+
5
+ from ...print_api import print_api
6
+ from ... import filesystem
7
+ from .. import ubuntu_terminal
8
+ from . import config_basic
9
+
10
+
11
+ def is_elastic_service_running():
12
+ return ubuntu_terminal.is_service_running(config_basic.UBUNTU_ELASTIC_SERVICE_NAME, return_false_on_error=False)
13
+
14
+
15
+ def enable_elastic_service():
16
+ ubuntu_terminal.enable_service(config_basic.UBUNTU_ELASTIC_SERVICE_NAME)
17
+
18
+
19
+ def start_elastic_service():
20
+ ubuntu_terminal.start_service(config_basic.UBUNTU_ELASTIC_SERVICE_NAME)
21
+
22
+
23
+ def is_kibana_service_running():
24
+ return ubuntu_terminal.is_service_running(config_basic.UBUNTU_KIBANA_SERVICE_NAME, return_false_on_error=False)
25
+
26
+
27
+ def enable_kibana_service():
28
+ ubuntu_terminal.enable_service(config_basic.UBUNTU_KIBANA_SERVICE_NAME)
29
+
30
+
31
+ def start_kibana_service():
32
+ ubuntu_terminal.start_service(config_basic.UBUNTU_KIBANA_SERVICE_NAME)
33
+
34
+
35
+ def start_elastic_and_check_service_availability(wait_time_seconds: float = 30, exit_on_error: bool = True):
36
+ """
37
+ Function starts the Elasticsearch service and checks its availability.
38
+ :param wait_time_seconds: float, the time to wait after starting the service before checking
39
+ the service availability.
40
+ :param exit_on_error: bool, if True, the function will exit the program if the service is not available.
41
+ :return:
42
+ """
43
+
44
+ # Start, enable and check the Elasticsearch service.
45
+ ubuntu_terminal.start_enable_service_check_availability(
46
+ service_name=config_basic.UBUNTU_ELASTIC_SERVICE_NAME,
47
+ wait_time_seconds=wait_time_seconds,
48
+ exit_on_error=exit_on_error
49
+ )
50
+
51
+ # Check if Elasticsearch is running.
52
+ if not is_server_available():
53
+ if exit_on_error:
54
+ sys.exit(1)
55
+
56
+
57
+ def start_kibana_and_check_service_availability(wait_time_seconds: float = 30, exit_on_error: bool = True):
58
+ """
59
+ Function starts the Kibana service and checks its availability.
60
+ :param wait_time_seconds: float, the time to wait after starting the service before checking
61
+ the service availability.
62
+ :param exit_on_error: bool, if True, the function will exit the program if the service is not available.
63
+ :return:
64
+ """
65
+
66
+ # Start, enable and check the Elasticsearch service.
67
+ ubuntu_terminal.start_enable_service_check_availability(
68
+ service_name=config_basic.UBUNTU_KIBANA_SERVICE_NAME,
69
+ wait_time_seconds=wait_time_seconds,
70
+ exit_on_error=exit_on_error
71
+ )
72
+
73
+
74
+ def is_elastic_config_file_exists(
75
+ config_file_path: str = None,
76
+ exit_on_error: bool = False,
77
+ output_message: bool = False
78
+ ) -> bool:
79
+ """
80
+ The function checks if the Elasticsearch configuration file exists.
81
+
82
+ :param config_file_path: str, the path to the configuration file.
83
+ :param exit_on_error: bool, if True, the function will exit the program if the file does not exist.
84
+ :param output_message: bool, if True, the function will print a message if the file does not exist.
85
+ :return:
86
+ """
87
+
88
+ if not config_file_path:
89
+ config_file_path = config_basic.ELASTIC_CONFIG_FILE
90
+
91
+ if not filesystem.check_file_existence(config_file_path):
92
+ if output_message:
93
+ message = f"Configuration file does not exist at {config_file_path}."
94
+ print_api(message, color='red', error_type=True)
95
+ if exit_on_error:
96
+ sys.exit(1)
97
+ return False
98
+ else:
99
+ return True
100
+
101
+
102
+ def check_xpack_security_setting(config_file_path: str = None):
103
+ """
104
+ The function checks if the 'xpack.security.enabled' setting is set to 'false' in the Elasticsearch
105
+ configuration file.
106
+
107
+ :param config_file_path:
108
+ :return:
109
+ """
110
+
111
+ if not config_file_path:
112
+ config_file_path = config_basic.ELASTIC_CONFIG_FILE
113
+
114
+ with open(config_file_path, 'r') as file:
115
+ # Read the file contents
116
+ contents = file.read()
117
+ # Check if the specific setting exists
118
+ if f"{config_basic.XPACK_SECURITY_SETTING_NAME}: false" in contents:
119
+ return False
120
+ elif f"{config_basic.XPACK_SECURITY_SETTING_NAME}: true" in contents:
121
+ return True
122
+ # If the setting doesn't exist, return None.
123
+ else:
124
+ return None
125
+
126
+
127
+ def modify_xpack_security_setting(
128
+ config_file_path: str = None,
129
+ setting: bool = False,
130
+ output_message: bool = True
131
+ ):
132
+ """
133
+ The function modifies the 'xpack.security.enabled' setting in the Elasticsearch configuration file.
134
+ :param config_file_path: str, the path to the configuration file.
135
+ :param setting: bool, the setting to change to. Will be added, if doesn't exist.
136
+ :param output_message: bool, if True, the function will print a message.
137
+ :return:
138
+ """
139
+
140
+ if not config_file_path:
141
+ config_file_path = config_basic.ELASTIC_CONFIG_FILE
142
+
143
+ # The setting to set in the configuration file.
144
+ xpack_setting_to_set: str = f'{config_basic.XPACK_SECURITY_SETTING_NAME}: {str(setting).lower()}'
145
+
146
+ # Check if the setting exists in the configuration file and get its value.
147
+ current_xpack_security_setting = check_xpack_security_setting(config_file_path)
148
+
149
+ # If the setting doesn't exist, add it to the configuration file.
150
+ if current_xpack_security_setting is None:
151
+ with open(config_file_path, 'a') as file:
152
+ file.write(f'{xpack_setting_to_set}\n')
153
+ if output_message:
154
+ print_api(f"Added [{xpack_setting_to_set}] to the configuration.")
155
+ # If the setting exists and is different from the desired setting, change it.
156
+ elif current_xpack_security_setting != setting:
157
+ with open(config_file_path, 'r') as file:
158
+ lines = file.readlines()
159
+ with open(config_file_path, 'w') as file:
160
+ for line in lines:
161
+ if f"{config_basic.XPACK_SECURITY_SETTING_NAME}:" in line:
162
+ file.write(f'{xpack_setting_to_set}\n')
163
+ else:
164
+ file.write(line)
165
+ if output_message:
166
+ print_api(f"Changed [{config_basic.XPACK_SECURITY_SETTING_NAME}] to [{setting}].")
167
+ # If the setting is already set to the desired value, print a message.
168
+ elif current_xpack_security_setting == setting:
169
+ if output_message:
170
+ print_api(f"The setting is already set to [{setting}].")
171
+
172
+
173
+ def is_server_available(
174
+ max_attempts: int = 5,
175
+ wait_between_attempts_seconds: float = 10,
176
+ elastic_url: str = None,
177
+ print_kwargs: dict = None
178
+ ):
179
+ """
180
+ The function checks if Elasticsearch server is up and running by sending GET request to the Elasticsearch server.
181
+ :param max_attempts: int, the maximum number of attempts to check if Elasticsearch is running.
182
+ :param wait_between_attempts_seconds: float, the time to wait between attempts.
183
+ :param elastic_url: str, the URL of the Elasticsearch server. If None, the default URL will be used.
184
+ :param print_kwargs: dict, the keyword arguments for the print_api function.
185
+ :return:
186
+ """
187
+
188
+ if not elastic_url:
189
+ elastic_url = config_basic.DEFAULT_ELASTIC_URL
190
+
191
+ if not print_kwargs:
192
+ print_kwargs = dict()
193
+
194
+ for attempt in range(1, max_attempts + 1):
195
+ print_api(f"Checking if Elasticsearch is running (Attempt {attempt}/{max_attempts})...", **print_kwargs)
196
+
197
+ try:
198
+ response = requests.get(elastic_url)
199
+ status_code = response.status_code
200
+
201
+ if status_code == 200:
202
+ print_api("Elasticsearch is up and running.", color='green', **print_kwargs)
203
+ return True
204
+ else:
205
+ print_api(f"Elasticsearch is not running. Status code: {status_code}", color='yellow', **print_kwargs)
206
+ except requests.exceptions.RequestException as e:
207
+ print_api(f"Failed to connect to Elasticsearch: {e}", color='yellow', **print_kwargs)
208
+
209
+ print_api("Waiting for Elasticsearch to start...", **print_kwargs)
210
+ time.sleep(wait_between_attempts_seconds)
211
+
212
+ print_api("Elasticsearch did not start within the expected time.", color='red', **print_kwargs)
213
+ return False
@@ -0,0 +1,225 @@
1
+ import sys
2
+
3
+ from ...print_api import print_api
4
+ from ... import process
5
+ from .. import ubuntu_terminal
6
+ from . import config_basic, infrastructure
7
+
8
+
9
+ def install_elastic_kibana_ubuntu(install_elastic: bool = True, install_kibana: bool = True):
10
+ """
11
+ The function will install docker on ubuntu.
12
+
13
+ :param install_elastic: bool, if True, install Elasticsearch.
14
+ :param install_kibana: bool, if True, install Kibana.
15
+
16
+ Usage in main.py (run with sudo):
17
+ from atomicshop.wrappers.elasticw import install_elastic
18
+
19
+
20
+ def main():
21
+ install_elastic.install_elastic_ubuntu()
22
+
23
+
24
+ if __name__ == '__main__':
25
+ main()
26
+ """
27
+
28
+ # This is pure bash script.
29
+ """
30
+ #!/bin/bash
31
+
32
+ # Color text in red.
33
+ echo_red() {
34
+ local color="\e[31m" # Red color
35
+ local reset="\e[0m" # Reset formatting
36
+ echo -e "${color}$1${reset}"
37
+ }
38
+
39
+ # Function to check if a service is running
40
+ check_service_running() {
41
+ local service_name=$1
42
+ local status=$(systemctl is-active "$service_name")
43
+
44
+ if [ "$status" == "active" ]; then
45
+ echo "$service_name service is active and running."
46
+ return 0
47
+ else
48
+ echo_red "$service_name service is not running or has failed. Status: $service_status, Failed: $service_failed"
49
+ return 1
50
+ fi
51
+ }
52
+
53
+ # Update and upgrade system packages
54
+ sudo apt-get update && sudo apt-get upgrade -y
55
+
56
+ # Install necessary dependencies
57
+ sudo apt-get install apt-transport-https openjdk-11-jdk wget -y
58
+
59
+ # Download and install the GPG signing key
60
+ wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | gpg --dearmor | sudo tee /usr/share/keyrings/elasticsearch-keyring.gpg > /dev/null
61
+
62
+ # Add the Elastic repository to the system
63
+ echo "deb [signed-by=/usr/share/keyrings/elasticsearch-keyring.gpg] https://artifacts.elastic.co/packages/8.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic-8.x.list
64
+
65
+ # Update package index
66
+ sudo apt-get update
67
+
68
+ # Install Elasticsearch
69
+ sudo apt-get install elasticsearch -y
70
+
71
+ # Path to the Elasticsearch configuration file
72
+ CONFIG_FILE="/etc/elasticsearch/elasticsearch.yml"
73
+
74
+ # Check if the configuration file exists
75
+ if [ ! -f "$CONFIG_FILE" ]; then
76
+ echo "Configuration file does not exist at $CONFIG_FILE."
77
+ exit 1
78
+ fi
79
+
80
+ # Function to check the setting in the configuration file
81
+ check_setting() {
82
+ if grep -q "^xpack.security.enabled: false" "$CONFIG_FILE"; then
83
+ echo "The setting is confirmed to be 'xpack.security.enabled: false'."
84
+ else
85
+ echo "Failed to set 'xpack.security.enabled: false'."
86
+ exit 1
87
+ fi
88
+ }
89
+
90
+ # Check if 'xpack.security.enabled' is set to 'false'
91
+ if grep -q "^xpack.security.enabled: false" "$CONFIG_FILE"; then
92
+ echo "The setting is already set to false."
93
+ elif grep -q "^xpack.security.enabled: true" "$CONFIG_FILE"; then
94
+ # If the setting is true, change it to false
95
+ sudo sed -i 's/^xpack.security.enabled: true/xpack.security.enabled: false/' "$CONFIG_FILE"
96
+ echo "Changed xpack.security.enabled to false."
97
+ check_setting
98
+ else
99
+ # If the setting doesn't exist, add it
100
+ echo "xpack.security.enabled: false" | sudo tee -a "$CONFIG_FILE" > /dev/null
101
+ echo "Added xpack.security.enabled: false to the configuration."
102
+ check_setting
103
+ fi
104
+
105
+ # Start and enable Elasticsearch service
106
+ sudo systemctl start elasticsearch
107
+ sudo systemctl enable elasticsearch
108
+
109
+ echo "Waiting 30 seconds for program to start before availability check..."
110
+ sleep 30
111
+
112
+ # Check if Elasticsearch service is running
113
+ if ! check_service_running "elasticsearch"; then
114
+ echo "Elasticsearch service failed to start. Exiting."
115
+ exit 1
116
+ fi
117
+
118
+ # Function to check if Elasticsearch is up and running
119
+ check_elasticsearch() {
120
+ max_attempts=5
121
+ wait_seconds=10
122
+
123
+ for ((i=1; i<=max_attempts; i++)); do
124
+ echo "Checking if Elasticsearch is running (Attempt $i/$max_attempts)..."
125
+
126
+ # Using curl to get the HTTP status code
127
+ status=$(curl --write-out %{http_code} --silent --output /dev/null http://localhost:9200)
128
+
129
+ if [ "$status" -eq 200 ]; then
130
+ echo "Elasticsearch is up and running."
131
+ return 0
132
+ else
133
+ echo "Elasticsearch is not running. Status code: $status"
134
+ fi
135
+
136
+ echo "Waiting for Elasticsearch to start..."
137
+ sleep $wait_seconds
138
+ done
139
+
140
+ echo "Elasticsearch did not start within the expected time."
141
+ return 1
142
+ }
143
+
144
+ # Check if Elasticsearch is running
145
+ if ! check_elasticsearch; then
146
+ echo "Elasticsearch failed to start. Exiting."
147
+ exit 1
148
+ fi
149
+
150
+ # Install Kibana
151
+ sudo apt-get install kibana -y
152
+
153
+ # Start and enable Kibana service
154
+ sudo systemctl start kibana
155
+ sudo systemctl enable kibana
156
+
157
+ echo "Waiting 30 seconds for program to start before availability check..."
158
+ sleep 30
159
+
160
+ # Check if Kibana service is running
161
+ if ! check_service_running "kibana"; then
162
+ echo "Kibana service failed to start. Exiting."
163
+ exit 1
164
+ fi
165
+
166
+ # Print status
167
+ echo "Elasticsearch and Kibana installation completed."
168
+ echo "Elasticsearch is running on http://localhost:9200"
169
+ echo "Kibana is running on http://localhost:5601"
170
+ """
171
+
172
+ if not install_elastic and not install_kibana:
173
+ raise ValueError("At least one of the services (Elasticsearch or Kibana) must be installed.")
174
+
175
+ # Update and upgrade system packages.
176
+ ubuntu_terminal.upgrade_system_packages()
177
+ ubuntu_terminal.update_system_packages()
178
+
179
+ # Install necessary dependencies.
180
+ ubuntu_terminal.install_packages(config_basic.UBUNTU_DEPENDENCY_PACKAGES)
181
+
182
+ # Install the GPG key and add elastic repository.
183
+ script = f"""
184
+ # Download and install the GPG signing key
185
+ wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | gpg --dearmor | sudo tee /usr/share/keyrings/elasticsearch-keyring.gpg > /dev/null
186
+
187
+ # Add the Elastic repository to the system
188
+ echo "deb [signed-by=/usr/share/keyrings/elasticsearch-keyring.gpg] https://artifacts.elastic.co/packages/8.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic-8.x.list
189
+ """
190
+ process.execute_script(script, shell=True)
191
+
192
+ # Update system with elastic search packages.
193
+ ubuntu_terminal.update_system_packages()
194
+
195
+ if install_elastic:
196
+ # Install Elasticsearch.
197
+ ubuntu_terminal.install_packages([config_basic.UBUNTU_ELASTIC_PACKAGE_NAME])
198
+
199
+ # Check if the configuration file exists.
200
+ infrastructure.is_elastic_config_file_exists(exit_on_error=True, output_message=True)
201
+
202
+ # Check if the specific setting exists or not and set it to false.
203
+ infrastructure.modify_xpack_security_setting(setting=False, output_message=True)
204
+
205
+ # Check if the setting was really set to false.
206
+ if infrastructure.check_xpack_security_setting() is False:
207
+ print_api(f"The setting is confirmed to be [{config_basic.XPACK_SECURITY_SETTING_NAME}: false].")
208
+ else:
209
+ print_api(f"Failed to set [{config_basic.XPACK_SECURITY_SETTING_NAME}: false].")
210
+ sys.exit(1)
211
+
212
+ infrastructure.start_elastic_and_check_service_availability()
213
+
214
+ if install_kibana:
215
+ # Install Kibana.
216
+ ubuntu_terminal.install_packages([config_basic.UBUNTU_KIBANA_PACKAGE_NAME])
217
+
218
+ # Start and enable Kibana service.
219
+ infrastructure.start_kibana_and_check_service_availability()
220
+
221
+ print_api("Installation completed.", color='green')
222
+ if install_elastic:
223
+ print_api(f"Default Elasticsearch on {config_basic.DEFAULT_ELASTIC_URL}")
224
+ if install_kibana:
225
+ print_api(f"Default Kibana on {config_basic.DEFAULT_KIBANA_URL}")
@@ -1,7 +1,7 @@
1
1
  from typing import Union, Literal
2
2
  from pathlib import Path
3
3
 
4
- from .... import permissions, process, filesystem
4
+ from .... import process, filesystem
5
5
  from .. import config_install
6
6
 
7
7
 
@@ -4,7 +4,7 @@ import shlex
4
4
 
5
5
  from ..print_api import print_api
6
6
  from ..tempfiles import TempFile
7
- from ..github_wrapper import GitHubWrapper
7
+ from .githubw import GitHubWrapper
8
8
  from ..process import execute_with_live_output
9
9
  from ..filesystem import create_directory
10
10
 
@@ -1,5 +1,3 @@
1
- import time
2
-
3
1
  from . import combos, javascript
4
2
  from ...file_io import file_io
5
3
 
@@ -91,9 +91,19 @@ class DnsServer:
91
91
 
92
92
  # Check if 'route_to_tcp_server_only_engine_domains' was set to 'True' and output message accordingly.
93
93
  if self.config['dns']['route_to_tcp_server_only_engine_domains']:
94
- self.logger.info(f"Current engine domains: {self.domain_list}")
95
- else:
96
- self.logger.info("Not using engine domains. All 'A' records will be forwarded to TCP Server.")
94
+ message = "Routing only engine domains to Built-in TCP Server."
95
+ print_api(message, logger=self.logger)
96
+
97
+ message = f"Current engine domains: {self.domain_list}"
98
+ print_api(message, logger=self.logger, color='green')
99
+
100
+ if self.config['dns']['route_to_tcp_server_all_domains']:
101
+ message = "Routing all domains to Built-in TCP Server."
102
+ print_api(message, logger=self.logger, color='green')
103
+
104
+ if self.config['dns']['regular_resolving']:
105
+ message = f"Routing all domains to Live DNS Service: {self.config['dns']['forwarding_dns_service_ipv4']}"
106
+ print_api(message, logger=self.logger, color='green')
97
107
 
98
108
  # The list that will hold all the threads that can be joined later
99
109
  threads_list: list = list()
@@ -201,22 +211,28 @@ class DnsServer:
201
211
  else:
202
212
  # Check if the incoming Record is "A" record.
203
213
  if qtype_string == "A":
204
- # If so, check if 'route_to_tcp_server_only_engine_domains' is set to 'True' in 'config.ini'.
214
+ # Check if 'route_to_tcp_server_only_engine_domains' is set to 'True' in 'config.ini'.
205
215
  # If so, we need to check if the incoming domain contain any of the 'engine_domains'.
206
216
  if self.config['dns']['route_to_tcp_server_only_engine_domains']:
207
217
  # If current query domain (+ subdomains) CONTAIN any of the domains from modules config
208
218
  # files and current request contains "A" (IPv4) record.
209
219
  if any(x in question_domain for x in self.domain_list):
210
- # If incoming domain contains any of the 'engine_domains' then domain will be forwarded
211
- # to our TCP Server.
220
+ # If incoming domain contains any of the 'engine_domains' then domain will
221
+ # be forwarded to our TCP Server.
212
222
  forward_to_tcp_server = True
213
223
  else:
214
224
  forward_to_tcp_server = False
215
- # If 'route_to_tcp_server_only_engine_domains' was set to 'False' in 'config.ini' file then the
216
- # domains in engine config files doesn't matter, and we'll forward all 'A' records domains to
217
- # our TCP Server.
218
- else:
225
+
226
+ # If 'route_to_tcp_server_all_domains' was set to 'False' in 'config.ini' file then
227
+ # we'll forward all 'A' records domains to the Built-in TCP Server.
228
+ if self.config['dns']['route_to_tcp_server_all_domains']:
219
229
  forward_to_tcp_server = True
230
+
231
+ # If 'regular_resolving' was set to 'True' in 'config.ini' file then
232
+ # we'll forward all 'A' records domains to the Live DNS Service.
233
+ if self.config['dns']['regular_resolving']:
234
+ forward_to_tcp_server = False
235
+
220
236
  # If incoming record is not an "A" record, then it will not be forwarded to our TCP Server.
221
237
  else:
222
238
  forward_to_tcp_server = False
@@ -1,14 +1,22 @@
1
+ import sys
1
2
  import subprocess
2
3
  import shutil
4
+ import time
3
5
 
6
+ from ..print_api import print_api
4
7
 
5
- def install_package(package: str):
8
+
9
+ def install_packages(package_list: list[str]):
6
10
  """
7
11
  Function installs a package using apt-get.
8
- :param package: str, package name.
12
+ :param package_list: list of strings, package names to install.
9
13
  :return:
10
14
  """
11
- subprocess.check_call(['sudo', 'apt-get', 'install', '-y', package])
15
+
16
+ # Construct the command with the package list
17
+ command = ["sudo", "apt-get", "install", "-y"] + package_list
18
+
19
+ subprocess.check_call(command)
12
20
 
13
21
 
14
22
  def is_package_installed(package: str) -> bool:
@@ -22,3 +30,102 @@ def is_package_installed(package: str) -> bool:
22
30
  return False
23
31
  else:
24
32
  return True
33
+
34
+
35
+ def update_system_packages():
36
+ """
37
+ Function updates the system packages.
38
+ :return:
39
+ """
40
+ subprocess.check_call(['sudo', 'apt-get', 'update'])
41
+
42
+
43
+ def upgrade_system_packages():
44
+ """
45
+ Function upgrades the system packages.
46
+ :return:
47
+ """
48
+ subprocess.check_call(['sudo', 'apt-get', 'upgrade', '-y'])
49
+
50
+
51
+ def is_service_running(service_name: str, return_false_on_error: bool = False) -> bool:
52
+ try:
53
+ # Use subprocess to run 'systemctl is-active' and capture its output
54
+ status = subprocess.check_output(['systemctl', 'is-active', service_name], text=True).strip()
55
+ except subprocess.CalledProcessError as e:
56
+ if return_false_on_error:
57
+ # Handle error if systemctl command fails
58
+ return False
59
+ else:
60
+ # Raise the exception if return_false_on_error is False
61
+ raise e
62
+
63
+ if status == "active":
64
+ return True
65
+ else:
66
+ return False
67
+
68
+
69
+ def enable_service(service_name: str):
70
+ """
71
+ Function enables a service.
72
+ :param service_name: str, the service name.
73
+ :return:
74
+ """
75
+ subprocess.check_call(['sudo', 'systemctl', 'enable', service_name])
76
+
77
+
78
+ def start_service(service_name: str):
79
+ """
80
+ Function starts a service.
81
+ :param service_name: str, the service name.
82
+ :return:
83
+ """
84
+ subprocess.check_call(['sudo', 'systemctl', 'start', service_name])
85
+
86
+
87
+ def start_enable_service_check_availability(
88
+ service_name: str,
89
+ wait_time_seconds: float = 30,
90
+ exit_on_error: bool = True,
91
+ start_service_bool: bool = True,
92
+ enable_service_bool: bool = True,
93
+ check_service_running: bool = True,
94
+ print_kwargs: dict = None
95
+ ):
96
+ """
97
+ Function starts and enables a service and checks its availability.
98
+
99
+ :param service_name: str, the service name.
100
+ :param wait_time_seconds: float, the time to wait after starting the service before checking the service
101
+ availability.
102
+ :param exit_on_error: bool, if True, the function will exit the program if the service is not available.
103
+ :param start_service_bool: bool, if True, the service will be started.
104
+ :param enable_service_bool: bool, if True, the service will be enabled.
105
+ :param check_service_running: bool, if True, the function will check if the service is running.
106
+ :param print_kwargs: dict, the print arguments.
107
+ :return:
108
+ """
109
+
110
+ if not start_service_bool and not enable_service_bool:
111
+ raise ValueError("Either 'start_service_bool' or 'enable_service_bool' must be True.")
112
+
113
+ # Start and enable the service.
114
+ if start_service_bool:
115
+ start_service(service_name)
116
+ if enable_service_bool:
117
+ enable_service(service_name)
118
+
119
+ if check_service_running:
120
+ print_api(
121
+ f"Waiting {str(wait_time_seconds)} seconds for the program to start before availability check...",
122
+ **(print_kwargs or {}))
123
+ time.sleep(wait_time_seconds)
124
+
125
+ if not is_service_running(service_name):
126
+ print_api(
127
+ f"[{service_name}] service failed to start.", color='red', error_type=True, **(print_kwargs or {}))
128
+ if exit_on_error:
129
+ sys.exit(1)
130
+ else:
131
+ print_api(f"[{service_name}] service is running.", color='green', **(print_kwargs or {}))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: atomicshop
3
- Version: 2.9.13
3
+ Version: 2.9.15
4
4
  Summary: Atomic functions and classes to make developer life easier
5
5
  Author: Denis Kras
6
6
  License: MIT License
@@ -1,4 +1,4 @@
1
- atomicshop/__init__.py,sha256=1mDlW2D2mjBVL1hBbLyWpj9YZ0vnfn0nL8Ik-itVx5k,123
1
+ atomicshop/__init__.py,sha256=YjtN4-RYTZwCTFS1O3pUEqPdO7RNYB0bgcXRvqPDH1Y,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
@@ -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=SMIa9H4E3CgpZ4Z8HmYx_7SMiwgsJHTogfZ9vE_cTPo,42808
17
+ atomicshop/filesystem.py,sha256=kMsAMp6ij1j1Qdd-T1H8A-5PYD6zH4cTLMwBnQoHgJ8,42791
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
@@ -24,7 +24,7 @@ atomicshop/keyboard_press.py,sha256=1W5kRtOB75fulVx-uF2yarBhW0_IzdI1k73AnvXstk0,
24
24
  atomicshop/pbtkmultifile_argparse.py,sha256=aEk8nhvoQVu-xyfZosK3ma17CwIgOjzO1erXXdjwtS4,4574
25
25
  atomicshop/permissions.py,sha256=GYWxm9niuJWY0pWCnASF34_HiTuvhTamn8BCgcFyVAk,2540
26
26
  atomicshop/print_api.py,sha256=DhbCQd0MWZZ5GYEk4oTu1opRFC-b31g1VWZgTGewG2Y,11568
27
- atomicshop/process.py,sha256=5lqepm1psRbz66J4MB43ou6HHyac9F34QJedGukwAnk,14188
27
+ atomicshop/process.py,sha256=SXaqG8pzNkHvppPhuhixEIXSaqbeDlTUFLaS5bYSp54,14176
28
28
  atomicshop/process_name_cmd.py,sha256=TNAK6kQZm5JKWzEW6QLqVHEG98ZLNDQiSS4YwDk8V8c,3830
29
29
  atomicshop/process_poller.py,sha256=WfmwCLALfTYOq8ri0vkPeqq8ruEyA_43DaN--CU2_XY,10854
30
30
  atomicshop/python_file_patcher.py,sha256=kd3rBWvTcosLEk-7TycNdfKW9fZbe161iVwmH4niUo0,5515
@@ -64,6 +64,7 @@ atomicshop/addons/process_list/process_list.cpp,sha256=e7olpLfLVg9vQnjEr5L2Y8aWG
64
64
  atomicshop/addons/process_list/compiled/Win10x64/process_list.dll,sha256=SkAZvYAfSbzQTTq-5aL6_dYR2rA4DHbgyenFfgLFzW0,266752
65
65
  atomicshop/addons/process_list/compiled/Win10x64/process_list.exp,sha256=VTph513eqa6f6HmqAj_6mBS1Rf9G56bgYqZNuDePYcs,708
66
66
  atomicshop/addons/process_list/compiled/Win10x64/process_list.lib,sha256=n9c2MVPs3GBNoOQjMesAwzNpv5aFZsW8c-ADS7GYRhA,1886
67
+ atomicshop/archiver/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
67
68
  atomicshop/archiver/_search_in_zip.py,sha256=dd8qFSvIhcKmtnPj_uYNJFPmMwZp4tZys0kKgTw_ACw,8385
68
69
  atomicshop/archiver/archiver.py,sha256=BomnK7zT-nQXA1z0i2R2aTv8eu88wPx7tf2HtOdbmEc,1280
69
70
  atomicshop/archiver/search_in_archive.py,sha256=mEngDfULXBd3Oio8a2SUtynfJASVLsH74XIYJOWVkH0,10467
@@ -72,7 +73,7 @@ atomicshop/archiver/zip.py,sha256=k742K1bEDtc_4N44j_Waebi-uOkxxavqltvV6q-BLW4,14
72
73
  atomicshop/basics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
73
74
  atomicshop/basics/ansi_escape_codes.py,sha256=WtIkm-BjSZS5J5irDUdAMBNvdX-qXFZcTX98jcBMpJE,3140
74
75
  atomicshop/basics/argparse_template.py,sha256=horwgSf3MX1ZgRnYxtmmQuz9OU_vKrKggF65gmjlmfg,5836
75
- atomicshop/basics/booleans.py,sha256=416QbQeYWFb5RMsMAHSH1Nj6IMaQwBO_uZH1JT87Krc,2020
76
+ atomicshop/basics/booleans.py,sha256=va3LYIaSOhjdifW4ZEesnIQxBICNHyQjUAkYelzchhE,2047
76
77
  atomicshop/basics/bytes_arrays.py,sha256=WvSRDhIGt1ywF95t-yNgpxLm1nlZUbM1Dz6QckcyE8Y,5915
77
78
  atomicshop/basics/classes.py,sha256=EijW_g4EhdNBnKPMG3nT3HjFspTchtM7to6zm9Ad_Mk,9771
78
79
  atomicshop/basics/dicts.py,sha256=N696f-vamrCcLpLOvtRpHrEmLfyOqkCyW8JDZnwYLpg,11295
@@ -105,15 +106,15 @@ atomicshop/file_io/tomls.py,sha256=oa0Wm8yMkPRXKN9jgBuTnKbioSOee4mABW5IMUFCYyU,3
105
106
  atomicshop/file_io/xlsxs.py,sha256=v_dyg9GD4LqgWi6wA1QuWRZ8zG4ZwB6Dz52ytdcmmmI,2184
106
107
  atomicshop/file_io/xmls.py,sha256=zh3SuK-dNaFq2NDNhx6ivcf4GYCfGM8M10PcEwDSpxk,2104
107
108
  atomicshop/mitm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
108
- atomicshop/mitm/connection_thread_worker.py,sha256=7f7T3t6ltndzb3125DgyRTzsD-oAbAfewDIhpNEeHRY,20630
109
- atomicshop/mitm/import_config.py,sha256=BPZ62ozMUaUKn7Crt6dhzvUgD3dSKd17kMfbJNObvlI,7486
110
- atomicshop/mitm/initialize_engines.py,sha256=b4iNwZEzIF2LlwScET_h_Hj_K8PKPcv8S9P7Jvpb-mw,7727
111
- atomicshop/mitm/initialize_mitm_server.py,sha256=8Rwq4OzA4VKpzWNhxn8-CkCY_UdPIK64J4UrtD7oE3M,11230
109
+ atomicshop/mitm/connection_thread_worker.py,sha256=PQ8bwOgrPudYP5oPnSi_DWaKXOi038M8TMImlLkxuPI,20486
110
+ atomicshop/mitm/import_config.py,sha256=_V-IVJ7a1L6E-VOR4CDfZj-S1odbsIlBe13ij0NlpqY,7974
111
+ atomicshop/mitm/initialize_engines.py,sha256=UGdT5DKYNri3MNOxESP7oeSxYiUDrVilJ4jic_nwdew,8055
112
+ atomicshop/mitm/initialize_mitm_server.py,sha256=aXNZlRu1_RGjC7lagvs2Q8rjQiygxYucy-U4C_SBnsk,13871
112
113
  atomicshop/mitm/message.py,sha256=u2U2f2SOHdBNU-6r1Ik2W14ai2EOwxUV4wVfGZA098k,1732
113
114
  atomicshop/mitm/shared_functions.py,sha256=NeHABBlY-tmQRooWGVl2jZQx1wSTKJtEqG7mMvF2Jqo,4268
114
115
  atomicshop/mitm/statistic_analyzer.py,sha256=1g5l6X-NbnHvh_TREJRumTDWgE4ixUNJ8pKGneKcf4Y,23524
115
116
  atomicshop/mitm/engines/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
116
- atomicshop/mitm/engines/create_module_template.py,sha256=ZQVWR1HUiYF5oLqNEk_qG5qxtHnkRzcxH0Nal04qY_k,4879
117
+ atomicshop/mitm/engines/create_module_template.py,sha256=tRjVSm1sD6FzML71Qbuwvita0qsusdFGm8NZLsZ-XMs,4853
117
118
  atomicshop/mitm/engines/create_module_template_example.py,sha256=X5xhvbV6-g9jU_bQVhf_crZmaH50LRWz3bS-faQ18ds,489
118
119
  atomicshop/mitm/engines/__parent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
119
120
  atomicshop/mitm/engines/__parent/parser___parent.py,sha256=sBvPlFMOCTdS-qgW9uTKvvJCFT5nNW9n3UyhaFcjAfg,1365
@@ -141,12 +142,12 @@ atomicshop/wrappers/_process_wrapper_tar.py,sha256=WUMZFKNrlG4nJP9tWZ51W7BR1j_pI
141
142
  atomicshop/wrappers/astw.py,sha256=VkYfkfyc_PJLIOxByT6L7B8uUmKY6-I8XGZl4t_z828,4239
142
143
  atomicshop/wrappers/configparserw.py,sha256=JwDTPjZoSrv44YKwIRcjyUnpN-FjgXVfMqMK_tJuSgU,22800
143
144
  atomicshop/wrappers/cryptographyw.py,sha256=H5NaHHDkr97QYhUrHFO9vY218u8k3N3Zgh6bQRnicUE,13140
144
- atomicshop/wrappers/ffmpegw.py,sha256=YKptcdNQC1wyPLRLvc24fIPr4_rj8IHH01UUzt6XFO0,6039
145
+ atomicshop/wrappers/ffmpegw.py,sha256=wcq0ZnAe0yajBOuTKZCCaKI7CDBjkq7FAgdW5IsKcVE,6031
145
146
  atomicshop/wrappers/githubw.py,sha256=AjD0VUlV2Kcddns2OaGmyX-FOAvdps-8SPSWS05E0QA,4809
146
147
  atomicshop/wrappers/numpyw.py,sha256=sBV4gSKyr23kXTalqAb1oqttzE_2XxBooCui66jbAqc,1025
147
148
  atomicshop/wrappers/process_wrapper_pbtk.py,sha256=ycPmBRnv627RWks6N8OhxJQe8Gu3h3Vwj-4HswPOw0k,599
148
149
  atomicshop/wrappers/pyopensslw.py,sha256=OBWxA6EJ2vU_Qlf4M8m6ilcG3hyYB4yB0EsXUf7NhEU,6804
149
- atomicshop/wrappers/ubuntu_terminal.py,sha256=FGY9pqgUrRDtoLeIdSqDQMZdyfPtLBYLiyg-HDq2a_g,532
150
+ atomicshop/wrappers/ubuntu_terminal.py,sha256=1CcTXASzxdFFFJTf3G1OtHcs8abbn_jgkPsY0OzEs1w,4132
150
151
  atomicshop/wrappers/wslw.py,sha256=AKphiHLSddL7ErevUowr3f9Y1AgGz_R3KZ3NssW07h8,6959
151
152
  atomicshop/wrappers/certauthw/certauth.py,sha256=hKedW0DOWlEigSNm8wu4SqHkCQsGJ1tJfH7s4nr3Bk0,12223
152
153
  atomicshop/wrappers/certauthw/certauthw.py,sha256=4WvhjANI7Kzqrr_nKmtA8Kf7B6rute_5wfP65gwQrjw,8082
@@ -155,8 +156,10 @@ atomicshop/wrappers/dockerw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMp
155
156
  atomicshop/wrappers/dockerw/dockerw.py,sha256=w8zSJr5C7cbvbuG09ORCpAe0BOcibqqL_Z2EKEBHYK4,6266
156
157
  atomicshop/wrappers/dockerw/install_docker.py,sha256=dpSOmD690oLukoLCo0u6Pzh5fRyCWBuSQEtG8VwC3jk,2765
157
158
  atomicshop/wrappers/elasticsearchw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
158
- atomicshop/wrappers/elasticsearchw/config_basic.py,sha256=nMtWYBlkQwzUMTLBaL3US8-f87bNPS_wzVxpLR1D6Hc,121
159
- atomicshop/wrappers/elasticsearchw/elasticsearchw.py,sha256=BmBTS6WYYO_XK7ZAzl3uL5P_YzDvjDTkokvvHd3t6Yw,9760
159
+ atomicshop/wrappers/elasticsearchw/config_basic.py,sha256=XJMKKfDrUq9ZKxYnQ-xFJxSA51z31Nn4eB8_n_hryVk,800
160
+ atomicshop/wrappers/elasticsearchw/elasticsearchw.py,sha256=7TqFdEFznO8NlligJhEKk1vm641ALpCYdaRl1uoXdzM,9768
161
+ atomicshop/wrappers/elasticsearchw/infrastructure.py,sha256=J1hKIEQA8ImRUmkM25fbmwHbZPC9VnT9NK1_kOfXitA,8311
162
+ atomicshop/wrappers/elasticsearchw/install_elastic.py,sha256=Lez_Tt21Jlprz7EaRZlppzbpTkYerWkkHd9cfIwcyy8,8308
160
163
  atomicshop/wrappers/elasticsearchw/queries/__init__.py,sha256=KBjT-bAt75CJsx1Apko9mpuFU4pfZV8DcGWQvpX65RU,78
161
164
  atomicshop/wrappers/elasticsearchw/queries/aggregation.py,sha256=N9a5yMMnb10sMa_x1qJBFQpgyJ49UWo8_vxuqmUtZ1A,1742
162
165
  atomicshop/wrappers/elasticsearchw/queries/info.py,sha256=P_VhhBo8MvRI4Shi-bh4RsYtlYNRKRBzScXPC64Up_Q,2900
@@ -173,7 +176,7 @@ atomicshop/wrappers/factw/fact_extractor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5
173
176
  atomicshop/wrappers/factw/fact_extractor/docker_image.py,sha256=jJAoJNQ4aoATjn3x_va031Obb4oBtcqCY40hydghm0s,2504
174
177
  atomicshop/wrappers/factw/fact_extractor/get_extractor.py,sha256=2mfOAftHIlCcGt1s7MWdq7DsDCuI6wX3MtvcEZ4SK-0,756
175
178
  atomicshop/wrappers/factw/install/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
176
- atomicshop/wrappers/factw/install/install_after_restart.py,sha256=Wixuc-foMA0qGjzypbbQ5sdE-F72yIKmrI9c6xwLY-g,1571
179
+ atomicshop/wrappers/factw/install/install_after_restart.py,sha256=roM1W2hkDynpEKda55xd7AsZxodsFj8i4wmFGt_HHzA,1558
177
180
  atomicshop/wrappers/factw/install/pre_install_and_install_before_restart.py,sha256=OWlT1h9XJChuKOT3GPa69nnrqxgM4TD9Cy-GR7E23LY,2377
178
181
  atomicshop/wrappers/factw/postgresql/__init__.py,sha256=xMBn2d3Exo23IPP2F_9-SXmOlhFbwWDgS9KwozSTjA0,162
179
182
  atomicshop/wrappers/factw/postgresql/analysis.py,sha256=2Rxzy2jyq3zEKIo53z8VkjuslKE_i5mq2ZpmJAvyd6U,716
@@ -197,7 +200,7 @@ atomicshop/wrappers/loggingw/loggingw.py,sha256=v9WAseZXB50LluT9rIUcRvvevg2nLVKP
197
200
  atomicshop/wrappers/loggingw/reading.py,sha256=xs7L6Jo-vedrhCVP7m-cJo0VhWmoSoK86avR4Tm0kG4,3675
198
201
  atomicshop/wrappers/playwrightw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
199
202
  atomicshop/wrappers/playwrightw/_tryouts.py,sha256=l1BLkFsiIMNlgv7nfZd1XGEvXQkIQkIcg48__9OaC00,4920
200
- atomicshop/wrappers/playwrightw/base.py,sha256=zwHfbFZV7qqpmReJg5lEpKtOO23DRxEd61ZdoLBU_9Q,9833
203
+ atomicshop/wrappers/playwrightw/base.py,sha256=WeRpx8otdXuKSr-BjY-uCJTze21kbPpfitoOjKQz5-g,9818
201
204
  atomicshop/wrappers/playwrightw/combos.py,sha256=215y7wugyyBrFK9_0WutnMXsF1jqJ2PLm9eHEa2PMz0,7145
202
205
  atomicshop/wrappers/playwrightw/engine.py,sha256=Ik9hysgJAtjbzr6ED-9gRBaxnt3cNt5hu1u4ut_M3To,14861
203
206
  atomicshop/wrappers/playwrightw/javascript.py,sha256=CL3tVE9C4SVvy76FEgGCl77B-xziCG6JZR5Ed8IfcSo,1112
@@ -216,7 +219,7 @@ atomicshop/wrappers/socketw/accepter.py,sha256=HQC1EyZmyUtVEfFbaBkHCE-VZp6RWyd9m
216
219
  atomicshop/wrappers/socketw/base.py,sha256=1vvg8EhRGvnxdrRAm1VJSLCXkm2SZDHRjdpTuhkH3Mg,1844
217
220
  atomicshop/wrappers/socketw/certificator.py,sha256=SxCKFyBlwzs4uohugfBokOYQpZJyH8KY46m87Q23n6w,9017
218
221
  atomicshop/wrappers/socketw/creator.py,sha256=C-l57G854HAtWJonVbgfQge290-Dg0Ov4aurJAWIKls,11199
219
- atomicshop/wrappers/socketw/dns_server.py,sha256=ql3R5lSKajoR_xPr9myk08ngb5dzk77henwOmqCtXIo,41225
222
+ atomicshop/wrappers/socketw/dns_server.py,sha256=laMR_opplvytVTvVcztNoDChZGMCDR31fDQejrCNaEI,42032
220
223
  atomicshop/wrappers/socketw/exception_wrapper.py,sha256=_YDnzyEcUnV6VISU3bk-UPdnsMvHjKJBHwxLMTsxQu8,8495
221
224
  atomicshop/wrappers/socketw/get_process.py,sha256=APw_oOXsuR5KljYesd4J8MuzR-kaw2ez3MN3oD_h9Qc,5226
222
225
  atomicshop/wrappers/socketw/receiver.py,sha256=m8hXKOa8dqEQGUdcbYjshH8-j0CsMGRkge2ifYKhaAw,9050
@@ -227,8 +230,8 @@ atomicshop/wrappers/socketw/socket_server_tester.py,sha256=AhpurHJmP2kgzHaUbq5ey
227
230
  atomicshop/wrappers/socketw/socket_wrapper.py,sha256=aXBwlEIJhFT0-c4i8iNlFx2It9VpCEpsv--5Oqcpxao,11624
228
231
  atomicshop/wrappers/socketw/ssl_base.py,sha256=k4V3gwkbq10MvOH4btU4onLX2GNOsSfUAdcHmL1rpVE,2274
229
232
  atomicshop/wrappers/socketw/statistics_csv.py,sha256=t3dtDEfN47CfYVi0CW6Kc2QHTEeZVyYhc57IYYh5nmA,826
230
- atomicshop-2.9.13.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
231
- atomicshop-2.9.13.dist-info/METADATA,sha256=D2qXuN1VKUUI9zVBO2sg6Wzg2LP1WiIfLbh0_-LVXg4,10423
232
- atomicshop-2.9.13.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
233
- atomicshop-2.9.13.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
234
- atomicshop-2.9.13.dist-info/RECORD,,
233
+ atomicshop-2.9.15.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
234
+ atomicshop-2.9.15.dist-info/METADATA,sha256=Pvhwhgb3o01SAy7xGphWOTiNIaCfMSxpVvgdSzOX9XE,10423
235
+ atomicshop-2.9.15.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
236
+ atomicshop-2.9.15.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
237
+ atomicshop-2.9.15.dist-info/RECORD,,