mirror of
https://github.com/mvt-project/mvt.git
synced 2024-06-26 14:28:54 +00:00
Improves interactionc module
This commit is contained in:
parent
577fcf752d
commit
179b6976fa
|
@ -17,6 +17,200 @@ INTERACTIONC_BACKUP_IDS = [
|
|||
INTERACTIONC_ROOT_PATHS = [
|
||||
"private/var/mobile/Library/CoreDuet/People/interactionC.db",
|
||||
]
|
||||
# Taken from APOLLO
|
||||
# https://github.com/mac4n6/APOLLO/blob/master/modules/interaction_contact_interactions.txt
|
||||
QUERIES = [
|
||||
"""SELECT
|
||||
ZINTERACTIONS.ZSTARTDATE AS "start_date",
|
||||
ZINTERACTIONS.ZENDDATE AS "end_date",
|
||||
ZINTERACTIONS.ZBUNDLEID AS "bundle_id",
|
||||
ZINTERACTIONS.ZACCOUNT AS "account",
|
||||
ZINTERACTIONS.ZTARGETBUNDLEID AS "target_bundle_id",
|
||||
CASE ZINTERACTIONS.ZDIRECTION
|
||||
WHEN '0' THEN 'INCOMING'
|
||||
WHEN '1' THEN 'OUTGOING'
|
||||
END 'DIRECTION' AS "direction",
|
||||
ZCONTACTS.ZDISPLAYNAME AS "sender_display_name",
|
||||
ZCONTACTS.ZIDENTIFIER AS "sender_identifier",
|
||||
ZCONTACTS.ZPERSONID AS "sender_personid",
|
||||
RECEIPIENTCONACT.ZDISPLAYNAME AS "recipient_display_name",
|
||||
RECEIPIENTCONACT.ZIDENTIFIER AS "recipient_identifier",
|
||||
RECEIPIENTCONACT.ZPERSONID AS "recipient_personid",
|
||||
ZINTERACTIONS.ZRECIPIENTCOUNT AS "recipient_count",
|
||||
ZINTERACTIONS.ZDOMAINIDENTIFIER AS "domain_identifier",
|
||||
ZINTERACTIONS.ZISRESPONSE AS "is_response",
|
||||
ZATTACHMENT.ZCONTENTTEXT AS "content",
|
||||
ZATTACHMENT.ZUTI AS "uti",
|
||||
ZATTACHMENT.ZCONTENTURL AS "attachment_content_url",
|
||||
ZATTACHMENT.ZSIZEINBYTES AS "size",
|
||||
ZATTACHMENT.ZPHOTOLOCALIDENTIFIER AS "photo_local_id",
|
||||
HEX(ZATTACHMENT.ZIDENTIFIER) AS "attachment_id",
|
||||
ZATTACHMENT.ZCLOUDIDENTIFIER AS "cloud_id",
|
||||
ZCONTACTS.ZINCOMINGRECIPIENTCOUNT AS "incoming_recipient_count",
|
||||
ZCONTACTS.ZINCOMINGSENDERCOUNT AS "incoming_sender_count",
|
||||
ZCONTACTS.ZOUTGOINGRECIPIENTCOUNT AS "outgoing_recipient_count",
|
||||
ZINTERACTIONS.ZCREATIONDATE AS "interactions_creation_date",
|
||||
ZCONTACTS.ZCREATIONDATE AS "contacts_creation_date",
|
||||
ZCONTACTS.ZFIRSTINCOMINGRECIPIENTDATE AS "first_incoming_recipient_date",
|
||||
ZCONTACTS.ZFIRSTINCOMINGSENDERDATE AS "first_incoming_sender_date",
|
||||
ZCONTACTS.ZFIRSTOUTGOINGRECIPIENTDATE AS "first_outgoing_recipient_date",
|
||||
ZCONTACTS.ZLASTINCOMINGSENDERDATE AS "last_incoming_sender_date",
|
||||
ZCONTACTS.ZLASTINCOMINGRECIPIENTDATE AS "last_incoming_recipient_date",
|
||||
ZCONTACTS.ZLASTOUTGOINGRECIPIENTDATE AS "last_outgoing_recipient_date",
|
||||
ZCONTACTS.ZCUSTOMIDENTIFIER AS "custom_id",
|
||||
ZINTERACTIONS.ZCONTENTURL AS "interaction_content_url",
|
||||
ZINTERACTIONS.ZLOCATIONUUID AS "location_uuid",
|
||||
ZINTERACTIONS.ZGROUPNAME AS "group_name",
|
||||
ZINTERACTIONS.ZDERIVEDINTENTIDENTIFIER AS "derivied_intent_id",
|
||||
ZINTERACTIONS.Z_PK AS "table_id"
|
||||
FROM ZINTERACTIONS
|
||||
LEFT JOIN ZCONTACTS
|
||||
ON ZINTERACTIONS.ZSENDER = ZCONTACTS.Z_PK
|
||||
LEFT JOIN Z_1INTERACTIONS
|
||||
ON ZINTERACTIONS.Z_PK == Z_1INTERACTIONS.Z_3INTERACTIONS
|
||||
LEFT JOIN ZATTACHMENT
|
||||
ON Z_1INTERACTIONS.Z_1ATTACHMENTS == ZATTACHMENT.Z_PK
|
||||
LEFT JOIN Z_2INTERACTIONRECIPIENT
|
||||
ON ZINTERACTIONS.Z_PK == Z_2INTERACTIONRECIPIENT.Z_3INTERACTIONRECIPIENT
|
||||
LEFT JOIN ZCONTACTS RECEIPIENTCONACT
|
||||
ON Z_2INTERACTIONRECIPIENT.Z_2RECIPIENTS == RECEIPIENTCONACT.Z_PK;
|
||||
""",
|
||||
""" SELECT
|
||||
ZINTERACTIONS.ZSTARTDATE AS "start_date",
|
||||
ZINTERACTIONS.ZENDDATE AS "end_date",
|
||||
ZINTERACTIONS.ZBUNDLEID AS "bundle_id",
|
||||
ZINTERACTIONS.ZACCOUNT AS "account",
|
||||
ZINTERACTIONS.ZTARGETBUNDLEID AS "target_bundle_id",
|
||||
CASE ZINTERACTIONS.ZDIRECTION
|
||||
WHEN '0' THEN 'INCOMING'
|
||||
WHEN '1' THEN 'OUTGOING'
|
||||
END 'DIRECTION' AS "direction",
|
||||
ZCONTACTS.ZDISPLAYNAME AS "sender_display_name",
|
||||
ZCONTACTS.ZIDENTIFIER AS "sender_identifier",
|
||||
ZCONTACTS.ZPERSONID AS "sender_personid",
|
||||
RECEIPIENTCONACT.ZDISPLAYNAME AS "recipient_display_name",
|
||||
RECEIPIENTCONACT.ZIDENTIFIER AS "recipient_identifier",
|
||||
RECEIPIENTCONACT.ZPERSONID AS "recipient_personid",
|
||||
ZINTERACTIONS.ZRECIPIENTCOUNT AS "recipient_count",
|
||||
ZINTERACTIONS.ZDOMAINIDENTIFIER AS "domain_identifier",
|
||||
ZINTERACTIONS.ZISRESPONSE AS "is_response",
|
||||
ZATTACHMENT.ZCONTENTTEXT AS "content",
|
||||
ZATTACHMENT.ZUTI AS "uti",
|
||||
ZATTACHMENT.ZCONTENTURL AS "attachment_content_url",
|
||||
ZATTACHMENT.ZSIZEINBYTES AS "size",
|
||||
HEX(ZATTACHMENT.ZIDENTIFIER) AS "attachment_id",
|
||||
ZATTACHMENT.ZCLOUDIDENTIFIER AS "cloud_id",
|
||||
ZCONTACTS.ZINCOMINGRECIPIENTCOUNT AS "incoming_recipient_count",
|
||||
ZCONTACTS.ZINCOMINGSENDERCOUNT AS "incoming_sender_count",
|
||||
ZCONTACTS.ZOUTGOINGRECIPIENTCOUNT AS "outgoing_recipient_count",
|
||||
ZINTERACTIONS.ZCREATIONDATE AS "interactions_creation_date",
|
||||
ZCONTACTS.ZCREATIONDATE AS "contacts_creation_date",
|
||||
ZCONTACTS.ZFIRSTINCOMINGRECIPIENTDATE AS "first_incoming_recipient_date",
|
||||
ZCONTACTS.ZFIRSTINCOMINGSENDERDATE AS "first_incoming_sender_date",
|
||||
ZCONTACTS.ZFIRSTOUTGOINGRECIPIENTDATE AS "first_outgoing_recipient_date",
|
||||
ZCONTACTS.ZLASTINCOMINGSENDERDATE AS "last_incoming_sender_date",
|
||||
CASE ZCONTACTS.ZLASTINCOMINGRECIPIENTDATE
|
||||
WHEN '0' THEN '0'
|
||||
ELSE ZCONTACTS.ZLASTINCOMINGRECIPIENTDATE
|
||||
END 'LAST INCOMING RECIPIENT DATE' AS "last_incoming_recipient_date",
|
||||
ZCONTACTS.ZLASTOUTGOINGRECIPIENTDATE AS "last_outgoing_recipient_date",
|
||||
ZCONTACTS.ZCUSTOMIDENTIFIER AS "custom_id",
|
||||
ZINTERACTIONS.ZCONTENTURL AS "interaction_content_url",
|
||||
ZINTERACTIONS.ZLOCATIONUUID AS "location_uuid",
|
||||
ZINTERACTIONS.Z_PK AS "table_id"
|
||||
FROM
|
||||
ZINTERACTIONS
|
||||
LEFT JOIN
|
||||
ZCONTACTS
|
||||
ON ZINTERACTIONS.ZSENDER = ZCONTACTS.Z_PK
|
||||
LEFT JOIN Z_1INTERACTIONS ON ZINTERACTIONS.Z_PK == Z_1INTERACTIONS.Z_3INTERACTIONS
|
||||
LEFT JOIN ZATTACHMENT ON Z_1INTERACTIONS.Z_1ATTACHMENTS == ZATTACHMENT.Z_PK
|
||||
LEFT JOIN Z_2INTERACTIONRECIPIENT ON ZINTERACTIONS.Z_PK== Z_2INTERACTIONRECIPIENT.Z_3INTERACTIONRECIPIENT
|
||||
LEFT JOIN ZCONTACTS RECEIPIENTCONACT ON Z_2INTERACTIONRECIPIENT.Z_2RECIPIENTS== RECEIPIENTCONACT.Z_PK
|
||||
""",
|
||||
""" SELECT
|
||||
ZINTERACTIONS.ZSTARTDATE AS "start_date",
|
||||
ZINTERACTIONS.ZENDDATE AS "end_date",
|
||||
ZINTERACTIONS.ZBUNDLEID AS "bundle_id",
|
||||
ZCONTACTS.ZDISPLAYNAME AS "sender_display_name",
|
||||
ZCONTACTS.ZIDENTIFIER AS "sender_identifier",
|
||||
ZCONTACTS.ZPERSONID AS "sender_personid",
|
||||
ZINTERACTIONS.ZDIRECTION AS "direction",
|
||||
ZINTERACTIONS.ZISRESPONSE AS "is_response",
|
||||
ZINTERACTIONS.ZMECHANISM AS "mechanism",
|
||||
ZINTERACTIONS.ZRECIPIENTCOUNT AS "recipient_count",
|
||||
ZINTERACTIONS.ZCREATIONDATE AS "interactions_creation_date",
|
||||
ZCONTACTS.ZCREATIONDATE AS "contacts_creation_date",
|
||||
ZCONTACTS.ZFIRSTINCOMINGRECIPIENTDATE AS "first_incoming_recipient_date",
|
||||
ZCONTACTS.ZFIRSTINCOMINGSENDERDATE AS "first_incoming_sender_date",
|
||||
ZCONTACTS.ZFIRSTOUTGOINGRECIPIENTDATE AS "first_outgoing_recipient_date",
|
||||
ZCONTACTS.ZLASTINCOMINGSENDERDATE AS "last_incoming_sender_date",
|
||||
CASE
|
||||
ZLASTINCOMINGRECIPIENTDATE
|
||||
WHEN
|
||||
'0'
|
||||
THEN
|
||||
'0'
|
||||
ELSE
|
||||
ZCONTACTS.ZLASTINCOMINGRECIPIENTDATE
|
||||
END AS "last_incoming_recipient_date",
|
||||
ZCONTACTS.ZLASTOUTGOINGRECIPIENTDATE AS "last_outgoing_recipient_date",
|
||||
ZINTERACTIONS.ZACCOUNT AS 'account',
|
||||
ZINTERACTIONS.ZDOMAINIDENTIFIER AS "domain_identifier",
|
||||
ZCONTACTS.ZINCOMINGRECIPIENTCOUNT AS "incoming_recipient_count",
|
||||
ZCONTACTS.ZINCOMINGSENDERCOUNT AS "incoming_sender_count",
|
||||
ZCONTACTS.ZOUTGOINGRECIPIENTCOUNT AS "outgoing_recipient_count",
|
||||
ZCONTACTS.ZCUSTOMIDENTIFIER AS "custom_id",
|
||||
ZINTERACTIONS.ZCONTENTURL AS "interaction_content_url",
|
||||
ZINTERACTIONS.ZLOCATIONUUID AS "location_uuid",
|
||||
ZINTERACTIONS.Z_PK AS "table_id"
|
||||
FROM
|
||||
ZINTERACTIONS
|
||||
LEFT JOIN
|
||||
ZCONTACTS
|
||||
ON ZINTERACTIONS.ZSENDER = ZCONTACTS.Z_PK
|
||||
""",
|
||||
""" SELECT
|
||||
ZINTERACTIONS.ZSTARTDATE AS "start_date",
|
||||
ZINTERACTIONS.ZENDDATE AS "end_date",
|
||||
ZINTERACTIONS.ZCREATIONDATE AS "interactions_creation_date",
|
||||
ZINTERACTIONS.ZBUNDLEID AS "bundle_id",
|
||||
ZCONTACTS.ZDISPLAYNAME AS "sender_display_name",
|
||||
ZCONTACTS.ZIDENTIFIER AS "sender_identifier",
|
||||
ZCONTACTS.ZPERSONID AS "sender_personid",
|
||||
ZINTERACTIONS.ZDIRECTION AS "direction",
|
||||
ZINTERACTIONS.ZISRESPONSE AS "is_response",
|
||||
ZINTERACTIONS.ZMECHANISM AS "mechanism",
|
||||
ZCONTACTS.ZCREATIONDATE AS "contacts_creation_date",
|
||||
ZCONTACTS.ZFIRSTINCOMINGRECIPIENTDATE AS "first_incoming_recipient_date",
|
||||
ZCONTACTS.ZFIRSTINCOMINGSENDERDATE AS "first_incoming_sender_date",
|
||||
ZCONTACTS.ZFIRSTOUTGOINGRECIPIENTDATE AS "first_outgoing_recipient_date",
|
||||
ZCONTACTS.ZLASTINCOMINGSENDERDATE AS "last_incoming_sender_date",
|
||||
CASE
|
||||
ZLASTINCOMINGRECIPIENTDATE
|
||||
WHEN
|
||||
'0'
|
||||
THEN
|
||||
'0'
|
||||
ELSE
|
||||
ZCONTACTS.ZLASTINCOMINGRECIPIENTDATE
|
||||
END AS "last_incoming_recipient_date",
|
||||
ZCONTACTS.ZLASTOUTGOINGRECIPIENTDATE AS "last_outgoing_recipient_date",
|
||||
ZINTERACTIONS.ZACCOUNT AS "account",
|
||||
ZINTERACTIONS.ZDOMAINIDENTIFIER AS "domain_identifier",
|
||||
ZCONTACTS.ZINCOMINGRECIPIENTCOUNT AS "incoming_recipient_count",
|
||||
ZCONTACTS.ZINCOMINGSENDERCOUNT AS "incoming_sender_count",
|
||||
ZCONTACTS.ZOUTGOINGRECIPIENTCOUNT AS "outgoing_recipient_count",
|
||||
ZINTERACTIONS.ZCONTENTURL AS "interaction_content_url",
|
||||
ZINTERACTIONS.ZLOCATIONUUID AS "location_uuid",
|
||||
ZINTERACTIONS.Z_PK AS "table_id"
|
||||
FROM
|
||||
ZINTERACTIONS
|
||||
LEFT JOIN
|
||||
ZCONTACTS
|
||||
ON ZINTERACTIONS.ZSENDER = ZCONTACTS.Z_PK
|
||||
"""
|
||||
]
|
||||
|
||||
|
||||
class InteractionC(IOSExtraction):
|
||||
|
@ -66,8 +260,8 @@ class InteractionC(IOSExtraction):
|
|||
"event": timestamp,
|
||||
"data": f"[{record['bundle_id']}] {record['account']} - "
|
||||
f"from {record['sender_display_name']} ({record['sender_identifier']}) "
|
||||
f"to {record['recipient_display_name']} ({record['recipient_identifier']}):"
|
||||
f" {record['content']}"
|
||||
f"to {record.get('recipient_display_name', '')} ({record.get('recipient_identifier', '')}):"
|
||||
f" {record.get('content', '')}"
|
||||
})
|
||||
processed.append(record[timestamp])
|
||||
|
||||
|
@ -81,108 +275,30 @@ class InteractionC(IOSExtraction):
|
|||
conn = sqlite3.connect(self.file_path)
|
||||
cur = conn.cursor()
|
||||
|
||||
# TODO: Support all versions.
|
||||
# Taken from:
|
||||
# https://github.com/mac4n6/APOLLO/blob/master/modules/interaction_contact_interactions.txt
|
||||
cur.execute("""
|
||||
SELECT
|
||||
ZINTERACTIONS.ZSTARTDATE,
|
||||
ZINTERACTIONS.ZENDDATE,
|
||||
ZINTERACTIONS.ZBUNDLEID,
|
||||
ZINTERACTIONS.ZACCOUNT,
|
||||
ZINTERACTIONS.ZTARGETBUNDLEID,
|
||||
CASE ZINTERACTIONS.ZDIRECTION
|
||||
WHEN '0' THEN 'INCOMING'
|
||||
WHEN '1' THEN 'OUTGOING'
|
||||
END 'DIRECTION',
|
||||
ZCONTACTS.ZDISPLAYNAME,
|
||||
ZCONTACTS.ZIDENTIFIER,
|
||||
ZCONTACTS.ZPERSONID,
|
||||
RECEIPIENTCONACT.ZDISPLAYNAME,
|
||||
RECEIPIENTCONACT.ZIDENTIFIER,
|
||||
RECEIPIENTCONACT.ZPERSONID,
|
||||
ZINTERACTIONS.ZRECIPIENTCOUNT,
|
||||
ZINTERACTIONS.ZDOMAINIDENTIFIER,
|
||||
ZINTERACTIONS.ZISRESPONSE,
|
||||
ZATTACHMENT.ZCONTENTTEXT,
|
||||
ZATTACHMENT.ZUTI,
|
||||
ZATTACHMENT.ZCONTENTURL,
|
||||
ZATTACHMENT.ZSIZEINBYTES,
|
||||
ZATTACHMENT.ZPHOTOLOCALIDENTIFIER,
|
||||
HEX(ZATTACHMENT.ZIDENTIFIER),
|
||||
ZATTACHMENT.ZCLOUDIDENTIFIER,
|
||||
ZCONTACTS.ZINCOMINGRECIPIENTCOUNT,
|
||||
ZCONTACTS.ZINCOMINGSENDERCOUNT,
|
||||
ZCONTACTS.ZOUTGOINGRECIPIENTCOUNT,
|
||||
ZINTERACTIONS.ZCREATIONDATE,
|
||||
ZCONTACTS.ZCREATIONDATE,
|
||||
ZCONTACTS.ZFIRSTINCOMINGRECIPIENTDATE,
|
||||
ZCONTACTS.ZFIRSTINCOMINGSENDERDATE,
|
||||
ZCONTACTS.ZFIRSTOUTGOINGRECIPIENTDATE,
|
||||
ZCONTACTS.ZLASTINCOMINGSENDERDATE,
|
||||
ZCONTACTS.ZLASTINCOMINGRECIPIENTDATE,
|
||||
ZCONTACTS.ZLASTOUTGOINGRECIPIENTDATE,
|
||||
ZCONTACTS.ZCUSTOMIDENTIFIER,
|
||||
ZINTERACTIONS.ZCONTENTURL,
|
||||
ZINTERACTIONS.ZLOCATIONUUID,
|
||||
ZINTERACTIONS.ZGROUPNAME,
|
||||
ZINTERACTIONS.ZDERIVEDINTENTIDENTIFIER,
|
||||
ZINTERACTIONS.Z_PK
|
||||
FROM ZINTERACTIONS
|
||||
LEFT JOIN ZCONTACTS
|
||||
ON ZINTERACTIONS.ZSENDER = ZCONTACTS.Z_PK
|
||||
LEFT JOIN Z_1INTERACTIONS
|
||||
ON ZINTERACTIONS.Z_PK == Z_1INTERACTIONS.Z_3INTERACTIONS
|
||||
LEFT JOIN ZATTACHMENT
|
||||
ON Z_1INTERACTIONS.Z_1ATTACHMENTS == ZATTACHMENT.Z_PK
|
||||
LEFT JOIN Z_2INTERACTIONRECIPIENT
|
||||
ON ZINTERACTIONS.Z_PK == Z_2INTERACTIONRECIPIENT.Z_3INTERACTIONRECIPIENT
|
||||
LEFT JOIN ZCONTACTS RECEIPIENTCONACT
|
||||
ON Z_2INTERACTIONRECIPIENT.Z_2RECIPIENTS == RECEIPIENTCONACT.Z_PK;
|
||||
""")
|
||||
# names = [description[0] for description in cur.description]
|
||||
try:
|
||||
cur.execute(QUERIES[0])
|
||||
except sqlite3.OperationalError:
|
||||
try:
|
||||
cur.execute(QUERIES[1])
|
||||
except sqlite3.OperationalError:
|
||||
try:
|
||||
cur.execute(QUERIES[2])
|
||||
except sqlite3.OperationalError:
|
||||
cur.execute(QUERIES[3])
|
||||
|
||||
for row in cur:
|
||||
self.results.append({
|
||||
"start_date": convert_mactime_to_iso(row[0]),
|
||||
"end_date": convert_mactime_to_iso(row[1]),
|
||||
"bundle_id": row[2],
|
||||
"account": row[3],
|
||||
"target_bundle_id": row[4],
|
||||
"direction": row[5],
|
||||
"sender_display_name": row[6],
|
||||
"sender_identifier": row[7],
|
||||
"sender_personid": row[8],
|
||||
"recipient_display_name": row[9],
|
||||
"recipient_identifier": row[10],
|
||||
"recipient_personid": row[11],
|
||||
"recipient_count": row[12],
|
||||
"domain_identifier": row[13],
|
||||
"is_response": row[14],
|
||||
"content": row[15],
|
||||
"uti": row[16],
|
||||
"content_url": row[17],
|
||||
"size": row[18],
|
||||
"photo_local_id": row[19],
|
||||
"attachment_id": row[20],
|
||||
"cloud_id": row[21],
|
||||
"incoming_recipient_count": row[22],
|
||||
"incoming_sender_count": row[23],
|
||||
"outgoing_recipient_count": row[24],
|
||||
"interactions_creation_date": convert_mactime_to_iso(row[25]) if row[25] else None,
|
||||
"contacts_creation_date": convert_mactime_to_iso(row[26]) if row[26] else None,
|
||||
"first_incoming_recipient_date": convert_mactime_to_iso(row[27]) if row[27] else None,
|
||||
"first_incoming_sender_date": convert_mactime_to_iso(row[28]) if row[28] else None,
|
||||
"first_outgoing_recipient_date": convert_mactime_to_iso(row[29]) if row[29] else None,
|
||||
"last_incoming_sender_date": convert_mactime_to_iso(row[30]) if row[30] else None,
|
||||
"last_incoming_recipient_date": convert_mactime_to_iso(row[31]) if row[31] else None,
|
||||
"last_outgoing_recipient_date": convert_mactime_to_iso(row[32]) if row[32] else None,
|
||||
"custom_id": row[33],
|
||||
"location_uuid": row[35],
|
||||
"group_name": row[36],
|
||||
"derivied_intent_id": row[37],
|
||||
"table_id": row[38]
|
||||
})
|
||||
names = [description[0] for description in cur.description]
|
||||
for item in cur:
|
||||
entry = {}
|
||||
for index, value in enumerate(item):
|
||||
if names[index] in self.timestamps:
|
||||
if value is None or isinstance(value, str):
|
||||
entry[names[index]] = value
|
||||
else:
|
||||
entry[names[index]] = convert_mactime_to_iso(value)
|
||||
else:
|
||||
entry[names[index]] = value
|
||||
|
||||
self.results.append(entry)
|
||||
|
||||
cur.close()
|
||||
conn.close()
|
||||
|
|
Loading…
Reference in New Issue
Block a user