Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linphone-desktop
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
Administrator
linphone-desktop
Commits
59010084
Commit
59010084
authored
May 30, 2017
by
Sylvain Berfini
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added ZRTP token authentication while in call
parent
a346aedd
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
315 additions
and
3 deletions
+315
-3
call_chat_secure_hovered.svg
linphone-desktop/assets/images/call_chat_secure_hovered.svg
+15
-0
call_chat_secure_normal.svg
linphone-desktop/assets/images/call_chat_secure_normal.svg
+15
-0
call_chat_secure_pressed.svg
linphone-desktop/assets/images/call_chat_secure_pressed.svg
+15
-0
call_chat_unsecure_hovered.svg
...hone-desktop/assets/images/call_chat_unsecure_hovered.svg
+15
-0
call_chat_unsecure_normal.svg
linphone-desktop/assets/images/call_chat_unsecure_normal.svg
+15
-0
call_chat_unsecure_pressed.svg
...hone-desktop/assets/images/call_chat_unsecure_pressed.svg
+15
-0
en.ts
linphone-desktop/assets/languages/en.ts
+20
-0
fr.ts
linphone-desktop/assets/languages/fr.ts
+20
-0
resources.qrc
linphone-desktop/resources.qrc
+6
-0
CallModel.cpp
linphone-desktop/src/components/call/CallModel.cpp
+51
-0
CallModel.hpp
linphone-desktop/src/components/call/CallModel.hpp
+23
-0
Incall.js
linphone-desktop/ui/views/App/Calls/Incall.js
+1
-1
Incall.qml
linphone-desktop/ui/views/App/Calls/Incall.qml
+94
-1
CallStyle.qml
linphone-desktop/ui/views/App/Styles/Calls/CallStyle.qml
+9
-0
linphone
submodules/linphone
+1
-1
No files found.
linphone-desktop/assets/images/call_chat_secure_hovered.svg
0 → 100644
View file @
59010084
<?xml version="1.0" encoding="UTF-8"?>
<svg
width=
"10px"
height=
"14px"
viewBox=
"0 0 10 14"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
>
<!-- Generator: Sketch 42 (36781) - http://www.bohemiancoding.com/sketch -->
<title>
chat_secure@x2
</title>
<desc>
Created with Sketch.
</desc>
<defs></defs>
<g
id=
"Symbols"
stroke=
"none"
stroke-width=
"1"
fill=
"none"
fill-rule=
"evenodd"
>
<g
id=
"chat_secure@x2"
>
<g
id=
"Group-2"
transform=
"translate(0.000000, 1.000000)"
>
<rect
id=
"Rectangle-4"
fill=
"#595759"
x=
"0"
y=
"4.33333322"
width=
"9.99999974"
height=
"8.66666644"
></rect>
<path
d=
"M7.99999979,11.3429854 L7.99999979,3.16521731 C7.99999979,1.41711606 6.65685407,0 4.99999987,0 C3.34314566,0 1.99999995,1.41711606 1.99999995,3.16521731 L1.99999995,11.3429854 L7.99999979,11.3429854 Z"
id=
"Oval-6"
stroke=
"#595759"
stroke-width=
"2"
></path>
</g>
</g>
</g>
</svg>
\ No newline at end of file
linphone-desktop/assets/images/call_chat_secure_normal.svg
0 → 100644
View file @
59010084
<?xml version="1.0" encoding="UTF-8"?>
<svg
width=
"10px"
height=
"14px"
viewBox=
"0 0 10 14"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
>
<!-- Generator: Sketch 42 (36781) - http://www.bohemiancoding.com/sketch -->
<title>
chat_secure@x2
</title>
<desc>
Created with Sketch.
</desc>
<defs></defs>
<g
id=
"Symbols"
stroke=
"none"
stroke-width=
"1"
fill=
"none"
fill-rule=
"evenodd"
>
<g
id=
"chat_secure@x2"
>
<g
id=
"Group-2"
transform=
"translate(0.000000, 1.000000)"
>
<rect
id=
"Rectangle-4"
fill=
"#595759"
x=
"0"
y=
"4.33333322"
width=
"9.99999974"
height=
"8.66666644"
></rect>
<path
d=
"M7.99999979,11.3429854 L7.99999979,3.16521731 C7.99999979,1.41711606 6.65685407,0 4.99999987,0 C3.34314566,0 1.99999995,1.41711606 1.99999995,3.16521731 L1.99999995,11.3429854 L7.99999979,11.3429854 Z"
id=
"Oval-6"
stroke=
"#595759"
stroke-width=
"2"
></path>
</g>
</g>
</g>
</svg>
\ No newline at end of file
linphone-desktop/assets/images/call_chat_secure_pressed.svg
0 → 100644
View file @
59010084
<?xml version="1.0" encoding="UTF-8"?>
<svg
width=
"10px"
height=
"14px"
viewBox=
"0 0 10 14"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
>
<!-- Generator: Sketch 42 (36781) - http://www.bohemiancoding.com/sketch -->
<title>
chat_secure@x2
</title>
<desc>
Created with Sketch.
</desc>
<defs></defs>
<g
id=
"Symbols"
stroke=
"none"
stroke-width=
"1"
fill=
"none"
fill-rule=
"evenodd"
>
<g
id=
"chat_secure@x2"
>
<g
id=
"Group-2"
transform=
"translate(0.000000, 1.000000)"
>
<rect
id=
"Rectangle-4"
fill=
"#595759"
x=
"0"
y=
"4.33333322"
width=
"9.99999974"
height=
"8.66666644"
></rect>
<path
d=
"M7.99999979,11.3429854 L7.99999979,3.16521731 C7.99999979,1.41711606 6.65685407,0 4.99999987,0 C3.34314566,0 1.99999995,1.41711606 1.99999995,3.16521731 L1.99999995,11.3429854 L7.99999979,11.3429854 Z"
id=
"Oval-6"
stroke=
"#595759"
stroke-width=
"2"
></path>
</g>
</g>
</g>
</svg>
\ No newline at end of file
linphone-desktop/assets/images/call_chat_unsecure_hovered.svg
0 → 100644
View file @
59010084
<?xml version="1.0" encoding="UTF-8"?>
<svg
width=
"10px"
height=
"16px"
viewBox=
"0 0 10 16"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
>
<!-- Generator: Sketch 42 (36781) - http://www.bohemiancoding.com/sketch -->
<title>
chat_unsecure@x2
</title>
<desc>
Created with Sketch.
</desc>
<defs></defs>
<g
id=
"Symbols"
stroke=
"none"
stroke-width=
"1"
fill=
"none"
fill-rule=
"evenodd"
>
<g
id=
"chat_unsecure@x2"
>
<g
id=
"Group-2"
transform=
"translate(0.000000, 0.180000)"
>
<rect
id=
"Rectangle-4"
fill=
"#FF0000"
x=
"0"
y=
"7.13541656"
width=
"10"
height=
"8.66666667"
></rect>
<path
d=
"M7.74999979,3.88630432 C7.74999979,2.19283123 6.44882738,0.820000052 4.84374987,0.820000052 C3.23867236,0.820000052 1.93749995,2.19283123 1.93749995,3.88630432 L1.93749995,11.8085172"
id=
"Oval-6"
stroke=
"#FF0000"
stroke-width=
"2"
></path>
</g>
</g>
</g>
</svg>
\ No newline at end of file
linphone-desktop/assets/images/call_chat_unsecure_normal.svg
0 → 100644
View file @
59010084
<?xml version="1.0" encoding="UTF-8"?>
<svg
width=
"10px"
height=
"16px"
viewBox=
"0 0 10 16"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
>
<!-- Generator: Sketch 42 (36781) - http://www.bohemiancoding.com/sketch -->
<title>
chat_unsecure@x2
</title>
<desc>
Created with Sketch.
</desc>
<defs></defs>
<g
id=
"Symbols"
stroke=
"none"
stroke-width=
"1"
fill=
"none"
fill-rule=
"evenodd"
>
<g
id=
"chat_unsecure@x2"
>
<g
id=
"Group-2"
transform=
"translate(0.000000, 0.180000)"
>
<rect
id=
"Rectangle-4"
fill=
"#FF0000"
x=
"0"
y=
"7.13541656"
width=
"10"
height=
"8.66666667"
></rect>
<path
d=
"M7.74999979,3.88630432 C7.74999979,2.19283123 6.44882738,0.820000052 4.84374987,0.820000052 C3.23867236,0.820000052 1.93749995,2.19283123 1.93749995,3.88630432 L1.93749995,11.8085172"
id=
"Oval-6"
stroke=
"#FF0000"
stroke-width=
"2"
></path>
</g>
</g>
</g>
</svg>
\ No newline at end of file
linphone-desktop/assets/images/call_chat_unsecure_pressed.svg
0 → 100644
View file @
59010084
<?xml version="1.0" encoding="UTF-8"?>
<svg
width=
"10px"
height=
"16px"
viewBox=
"0 0 10 16"
version=
"1.1"
xmlns=
"http://www.w3.org/2000/svg"
xmlns:xlink=
"http://www.w3.org/1999/xlink"
>
<!-- Generator: Sketch 42 (36781) - http://www.bohemiancoding.com/sketch -->
<title>
chat_unsecure@x2
</title>
<desc>
Created with Sketch.
</desc>
<defs></defs>
<g
id=
"Symbols"
stroke=
"none"
stroke-width=
"1"
fill=
"none"
fill-rule=
"evenodd"
>
<g
id=
"chat_unsecure@x2"
>
<g
id=
"Group-2"
transform=
"translate(0.000000, 0.180000)"
>
<rect
id=
"Rectangle-4"
fill=
"#FF0000"
x=
"0"
y=
"7.13541656"
width=
"10"
height=
"8.66666667"
></rect>
<path
d=
"M7.74999979,3.88630432 C7.74999979,2.19283123 6.44882738,0.820000052 4.84374987,0.820000052 C3.23867236,0.820000052 1.93749995,2.19283123 1.93749995,3.88630432 L1.93749995,11.8085172"
id=
"Oval-6"
stroke=
"#FF0000"
stroke-width=
"2"
></path>
</g>
</g>
</g>
</svg>
\ No newline at end of file
linphone-desktop/assets/languages/en.ts
View file @
59010084
...
...
@@ -731,6 +731,26 @@ Server url not configured.</translation>
<
source
>
pendingRequestLabel
<
/source
>
<
translation
>
Please
to
wait
,
a
request
is
pending
.
<
/translation
>
<
/message
>
<
message
>
<
source
>
Say
:
<
/source
>
<
translation
>
Say
:
<
/translation
>
<
/message
>
<
message
>
<
source
>
Your
correspondent
should
say
:
<
/source
>
<
translation
>
Your
correspondent
should
say
:
<
/translation
>
<
/message
>
<
message
>
<
source
>
Deny
<
/source
>
<
translation
>
DENY
<
/translation
>
<
/message
>
<
message
>
<
source
>
Accept
<
/source
>
<
translation
>
ACCEPT
<
/translation
>
<
/message
>
<
message
>
<
source
>
Confirm
the
following
SAS
with
peer
:
<
/source
>
<
translation
>
Confirm
the
following
SAS
with
peer
:
<
/translation
>
<
/message
>
<
/context
>
<
context
>
<
name
>
InviteFriends
<
/name
>
...
...
linphone-desktop/assets/languages/fr.ts
View file @
59010084
...
...
@@ -731,6 +731,26 @@ Url du serveur non configurée.</translation>
<
source
>
pendingRequestLabel
<
/source
>
<
translation
>
Merci
de
patienter
,
une
requ
ê
te
est
en
attente
.
<
/translation
>
<
/message
>
<
message
>
<
source
>
Say
:
<
/source
>
<
translation
>
Dites
:
<
/translation
>
<
/message
>
<
message
>
<
source
>
Your
correspondent
should
say
:
<
/source
>
<
translation
>
Votre
interlocuteur
devrait
dire
:
<
/translation
>
<
/message
>
<
message
>
<
source
>
Deny
<
/source
>
<
translation
>
REJETER
<
/translation
>
<
/message
>
<
message
>
<
source
>
Accept
<
/source
>
<
translation
>
VALIDER
<
/translation
>
<
/message
>
<
message
>
<
source
>
Confirm
the
following
SAS
with
peer
:
<
/source
>
<
translation
>
Confirmez
le
SAS
suivant
avec
votre
interlocuteur
:
<
/translation
>
<
/message
>
<
/context
>
<
context
>
<
name
>
InviteFriends
<
/name
>
...
...
linphone-desktop/resources.qrc
View file @
59010084
...
...
@@ -26,6 +26,12 @@
<file>
assets/images/call_accept_hovered.svg
</file>
<file>
assets/images/call_accept_normal.svg
</file>
<file>
assets/images/call_accept_pressed.svg
</file>
<file>
assets/images/call_chat_secure_hovered.svg
</file>
<file>
assets/images/call_chat_secure_normal.svg
</file>
<file>
assets/images/call_chat_secure_pressed.svg
</file>
<file>
assets/images/call_chat_unsecure_hovered.svg
</file>
<file>
assets/images/call_chat_unsecure_normal.svg
</file>
<file>
assets/images/call_chat_unsecure_pressed.svg
</file>
<file>
assets/images/call_hovered.svg
</file>
<file>
assets/images/call_normal.svg
</file>
<file>
assets/images/call_pressed.svg
</file>
...
...
linphone-desktop/src/components/call/CallModel.cpp
View file @
59010084
...
...
@@ -263,6 +263,7 @@ void CallModel::handleCallStateChanged (const shared_ptr<linphone::Call> &call,
break
;
}
emit
securityUpdated
();
emit
statusChanged
(
getStatus
());
}
...
...
@@ -495,6 +496,56 @@ void CallModel::sendDtmf (const QString &dtmf) {
// -----------------------------------------------------------------------------
CallModel
::
CallEncryption
CallModel
::
getEncryption
()
const
{
shared_ptr
<
const
linphone
::
CallParams
>
params
=
mCall
->
getCurrentParams
();
linphone
::
MediaEncryption
encryption
=
params
->
getMediaEncryption
();
switch
(
encryption
)
{
case
linphone
:
:
MediaEncryptionSRTP
:
return
CallEncryptionSRTP
;
case
linphone
:
:
MediaEncryptionZRTP
:
return
CallEncryptionZRTP
;
case
linphone
:
:
MediaEncryptionDTLS
:
return
CallEncryptionDTLS
;
case
linphone
:
:
MediaEncryptionNone
:
default:
return
CallEncryptionNone
;
}
}
bool
CallModel
::
isSecured
()
const
{
shared_ptr
<
const
linphone
::
CallParams
>
params
=
mCall
->
getCurrentParams
();
linphone
::
MediaEncryption
encryption
=
params
->
getMediaEncryption
();
return
(
encryption
==
linphone
::
MediaEncryptionZRTP
&&
mCall
->
getAuthenticationTokenVerified
())
||
encryption
==
linphone
::
MediaEncryptionSRTP
||
encryption
==
linphone
::
MediaEncryptionDTLS
;
}
QString
CallModel
::
getLocalSAS
()
const
{
QString
token
=
mCall
->
getAuthenticationToken
().
c_str
();
linphone
::
CallDir
direction
=
mCall
->
getDir
();
if
(
direction
==
linphone
::
CallDirIncoming
)
{
return
token
.
left
(
2
).
toUpper
();
}
else
{
return
token
.
right
(
2
).
toUpper
();
}
}
QString
CallModel
::
getRemoteSAS
()
const
{
QString
token
=
mCall
->
getAuthenticationToken
().
c_str
();
linphone
::
CallDir
direction
=
mCall
->
getDir
();
if
(
direction
==
linphone
::
CallDirIncoming
)
{
return
token
.
right
(
2
).
toUpper
();
}
else
{
return
token
.
left
(
2
).
toUpper
();
}
}
void
CallModel
::
verifyAuthenticationToken
(
bool
verify
)
{
mCall
->
setAuthenticationTokenVerified
(
verify
);
emit
securityUpdated
();
}
// -----------------------------------------------------------------------------
QVariantList
CallModel
::
getAudioStats
()
const
{
return
mAudioStats
;
}
...
...
linphone-desktop/src/components/call/CallModel.hpp
View file @
59010084
...
...
@@ -55,6 +55,11 @@ class CallModel : public QObject {
Q_PROPERTY
(
QVariantList
audioStats
READ
getAudioStats
NOTIFY
statsUpdated
);
Q_PROPERTY
(
QVariantList
videoStats
READ
getVideoStats
NOTIFY
statsUpdated
);
Q_PROPERTY
(
CallEncryption
encryption
READ
getEncryption
NOTIFY
securityUpdated
);
Q_PROPERTY
(
bool
isSecured
READ
isSecured
NOTIFY
securityUpdated
);
Q_PROPERTY
(
QString
localSAS
READ
getLocalSAS
NOTIFY
securityUpdated
);
Q_PROPERTY
(
QString
remoteSAS
READ
getRemoteSAS
NOTIFY
securityUpdated
);
public:
enum
CallStatus
{
CallStatusConnected
,
...
...
@@ -67,6 +72,15 @@ public:
Q_ENUM
(
CallStatus
);
enum
CallEncryption
{
CallEncryptionNone
,
CallEncryptionSRTP
,
CallEncryptionZRTP
,
CallEncryptionDTLS
};
Q_ENUM
(
CallEncryption
);
CallModel
(
std
::
shared_ptr
<
linphone
::
Call
>
linphoneCall
);
~
CallModel
();
...
...
@@ -100,6 +114,8 @@ public:
Q_INVOKABLE
void
sendDtmf
(
const
QString
&
dtmf
);
Q_INVOKABLE
void
verifyAuthenticationToken
(
bool
verify
);
signals:
void
callErrorChanged
(
const
QString
&
callError
);
void
isInConferenceChanged
(
bool
status
);
...
...
@@ -108,6 +124,7 @@ signals:
void
statsUpdated
();
void
statusChanged
(
CallStatus
status
);
void
videoRequested
();
void
securityUpdated
();
private:
void
handleCallStateChanged
(
const
std
::
shared_ptr
<
linphone
::
Call
>
&
call
,
linphone
::
CallState
state
);
...
...
@@ -145,10 +162,16 @@ private:
bool
getRecording
()
const
;
CallEncryption
getEncryption
()
const
;
bool
isSecured
()
const
;
QString
getLocalSAS
()
const
;
QString
getRemoteSAS
()
const
;
QVariantList
getAudioStats
()
const
;
QVariantList
getVideoStats
()
const
;
void
updateStats
(
const
std
::
shared_ptr
<
const
linphone
::
CallStats
>
&
callStats
,
QVariantList
&
statsList
);
QString
iceStateToString
(
linphone
::
IceState
state
)
const
;
bool
mIsInConference
=
false
;
...
...
linphone-desktop/ui/views/App/Calls/Incall.js
View file @
59010084
...
...
@@ -9,7 +9,7 @@
// =============================================================================
function
computeAvatarSize
(
maxSize
)
{
var
height
=
container
.
height
var
height
=
zrtp
.
visible
?
container
.
height
-
zrtp
.
height
:
container
.
height
var
width
=
container
.
width
var
size
=
height
<
maxSize
&&
height
>
0
?
height
:
maxSize
...
...
linphone-desktop/ui/views/App/Calls/Incall.qml
View file @
59010084
...
...
@@ -102,6 +102,13 @@ Rectangle {
onClicked
:
telKeypad
.
visible
=
!
telKeypad
.
visible
}
ActionButton
{
id
:
callSecure
icon
:
incall
.
call
.
isSecured
?
'
call_chat_secure
'
:
'
call_chat_unsecure
'
onClicked
:
incall
.
call
.
encryption
===
CallModel
.
CallEncryptionZRTP
?
zrtp
.
visible
=
true
:
zrtp
.
visible
=
false
}
}
ContactDescription
{
...
...
@@ -228,7 +235,7 @@ Rectangle {
Camera
{
call
:
incall
.
call
height
:
container
.
height
height
:
zrtp
.
visible
?
container
.
height
-
zrtp
.
height
:
container
.
height
width
:
container
.
width
}
}
...
...
@@ -242,6 +249,92 @@ Rectangle {
}
}
Item
{
id
:
zrtp
height
:
CallStyle
.
zrtpArea
.
height
visible
:
false
Layout.fillWidth
:
true
anchors.top
:
container
.
bottom
Layout.margins
:
CallStyle
.
container
.
margins
GridLayout
{
anchors.centerIn
:
parent
columns
:
1
Text
{
Layout.fillWidth
:
true
anchors.horizontalCenter
:
parent
.
horizontalCenter
horizontalAlignment
:
Text
.
AlignHCenter
verticalAlignment
:
Text
.
AlignVCenter
text
:
qsTr
(
"
Confirm the following SAS with peer:
"
)
elide
:
Text
.
ElideRight
font.pointSize
:
CallStyle
.
zrtpArea
.
fontSize
font.bold
:
true
color
:
Colors
.
j
}
RowLayout
{
anchors.horizontalCenter
:
parent
.
horizontalCenter
spacing
:
CallStyle
.
zrtpArea
.
vu
.
spacing
Layout.fillWidth
:
true
Text
{
text
:
qsTr
(
"
Say:
"
)
font.pointSize
:
CallStyle
.
zrtpArea
.
fontSize
color
:
Colors
.
j
}
Text
{
text
:
incall
.
call
.
localSAS
font.pointSize
:
CallStyle
.
zrtpArea
.
fontSize
font.bold
:
true
color
:
Colors
.
i
}
Text
{
text
:
"
-
"
font.pointSize
:
CallStyle
.
zrtpArea
.
fontSize
color
:
Colors
.
j
}
Text
{
text
:
qsTr
(
"
Your correspondent should say:
"
)
font.pointSize
:
CallStyle
.
zrtpArea
.
fontSize
color
:
Colors
.
j
}
Text
{
text
:
incall
.
call
.
remoteSAS
font.pointSize
:
CallStyle
.
zrtpArea
.
fontSize
font.bold
:
true
color
:
Colors
.
i
}
}
RowLayout
{
anchors.horizontalCenter
:
parent
.
horizontalCenter
spacing
:
CallStyle
.
zrtpArea
.
vu
.
spacing
Layout.fillWidth
:
true
TextButtonA
{
text
:
qsTr
(
'
Deny
'
)
onClicked
:
{
zrtp
.
visible
=
false
incall
.
call
.
verifyAuthenticationToken
(
false
)
}
}
TextButtonB
{
text
:
qsTr
(
'
Accept
'
)
onClicked
:
{
zrtp
.
visible
=
false
incall
.
call
.
verifyAuthenticationToken
(
true
)
}
}
}
}
}
// -------------------------------------------------------------------------
// Action Buttons.
// -------------------------------------------------------------------------
...
...
linphone-desktop/ui/views/App/Styles/Calls/CallStyle.qml
View file @
59010084
...
...
@@ -76,4 +76,13 @@ QtObject {
property
int
relativeY
:
90
}
}
property
QtObject
zrtpArea
:
QtObject
{
property
int
height
:
50
property
int
fontSize
:
12
property
QtObject
vu
:
QtObject
{
property
int
spacing
:
5
}
}
}
linphone
@
19a0bf17
Subproject commit
87ca1adf5ef967bb3876ea0c060cb9135f36718d
Subproject commit
19a0bf173f7060dec5023292239a715ed807e327
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