atomicshop 2.21.0__py3-none-any.whl → 2.21.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/mitm/connection_thread_worker.py +124 -157
- atomicshop/mitm/engines/__parent/responder___parent.py +43 -43
- atomicshop/mitm/engines/__reference_general/responder___reference_general.py +43 -43
- {atomicshop-2.21.0.dist-info → atomicshop-2.21.1.dist-info}/METADATA +1 -1
- {atomicshop-2.21.0.dist-info → atomicshop-2.21.1.dist-info}/RECORD +9 -9
- {atomicshop-2.21.0.dist-info → atomicshop-2.21.1.dist-info}/LICENSE.txt +0 -0
- {atomicshop-2.21.0.dist-info → atomicshop-2.21.1.dist-info}/WHEEL +0 -0
- {atomicshop-2.21.0.dist-info → atomicshop-2.21.1.dist-info}/top_level.txt +0 -0
atomicshop/__init__.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from datetime import datetime
|
|
2
2
|
import threading
|
|
3
3
|
import queue
|
|
4
|
-
import copy
|
|
5
4
|
import socket
|
|
6
5
|
|
|
7
6
|
from ..wrappers.socketw import receiver, sender, socket_client, base
|
|
@@ -182,24 +181,27 @@ def thread_worker_main(
|
|
|
182
181
|
network_logger.info("Thread Finished. Will continue listening on the Main thread")
|
|
183
182
|
|
|
184
183
|
def create_responder_response(client_message: ClientMessage) -> list[bytes]:
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
# If it's the first cycle and the protocol is Websocket, then we'll create the HTTP Handshake
|
|
189
|
-
# response automatically.
|
|
190
|
-
if protocol == 'Websocket' and client_receive_count == 1:
|
|
191
|
-
responses: list = list()
|
|
192
|
-
responses.append(
|
|
193
|
-
websocket_parse.create_byte_http_response(client_message.request_raw_bytes))
|
|
184
|
+
if client_message.action == 'service_connect':
|
|
185
|
+
return responder.create_connect_response(client_message)
|
|
194
186
|
else:
|
|
195
|
-
#
|
|
196
|
-
|
|
187
|
+
# Since we're in response mode, we'll record the request anyway, after the responder did its job.
|
|
188
|
+
# client_message.info = "In Server Response Mode"
|
|
189
|
+
|
|
190
|
+
# If it's the first cycle and the protocol is Websocket, then we'll create the HTTP Handshake
|
|
191
|
+
# response automatically.
|
|
192
|
+
if protocol == 'Websocket' and client_receive_count == 1:
|
|
193
|
+
responses: list = list()
|
|
194
|
+
responses.append(
|
|
195
|
+
websocket_parse.create_byte_http_response(client_message.request_raw_bytes))
|
|
196
|
+
else:
|
|
197
|
+
# Creating response for parsed message and printing
|
|
198
|
+
responses: list = responder.create_response(client_message)
|
|
197
199
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
200
|
+
# Output first 100 characters of all the responses in the list.
|
|
201
|
+
for response_raw_bytes_single in responses:
|
|
202
|
+
responder.logger.info(f"{response_raw_bytes_single[0: 100]}...")
|
|
201
203
|
|
|
202
|
-
|
|
204
|
+
return responses
|
|
203
205
|
|
|
204
206
|
def create_client_socket(client_message: ClientMessage):
|
|
205
207
|
# If there is a custom certificate for the client for this domain, then we'll use it.
|
|
@@ -303,53 +305,11 @@ def thread_worker_main(
|
|
|
303
305
|
|
|
304
306
|
return client_message
|
|
305
307
|
|
|
306
|
-
def responder_thread_worker():
|
|
307
|
-
nonlocal exception_or_close_in_receiving_thread
|
|
308
|
-
|
|
309
|
-
client_message: ClientMessage = client_message_first_start()
|
|
310
|
-
try:
|
|
311
|
-
while True:
|
|
312
|
-
client_message = responder_queue.get()
|
|
313
|
-
print_api(f"Got message from queue, action: [{client_message.action}]", logger=network_logger, logger_method='info')
|
|
314
|
-
|
|
315
|
-
# If the message is not a ClientMessage object, then we'll break the loop, since it is the exit signal.
|
|
316
|
-
if not isinstance(client_message, ClientMessage):
|
|
317
|
-
return
|
|
318
|
-
|
|
319
|
-
if client_message.action == 'service_connect':
|
|
320
|
-
raw_responses: list[bytes] = responder.create_connect_response(client_message)
|
|
321
|
-
else:
|
|
322
|
-
raw_responses: list[bytes] = create_responder_response(client_message)
|
|
323
|
-
print_api(f"Got responses from responder, count: [{len(raw_responses)}]", logger=network_logger, logger_method='info')
|
|
324
|
-
|
|
325
|
-
is_socket_closed: bool = False
|
|
326
|
-
for response_raw_bytes in raw_responses:
|
|
327
|
-
client_message.reinitialize_dynamic_vars()
|
|
328
|
-
client_message.timestamp = datetime.now()
|
|
329
|
-
client_message.response_raw_bytes = response_raw_bytes
|
|
330
|
-
|
|
331
|
-
record_and_statistics_write(client_message)
|
|
332
|
-
|
|
333
|
-
error_on_send: str = sender.Sender(
|
|
334
|
-
ssl_socket=client_socket, class_message=client_message.response_raw_bytes,
|
|
335
|
-
logger=network_logger).send()
|
|
336
|
-
|
|
337
|
-
# If there was problem with sending data, we'll break the main while loop.
|
|
338
|
-
if error_on_send:
|
|
339
|
-
client_message.errors.append(error_on_send)
|
|
340
|
-
record_and_statistics_write(client_message)
|
|
341
|
-
is_socket_closed = True
|
|
342
|
-
|
|
343
|
-
if is_socket_closed:
|
|
344
|
-
exception_or_close_in_receiving_thread = True
|
|
345
|
-
return
|
|
346
|
-
except Exception as exc:
|
|
347
|
-
handle_exceptions_on_sub_connection_thread(client_message, client_exception_queue, exc)
|
|
348
|
-
|
|
349
308
|
def receive_send_start(
|
|
350
309
|
receiving_socket,
|
|
351
310
|
sending_socket = None,
|
|
352
|
-
exception_queue: queue.Queue = None
|
|
311
|
+
exception_queue: queue.Queue = None,
|
|
312
|
+
client_connection_message: ClientMessage = None
|
|
353
313
|
):
|
|
354
314
|
nonlocal client_receive_count
|
|
355
315
|
nonlocal server_receive_count
|
|
@@ -370,59 +330,87 @@ def thread_worker_main(
|
|
|
370
330
|
raise ValueError(f"Unknown side of the socket: {receiving_socket}")
|
|
371
331
|
|
|
372
332
|
while True:
|
|
373
|
-
|
|
333
|
+
# pass the socket connect to responder.
|
|
334
|
+
if side == 'Service' and client_connection_message:
|
|
335
|
+
client_message = client_connection_message
|
|
374
336
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
337
|
+
bytes_to_send_list: list[bytes] = create_responder_response(client_message)
|
|
338
|
+
print_api(f"Got responses from responder, count: [{len(bytes_to_send_list)}]", logger=network_logger,
|
|
339
|
+
logger_method='info')
|
|
378
340
|
else:
|
|
379
|
-
|
|
380
|
-
current_count = server_receive_count
|
|
341
|
+
client_message.reinitialize_dynamic_vars()
|
|
381
342
|
|
|
382
|
-
|
|
383
|
-
|
|
343
|
+
if side == 'Client':
|
|
344
|
+
client_receive_count += 1
|
|
345
|
+
current_count = client_receive_count
|
|
346
|
+
else:
|
|
347
|
+
server_receive_count += 1
|
|
348
|
+
current_count = server_receive_count
|
|
384
349
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
ssl_socket=receiving_socket, logger=network_logger).receive()
|
|
350
|
+
network_logger.info(
|
|
351
|
+
f"Initializing Receiver for {side} cycle: {str(current_count)}")
|
|
388
352
|
|
|
389
|
-
|
|
390
|
-
|
|
353
|
+
# Getting message from the client over the socket using specific class.
|
|
354
|
+
received_raw_data, is_socket_closed, error_message = receiver.Receiver(
|
|
355
|
+
ssl_socket=receiving_socket, logger=network_logger).receive()
|
|
391
356
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
process_client_raw_data(received_raw_data, error_message, client_message)
|
|
395
|
-
client_message.action = 'client_receive'
|
|
396
|
-
# In case of service socket, we'll process the raw data specifically for the service.
|
|
397
|
-
else:
|
|
398
|
-
process_server_raw_data(received_raw_data, error_message, client_message)
|
|
399
|
-
client_message.action = 'service_receive'
|
|
357
|
+
# Getting current time of message received, either from client or service.
|
|
358
|
+
client_message.timestamp = datetime.now()
|
|
400
359
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
360
|
+
# In case of client socket, we'll process the raw data specifically for the client.
|
|
361
|
+
if side == 'Client':
|
|
362
|
+
process_client_raw_data(received_raw_data, error_message, client_message)
|
|
363
|
+
client_message.action = 'client_receive'
|
|
364
|
+
# In case of service socket, we'll process the raw data specifically for the service.
|
|
365
|
+
else:
|
|
366
|
+
process_server_raw_data(received_raw_data, error_message, client_message)
|
|
367
|
+
client_message.action = 'service_receive'
|
|
368
|
+
|
|
369
|
+
# If there was an exception in the service thread, then receiving empty bytes doesn't mean that
|
|
370
|
+
# the socket was closed by the other side, it means that the service thread closed the socket.
|
|
371
|
+
if (received_raw_data == b'' or error_message) and exception_or_close_in_receiving_thread:
|
|
372
|
+
print_api("Both sockets are closed, breaking the loop", logger=network_logger,
|
|
373
|
+
logger_method='info')
|
|
374
|
+
return
|
|
407
375
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
376
|
+
# We will record only if there was no closing signal, because if there was, it means that we initiated
|
|
377
|
+
# the close on the opposite socket.
|
|
378
|
+
record_and_statistics_write(client_message)
|
|
379
|
+
|
|
380
|
+
# Now send it to requester/responder.
|
|
381
|
+
if side == 'Client':
|
|
382
|
+
# Send to requester.
|
|
383
|
+
bytes_to_send_list: list[bytes] = [client_message.request_raw_bytes]
|
|
384
|
+
else:
|
|
385
|
+
bytes_to_send_list: list[bytes] = create_responder_response(client_message)
|
|
386
|
+
print_api(f"Got responses from responder, count: [{len(bytes_to_send_list)}]",
|
|
387
|
+
logger=network_logger,
|
|
388
|
+
logger_method='info')
|
|
389
|
+
|
|
390
|
+
if is_socket_closed:
|
|
391
|
+
exception_or_close_in_receiving_thread = True
|
|
392
|
+
finish_thread()
|
|
393
|
+
return
|
|
411
394
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
395
|
+
# If nothing was passed from the responder, and the client message is the connection message, then we'll skip to the next iteration.
|
|
396
|
+
if not bytes_to_send_list and client_connection_message:
|
|
397
|
+
client_connection_message = None
|
|
398
|
+
continue
|
|
416
399
|
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
responder_queue.put(copy.deepcopy(client_message))
|
|
420
|
-
else:
|
|
421
|
-
# if side == 'Client':
|
|
422
|
-
# raise NotImplementedError
|
|
400
|
+
is_socket_closed: bool = False
|
|
401
|
+
for bytes_to_send_single in bytes_to_send_list:
|
|
423
402
|
client_message.reinitialize_dynamic_vars()
|
|
403
|
+
client_message.timestamp = datetime.now()
|
|
404
|
+
|
|
405
|
+
if side == 'Client':
|
|
406
|
+
client_message.request_raw_bytes = bytes_to_send_single
|
|
407
|
+
else:
|
|
408
|
+
client_message.response_raw_bytes = bytes_to_send_single
|
|
409
|
+
|
|
410
|
+
record_and_statistics_write(client_message)
|
|
411
|
+
|
|
424
412
|
error_on_send: str = sender.Sender(
|
|
425
|
-
ssl_socket=sending_socket, class_message=
|
|
413
|
+
ssl_socket=sending_socket, class_message=bytes_to_send_single,
|
|
426
414
|
logger=network_logger).send()
|
|
427
415
|
|
|
428
416
|
if error_on_send:
|
|
@@ -439,9 +427,11 @@ def thread_worker_main(
|
|
|
439
427
|
# If the socket was closed on message receive, then we'll break the loop only after send.
|
|
440
428
|
if is_socket_closed or error_on_send:
|
|
441
429
|
exception_or_close_in_receiving_thread = True
|
|
442
|
-
responder_queue.put('exit')
|
|
443
430
|
finish_thread()
|
|
444
431
|
return
|
|
432
|
+
|
|
433
|
+
# For next iteration to start in case this iteration was responsible to process connection message, we need to set it to None.
|
|
434
|
+
client_connection_message = None
|
|
445
435
|
except Exception as exc:
|
|
446
436
|
# If the sockets were already closed, then there is nothing to do here besides log.
|
|
447
437
|
# if (isinstance(exc, OSError) and exc.errno == 10038 and
|
|
@@ -470,7 +460,6 @@ def thread_worker_main(
|
|
|
470
460
|
# record_and_statistics_write(client_message)
|
|
471
461
|
|
|
472
462
|
finish_thread()
|
|
473
|
-
responder_queue.put('exit')
|
|
474
463
|
exception_queue.put(exc)
|
|
475
464
|
|
|
476
465
|
def handle_exceptions_on_main_connection_thread(
|
|
@@ -522,14 +511,13 @@ def thread_worker_main(
|
|
|
522
511
|
reference_module=reference_module
|
|
523
512
|
)
|
|
524
513
|
parser = found_domain_module.parser_class_object
|
|
525
|
-
responder = found_domain_module.responder_class_object
|
|
526
|
-
|
|
527
|
-
recorder = recorder_no_init(record_path=config_static.LogRec.recordings_path)
|
|
514
|
+
responder = found_domain_module.responder_class_object()
|
|
515
|
+
recorder = found_domain_module.recorder_class_object(record_path=config_static.LogRec.recordings_path)
|
|
528
516
|
|
|
529
517
|
network_logger.info(f"Assigned Modules for [{server_name}]: "
|
|
530
518
|
f"{parser.__name__}, "
|
|
531
|
-
f"{responder.__name__}, "
|
|
532
|
-
f"{
|
|
519
|
+
f"{responder.__class__.__name__}, "
|
|
520
|
+
f"{recorder.__class__.__name__}")
|
|
533
521
|
|
|
534
522
|
|
|
535
523
|
# Initializing the client message object with current thread's data.
|
|
@@ -537,8 +525,6 @@ def thread_worker_main(
|
|
|
537
525
|
client_message_connection: ClientMessage = ClientMessage()
|
|
538
526
|
# This is needed to indicate if there was an exception or socket was closed in any of the receiving thread.
|
|
539
527
|
exception_or_close_in_receiving_thread: bool = False
|
|
540
|
-
# Responder queue for ClientMessage objects.
|
|
541
|
-
responder_queue: queue.Queue = queue.Queue()
|
|
542
528
|
# Queue for http request URI paths.
|
|
543
529
|
http_path_queue: queue.Queue = queue.Queue()
|
|
544
530
|
|
|
@@ -558,15 +544,6 @@ def thread_worker_main(
|
|
|
558
544
|
network_logger.info(f"Thread Created - Client [{client_ip}:{source_port}] | "
|
|
559
545
|
f"Destination service: [{server_name}:{destination_port}]")
|
|
560
546
|
|
|
561
|
-
# If we're in offline mode, we'll start the responder thread.
|
|
562
|
-
if config_static.MainConfig.offline:
|
|
563
|
-
responder_thread: threading.Thread = threading.Thread(
|
|
564
|
-
target=responder_thread_worker, name=f"Thread-{thread_id}-Responder", daemon=True)
|
|
565
|
-
responder_thread.start()
|
|
566
|
-
else:
|
|
567
|
-
# noinspection PyTypeChecker
|
|
568
|
-
responder_thread = None
|
|
569
|
-
|
|
570
547
|
service_client = None
|
|
571
548
|
client_receive_count: int = 0
|
|
572
549
|
server_receive_count: int = 0
|
|
@@ -576,58 +553,48 @@ def thread_worker_main(
|
|
|
576
553
|
# noinspection PyTypeChecker
|
|
577
554
|
connection_error: str = None
|
|
578
555
|
service_socket_instance = None
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
service_socket_instance, connection_error = service_client.service_connection()
|
|
585
|
-
# Now we'll update the server IP with the IP of the service.
|
|
586
|
-
server_ip = service_socket_instance.getpeername()[0]
|
|
587
|
-
client_message_connection.server_ip = server_ip
|
|
588
|
-
else:
|
|
589
|
-
client_message_connection.timestamp = datetime.now()
|
|
590
|
-
client_message_connection.action = 'service_connect'
|
|
591
|
-
client_message_connection.info = 'Server Response Mode'
|
|
592
|
-
responder_queue.put(copy.deepcopy(client_message_connection))
|
|
593
|
-
|
|
594
|
-
if connection_error:
|
|
595
|
-
client_message_connection.timestamp = datetime.now()
|
|
596
|
-
client_message_connection.errors.append(connection_error)
|
|
597
|
-
client_message_connection.action = 'service_connect'
|
|
598
|
-
record_and_statistics_write(client_message_connection)
|
|
556
|
+
client_message_connection.action = 'service_connect'
|
|
557
|
+
client_message_connection.timestamp = datetime.now()
|
|
558
|
+
|
|
559
|
+
if config_static.MainConfig.offline:
|
|
560
|
+
client_message_connection.info = 'Offline Mode'
|
|
599
561
|
else:
|
|
562
|
+
service_client = create_client_socket(client_message_connection)
|
|
563
|
+
service_socket_instance, connection_error = service_client.service_connection()
|
|
564
|
+
# Now we'll update the server IP with the IP of the service.
|
|
565
|
+
server_ip = service_socket_instance.getpeername()[0]
|
|
566
|
+
client_message_connection.server_ip = server_ip
|
|
567
|
+
|
|
568
|
+
if connection_error:
|
|
569
|
+
client_message_connection.errors.append(connection_error)
|
|
570
|
+
record_and_statistics_write(client_message_connection)
|
|
571
|
+
|
|
572
|
+
if not connection_error:
|
|
600
573
|
client_exception_queue: queue.Queue = queue.Queue()
|
|
601
574
|
client_thread = threading.Thread(
|
|
602
|
-
target=receive_send_start,
|
|
575
|
+
target=receive_send_start,
|
|
576
|
+
args=(client_socket, service_socket_instance, client_exception_queue, None),
|
|
603
577
|
name=f"Thread-{thread_id}-Client")
|
|
604
578
|
client_thread.daemon = True
|
|
605
579
|
client_thread.start()
|
|
606
580
|
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
581
|
+
service_exception_queue: queue.Queue = queue.Queue()
|
|
582
|
+
service_thread = threading.Thread(
|
|
583
|
+
target=receive_send_start,
|
|
584
|
+
args=(service_socket_instance, client_socket, service_exception_queue, client_message_connection),
|
|
585
|
+
name=f"Thread-{thread_id}-Service")
|
|
586
|
+
service_thread.daemon = True
|
|
587
|
+
service_thread.start()
|
|
614
588
|
|
|
615
589
|
client_thread.join()
|
|
616
|
-
|
|
617
|
-
responder_thread.join()
|
|
618
|
-
else:
|
|
619
|
-
service_thread.join()
|
|
590
|
+
service_thread.join()
|
|
620
591
|
|
|
621
592
|
# If there was an exception in any of the threads, then we'll raise it here.
|
|
622
593
|
if not client_exception_queue.empty():
|
|
623
594
|
raise client_exception_queue.get()
|
|
624
|
-
if not
|
|
625
|
-
|
|
626
|
-
raise service_exception_queue.get()
|
|
595
|
+
if not service_exception_queue.empty():
|
|
596
|
+
raise service_exception_queue.get()
|
|
627
597
|
|
|
628
598
|
finish_thread()
|
|
629
599
|
except Exception as e:
|
|
630
|
-
if not client_message_connection.timestamp:
|
|
631
|
-
client_message_connection.timestamp = datetime.now()
|
|
632
|
-
|
|
633
600
|
handle_exceptions_on_main_connection_thread(e, client_message_connection)
|
|
@@ -110,48 +110,49 @@ class ResponderParent:
|
|
|
110
110
|
headers: dict,
|
|
111
111
|
body: bytes
|
|
112
112
|
) -> bytes:
|
|
113
|
+
# noinspection GrazieInspection
|
|
113
114
|
"""
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
115
|
+
Create genuine response from input parameters.
|
|
116
|
+
---------------
|
|
117
|
+
The response is built from:
|
|
118
|
+
HTTP-Version HTTP-Status HTTP-Status-String\r\n
|
|
119
|
+
Headers1: Value\r\n
|
|
120
|
+
Headers2: Value\r\n
|
|
121
|
+
\r\n # This is meant to end the headers' section
|
|
122
|
+
Body\r\n\r\n # In most cases Body is ended with '\r\n\r\n'
|
|
123
|
+
---------------
|
|
124
|
+
Example for 200 response:
|
|
125
|
+
HTTP/1.1 200 OK\r\n
|
|
126
|
+
Cache-Control: max-age=86400\r\n
|
|
127
|
+
Content-Type: application/json; charset=utf-8\r\n
|
|
128
|
+
\r\n
|
|
129
|
+
{"id":1,"name":"something"}
|
|
130
|
+
---------------
|
|
131
|
+
The final response will look like oneline string:
|
|
132
|
+
HTTP/1.1 200 OK\r\nCache-Control: max-age=86400\r\n
|
|
133
|
+
Content-Type: application/json; charset=utf-8\r\n\r\n{"id":1,"name":"something"}
|
|
134
|
+
---------------
|
|
135
|
+
You can create response as:
|
|
136
|
+
|
|
137
|
+
...HTTP/1.1 200 OK
|
|
138
|
+
header1: value
|
|
139
|
+
header2: value
|
|
140
|
+
|
|
141
|
+
{data: value}...
|
|
142
|
+
|
|
143
|
+
Change 3 dots ("...") to 3 double quotes before "HTTP" and after "value}".
|
|
144
|
+
This way there will be "\n" added automatically after each line.
|
|
145
|
+
While, the HTTP Client does the parsing of the text and not raw data, most probably it will be parsed well,
|
|
146
|
+
but genuine responses from HTTP sources come with "\r\n" at the end of the line, so better use these for
|
|
147
|
+
better compatibility.
|
|
148
|
+
---------------
|
|
149
|
+
|
|
150
|
+
:param http_version: HTTP Version of Response in HTTP Status line.
|
|
151
|
+
:param status_code: HTTP Status Code of Response in HTTP Status line.
|
|
152
|
+
:param headers: HTTP Headers of Response.
|
|
153
|
+
:param body: HTTP body data of Response, bytes.
|
|
154
|
+
:return: bytes of the response.
|
|
155
|
+
"""
|
|
155
156
|
|
|
156
157
|
try:
|
|
157
158
|
# Building full status string line and the "\r\n" to the end of the status line
|
|
@@ -201,6 +202,5 @@ class ResponderParent:
|
|
|
201
202
|
def create_response(self, class_client_message: ClientMessage):
|
|
202
203
|
""" This function should be overridden in the child class. """
|
|
203
204
|
|
|
204
|
-
|
|
205
|
-
response_bytes_list: list[bytes] = list()
|
|
205
|
+
response_bytes_list: list[bytes] = [class_client_message.response_raw_bytes]
|
|
206
206
|
return response_bytes_list
|
|
@@ -23,49 +23,49 @@ class ResponderGeneral(ResponderParent):
|
|
|
23
23
|
|
|
24
24
|
self.logger = create_custom_logger()
|
|
25
25
|
|
|
26
|
-
def create_response(self, class_client_message: ClientMessage):
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
26
|
+
# def create_response(self, class_client_message: ClientMessage):
|
|
27
|
+
# # noinspection GrazieInspection
|
|
28
|
+
# """
|
|
29
|
+
# Function to create Response based on ClientMessage and its Request.
|
|
30
|
+
#
|
|
31
|
+
# :param class_client_message: contains request and other parameters to help creating response.
|
|
32
|
+
# :return: list of responses in bytes.
|
|
33
|
+
# -----------------------------------
|
|
34
|
+
#
|
|
35
|
+
# # Example of creating list of bytes using 'build_byte_response' function:
|
|
36
|
+
# result_list: list[bytes] = list()
|
|
37
|
+
# result_list.append(
|
|
38
|
+
# self.build_byte_response(
|
|
39
|
+
# http_version=class_client_message.request_raw_decoded.request_version,
|
|
40
|
+
# status_code=200,
|
|
41
|
+
# headers=response_headers,
|
|
42
|
+
# body=b''
|
|
43
|
+
# )
|
|
44
|
+
# )
|
|
45
|
+
#
|
|
46
|
+
# return result_list
|
|
47
|
+
# -----------------------------------
|
|
48
|
+
# # Example of extracting variables from URL PATH based on custom PATH TEMPLATE:
|
|
49
|
+
# # (more examples in 'self.extract_variables_from_path_template' function description)
|
|
50
|
+
# template_path: str = "/hithere/<variable1>/else/<variable2>/tested/"
|
|
51
|
+
# path_variables: dict = extract_variables_from_path_template(
|
|
52
|
+
# path=class_client_message.request_raw_decoded.path,
|
|
53
|
+
# template_path=template_path
|
|
54
|
+
# )
|
|
55
|
+
# -----------------------------------
|
|
56
|
+
# # Example of extracting value from URL PATH parameters after question mark:
|
|
57
|
+
# parameter_value = extract_value_from_path_parameter(
|
|
58
|
+
# path=class_client_message.request_raw_decoded.path,
|
|
59
|
+
# parameter='test_id'
|
|
60
|
+
# )
|
|
61
|
+
# """
|
|
62
|
+
#
|
|
63
|
+
# # byte_response: bytes = b''
|
|
64
|
+
# # self.logger.info(f"Response: {byte_response}")
|
|
65
|
+
#
|
|
66
|
+
# response_bytes_list: list[bytes] = list()
|
|
67
|
+
# # response_bytes_list.append(byte_response)
|
|
68
|
+
# return response_bytes_list
|
|
69
69
|
|
|
70
70
|
# def create_connect_response(self, class_client_message: ClientMessage):
|
|
71
71
|
# """
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
atomicshop/__init__.py,sha256=
|
|
1
|
+
atomicshop/__init__.py,sha256=FYQ8-qAL9PVUMgBs-HklwbCpRvP--eHNx3_VzcTLtVM,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
|
|
@@ -135,7 +135,7 @@ atomicshop/file_io/xmls.py,sha256=zh3SuK-dNaFq2NDNhx6ivcf4GYCfGM8M10PcEwDSpxk,21
|
|
|
135
135
|
atomicshop/mitm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
136
136
|
atomicshop/mitm/config_static.py,sha256=dQH9AJFnwuO8qNVmoN4f3OrllIHlUvC5tkCGAPteK_U,8066
|
|
137
137
|
atomicshop/mitm/config_toml_editor.py,sha256=2p1CMcktWRR_NW-SmyDwylu63ad5e0-w1QPMa8ZLDBw,1635
|
|
138
|
-
atomicshop/mitm/connection_thread_worker.py,sha256=
|
|
138
|
+
atomicshop/mitm/connection_thread_worker.py,sha256=IZtcdW9ZZrtgL-dawt_o56emGCrzWtbd8fUAwgKX9NU,27972
|
|
139
139
|
atomicshop/mitm/import_config.py,sha256=Aj_q3GEovZgN_ig15PWi-LhkuEG0CjDSwakhJg4xp2U,17575
|
|
140
140
|
atomicshop/mitm/initialize_engines.py,sha256=ygxTtfpjlSErF-tKS3rYCyA1X4WT0GyQCZNbtzjPngk,7339
|
|
141
141
|
atomicshop/mitm/message.py,sha256=CDhhm4BTuZE7oNZCjvIZ4BuPOW4MuIzQLOg91hJaxDI,3065
|
|
@@ -149,11 +149,11 @@ atomicshop/mitm/engines/create_module_template_main_example.py,sha256=LeQ44Rp2Gi
|
|
|
149
149
|
atomicshop/mitm/engines/__parent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
150
150
|
atomicshop/mitm/engines/__parent/parser___parent.py,sha256=HHaCXhScl3OlPjz6eUxsDpJaZyk6BNuDMc9xCkeo2Ws,661
|
|
151
151
|
atomicshop/mitm/engines/__parent/recorder___parent.py,sha256=JbbcpV6j4odvREmvcXQlzKr5_hwLiEHhF0O414PlTes,6010
|
|
152
|
-
atomicshop/mitm/engines/__parent/responder___parent.py,sha256=
|
|
152
|
+
atomicshop/mitm/engines/__parent/responder___parent.py,sha256=mtiS_6ej9nxT9UhAQR4ftMqnqL-j_kO3u8KEaoEaI9k,9495
|
|
153
153
|
atomicshop/mitm/engines/__reference_general/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
154
154
|
atomicshop/mitm/engines/__reference_general/parser___reference_general.py,sha256=57MEPZMAjTO6xBDZ-yt6lgGJyqRrP0Do5Gk_cgCiPns,2998
|
|
155
155
|
atomicshop/mitm/engines/__reference_general/recorder___reference_general.py,sha256=El2_YHLoHUCiKfkAmGlXxtFpmSjsUFdsb8I1MvSAFaM,653
|
|
156
|
-
atomicshop/mitm/engines/__reference_general/responder___reference_general.py,sha256=
|
|
156
|
+
atomicshop/mitm/engines/__reference_general/responder___reference_general.py,sha256=zVMmON1sy6HH-A35uZZuAURBMfKS5X9ivkPVjPl-sCw,9654
|
|
157
157
|
atomicshop/mitm/statistic_analyzer_helper/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
158
158
|
atomicshop/mitm/statistic_analyzer_helper/analyzer_helper.py,sha256=pk6L1t1ea1kvlBoR9QEJptOmaX-mumhwLsP2GCKukbk,5920
|
|
159
159
|
atomicshop/mitm/statistic_analyzer_helper/moving_average_helper.py,sha256=UnnY_FSTiXEfZ8SkDKU2s2qpgPYu1oOT99ghmY-zzas,19992
|
|
@@ -330,8 +330,8 @@ atomicshop/wrappers/socketw/statistics_csv.py,sha256=WcNyaqEZ82S5-f3kzqi1nllNT2N
|
|
|
330
330
|
atomicshop/wrappers/winregw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
331
331
|
atomicshop/wrappers/winregw/winreg_installed_software.py,sha256=Qzmyktvob1qp6Tjk2DjLfAqr_yXV0sgWzdMW_9kwNjY,2345
|
|
332
332
|
atomicshop/wrappers/winregw/winreg_network.py,sha256=AENV88H1qDidrcpyM9OwEZxX5svfi-Jb4N6FkS1xtqA,8851
|
|
333
|
-
atomicshop-2.21.
|
|
334
|
-
atomicshop-2.21.
|
|
335
|
-
atomicshop-2.21.
|
|
336
|
-
atomicshop-2.21.
|
|
337
|
-
atomicshop-2.21.
|
|
333
|
+
atomicshop-2.21.1.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
|
|
334
|
+
atomicshop-2.21.1.dist-info/METADATA,sha256=xGsV5SmY4zYzw1ns7OPlC7zX0NkYGx2ZQh0fpVUyHvQ,10630
|
|
335
|
+
atomicshop-2.21.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
336
|
+
atomicshop-2.21.1.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
|
|
337
|
+
atomicshop-2.21.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|