Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vmj-qt
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kulya
vmj-qt
Commits
00c2cd54
Commit
00c2cd54
authored
Sep 21, 2022
by
Tijmen de Mes
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added OTR supoort to message stream
parent
4c4a95e8
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
156 additions
and
0 deletions
+156
-0
messages.py
blink/messages.py
+80
-0
message.py
blink/streams/message.py
+76
-0
No files found.
blink/messages.py
View file @
00c2cd54
...
...
@@ -317,6 +317,12 @@ class BlinkMessage(MSRPChatMessage):
self
.
disposition
=
disposition
self
.
is_secure
=
is_secure
self
.
direction
=
direction
print
(
f
"MSG: {self.timestamp}"
)
class
OTRInternalMessage
(
BlinkMessage
):
def
__init__
(
self
,
content
):
super
(
OTRInternalMessage
,
self
)
.
__init__
(
content
,
'text/plain'
)
@
implementer
(
IObserver
)
...
...
@@ -486,6 +492,76 @@ class OutgoingMessage(object):
notification_center
.
post_notification
(
'BlinkMessageDidFail'
,
sender
=
self
.
session
,
data
=
NotificationData
(
data
=
notification
.
data
,
id
=
self
.
id
))
@
implementer
(
IObserver
)
class
InternalOTROutgoingMessage
(
OutgoingMessage
):
@
property
def
message
(
self
):
return
OTRInternalMessage
(
self
.
content
,
self
.
content_type
)
def
_send
(
self
,
routes
=
None
):
if
routes
is
not
None
or
self
.
session
.
routes
:
notification_center
=
NotificationCenter
()
routes
=
routes
if
routes
is
not
None
else
self
.
session
.
routes
from_uri
=
self
.
account
.
uri
content
=
self
.
content
content
=
content
if
isinstance
(
content
,
bytes
)
else
content
.
encode
()
additional_sip_headers
=
[]
if
self
.
account
.
sms
.
use_cpim
:
ns
=
CPIMNamespace
(
'urn:ietf:params:imdn'
,
'imdn'
)
additional_headers
=
[
CPIMHeader
(
'Message-ID'
,
ns
,
self
.
id
)]
payload
=
CPIMPayload
(
content
,
self
.
content_type
,
charset
=
'utf-8'
,
sender
=
ChatIdentity
(
from_uri
,
self
.
account
.
display_name
),
recipients
=
[
ChatIdentity
(
self
.
sip_uri
,
None
)],
timestamp
=
str
(
self
.
timestamp
),
additional_headers
=
additional_headers
)
payload
,
content_type
=
payload
.
encode
()
else
:
payload
=
content
content_type
=
self
.
content_type
route
=
routes
[
0
]
message_request
=
Message
(
FromHeader
(
from_uri
,
self
.
account
.
display_name
),
ToHeader
(
self
.
sip_uri
),
RouteHeader
(
route
.
uri
),
content_type
,
payload
,
credentials
=
self
.
account
.
credentials
,
extra_headers
=
additional_sip_headers
)
notification_center
.
add_observer
(
self
,
sender
=
message_request
)
message_request
.
send
()
else
:
pass
# TODO
def
send
(
self
):
if
self
.
session
is
None
:
return
if
self
.
session
.
routes
:
self
.
_send
()
else
:
self
.
_lookup
()
def
_NH_DNSLookupDidSucceed
(
self
,
notification
):
notification
.
center
.
remove_observer
(
self
,
sender
=
notification
.
sender
)
if
notification
.
sender
is
self
.
lookup
:
routes
=
notification
.
data
.
result
self
.
session
.
routes
=
routes
self
.
_send
()
def
_NH_DNSLookupDidFail
(
self
,
notification
):
notification
.
center
.
remove_observer
(
self
,
sender
=
notification
.
sender
)
return
def
_NH_SIPMessageDidSucceed
(
self
,
notification
):
return
def
_NH_SIPMessageDidFail
(
self
,
notification
):
return
class
RequestList
(
list
):
def
__getitem__
(
self
,
key
):
if
isinstance
(
key
,
int
):
...
...
@@ -1143,6 +1219,10 @@ class MessageManager(object, metaclass=Singleton):
bisect
.
insort_right
(
self
.
pgp_requests
,
export_request
)
export_request
.
dialog
.
show
()
def
send_otr_message
(
self
,
session
,
data
):
outgoing_message
=
InternalOTROutgoingMessage
(
session
.
account
,
session
.
contact
,
data
,
'text/plain'
,
session
=
session
)
self
.
_send_message
(
outgoing_message
)
def
send_composing_indication
(
self
,
session
,
state
,
refresh
=
None
,
last_active
=
None
):
if
not
session
.
account
.
sms
.
enable_iscomposing
:
return
...
...
blink/streams/message.py
View file @
00c2cd54
...
...
@@ -4,9 +4,12 @@ from application.notification import IObserver, NotificationCenter, Notification
from
application.python
import
Null
from
application.system
import
makedirs
from
otr
import
OTRTransport
from
otr.exceptions
import
IgnoreMessage
,
UnencryptedMessage
,
EncryptedMessageError
,
OTRError
,
OTRFinishedError
from
sipsimple.account
import
AccountManager
from
sipsimple.configuration.settings
import
SIPSimpleSettings
from
sipsimple.streams
import
IMediaStream
,
MediaStreamType
,
UnknownStreamError
from
sipsimple.streams.msrp.chat
import
OTREncryption
from
sipsimple.threading
import
run_in_thread
from
sipsimple.threading.green
import
run_in_green_thread
...
...
@@ -40,6 +43,7 @@ class MessageStream(object, metaclass=MediaStreamType):
self
.
public_key
=
None
self
.
remote_public_key
=
None
self
.
other_private_keys
=
[]
self
.
encryption
=
OTREncryption
(
self
)
notification_center
=
NotificationCenter
()
notification_center
.
add_observer
(
self
,
name
=
'PGPKeysShouldReload'
)
...
...
@@ -75,6 +79,14 @@ class MessageStream(object, metaclass=MediaStreamType):
def
end
(
self
):
pass
@
property
def
local_uri
(
self
):
return
None
@
property
def
msrp
(
self
):
return
None
@
property
def
can_encrypt
(
self
):
return
self
.
private_key
is
not
None
and
self
.
remote_public_key
is
not
None
...
...
@@ -148,11 +160,72 @@ class MessageStream(object, metaclass=MediaStreamType):
notification_center
=
NotificationCenter
()
notification_center
.
post_notification
(
'PGPKeysDidGenerate'
,
sender
=
session
,
data
=
NotificationData
(
private_key
=
private_key
,
public_key
=
private_key
.
pubkey
))
def
inject_otr_message
(
self
,
data
):
from
blink.messages
import
MessageManager
MessageManager
()
.
send_otr_message
(
self
.
blink_session
,
data
)
def
enable_pgp
(
self
):
self
.
_load_pgp_keys
()
def
enable_otr
(
self
):
self
.
encryption
.
start
()
def
disable_otr
(
self
):
self
.
encryption
.
stop
()
def
check_otr
(
self
,
message
):
content
=
None
notification_center
=
NotificationCenter
()
try
:
content
=
self
.
encryption
.
otr_session
.
handle_input
(
message
.
content
.
encode
(),
message
.
content_type
)
except
IgnoreMessage
:
return
None
except
UnencryptedMessage
:
return
message
except
EncryptedMessageError
as
e
:
log
.
warning
(
f
'OTR encrypted message error: {e}'
)
return
None
except
OTRFinishedError
:
log
.
info
(
'OTR has finished'
)
return
None
except
OTRError
as
e
:
log
.
warning
(
f
'OTR message error: {e}'
)
return
None
else
:
content
=
content
.
decode
()
if
isinstance
(
content
,
bytes
)
else
content
if
content
.
startswith
(
'?OTR:'
):
notification_center
.
post_notification
(
'ChatStreamOTRError'
,
sender
=
self
,
data
=
NotificationData
(
error
=
'OTR message could not be decoded'
))
log
.
warning
(
'OTR message could not be decoded'
)
if
self
.
encryption
.
active
:
self
.
encryption
.
stop
()
return
None
log
.
info
(
"Message uses OTR encryption, message is decoded"
)
message
.
is_secure
=
self
.
encryption
.
active
message
.
content
=
content
.
decode
()
if
isinstance
(
content
,
bytes
)
else
content
return
message
def
encrypt
(
self
,
content
,
content_type
=
None
):
# print('-- Encrypting message')
if
self
.
encryption
.
active
:
try
:
encrypted_content
=
self
.
encryption
.
otr_session
.
handle_output
(
content
.
encode
(),
content_type
)
except
OTRError
as
e
:
log
.
info
(
"Encryption failed OTR encryption has been disabled by remote party"
)
self
.
encryption
.
stop
()
raise
Exception
(
f
"OTR encryption has been disabled by remote party {e}"
)
except
OTRFinishedError
:
log
.
info
(
"OTR encryption has been disabled by remote party"
)
self
.
encryption
.
stop
()
raise
Exception
(
"OTR encryption has been disabled by remote party"
)
else
:
if
not
encrypted_content
.
startswith
(
b
'?OTR:'
):
self
.
encryption
.
stop
()
log
.
info
(
"OTR encryption has been stopped"
)
raise
Exception
(
"OTR encryption has been stopped"
)
return
str
(
encrypted_content
.
decode
())
pgp_message
=
PGPMessage
.
new
(
content
,
compression
=
CompressionAlgorithm
.
Uncompressed
)
cipher
=
SymmetricKeyAlgorithm
.
AES256
...
...
@@ -266,3 +339,6 @@ class MessageStream(object, metaclass=MediaStreamType):
if
loaded_key
is
None
:
continue
self
.
other_private_keys
.
append
((
account
,
loaded_key
))
OTRTransport
.
register
(
MessageStream
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment