new zrtp api

This commit is contained in:
Gaelle Braud 2024-06-26 17:03:21 +02:00
parent 6933989753
commit 99061afc92
12 changed files with 469 additions and 197 deletions

View file

@ -65,13 +65,10 @@ CallCore::CallCore(const std::shared_ptr<linphone::Call> &call) : QObject(nullpt
mLocalAddress = Utils::coreStringToAppString(call->getCallLog()->getLocalAddress()->asStringUriOnly());
mStatus = LinphoneEnums::fromLinphone(call->getCallLog()->getStatus());
mTransferState = LinphoneEnums::fromLinphone(call->getTransferState());
auto token = Utils::coreStringToAppString(mCallModel->getAuthenticationToken());
auto localToken = mDir == LinphoneEnums::CallDir::Incoming ? token.left(2).toUpper() : token.right(2).toUpper();
auto remoteToken = mDir == LinphoneEnums::CallDir::Outgoing ? token.left(2).toUpper() : token.right(2).toUpper();
mLocalToken = Utils::coreStringToAppString(mCallModel->getLocalAtuhenticationToken());
mRemoteTokens = mCallModel->getRemoteAtuhenticationTokens();
mEncryption = LinphoneEnums::fromLinphone(call->getParams()->getMediaEncryption());
auto tokenVerified = call->getAuthenticationTokenVerified();
mLocalSas = localToken;
mRemoteSas = remoteToken;
mIsSecured = (mEncryption == LinphoneEnums::MediaEncryption::Zrtp && tokenVerified) ||
mEncryption == LinphoneEnums::MediaEncryption::Srtp ||
mEncryption == LinphoneEnums::MediaEncryption::Dtls;
@ -150,13 +147,21 @@ void CallCore::setSelf(QSharedPointer<CallCore> me) {
}
});
});
mCallModelConnection->makeConnectToCore(&CallCore::lVerifyAuthenticationToken, [this](bool verified) {
mCallModelConnection->invokeToModel(
[this, verified]() { mCallModel->setAuthenticationTokenVerified(verified); });
mCallModelConnection->makeConnectToCore(&CallCore::lCheckAuthenticationTokenSelected, [this](const QString &token) {
mCallModelConnection->invokeToModel([this, token]() { mCallModel->checkAuthenticationToken(token); });
});
mCallModelConnection->makeConnectToModel(&CallModel::authenticationTokenVerifiedChanged, [this](bool verified) {
mCallModelConnection->invokeToCore([this, verified]() { setIsSecured(verified); });
mCallModelConnection->makeConnectToCore(&CallCore::lSkipZrtpAuthentication, [this]() {
mCallModelConnection->invokeToModel([this]() { mCallModel->skipZrtpAuthentication(); });
});
mCallModelConnection->makeConnectToModel(&CallModel::authenticationTokenVerified,
[this](const std::shared_ptr<linphone::Call> &call, bool verified) {
auto isMismatch = mCallModel->getZrtpCaseMismatch();
mCallModelConnection->invokeToCore([this, verified, isMismatch]() {
setTokenVerified(verified);
setIsSecured(verified && !isMismatch);
emit tokenVerified();
});
});
mCallModelConnection->makeConnectToModel(
&CallModel::remoteRecording, [this](const std::shared_ptr<linphone::Call> &call, bool recording) {
mCallModelConnection->invokeToCore([this, recording]() { setRemoteRecording(recording); });
@ -232,23 +237,22 @@ void CallCore::setSelf(QSharedPointer<CallCore> me) {
[this](const std::shared_ptr<linphone::Call> &call, bool on, const std::string &authenticationToken) {
auto encryption = LinphoneEnums::fromLinphone(call->getCurrentParams()->getMediaEncryption());
auto tokenVerified = mCallModel->getAuthenticationTokenVerified();
auto token = Utils::coreStringToAppString(mCallModel->getAuthenticationToken());
mCallModelConnection->invokeToCore([this, call, encryption, tokenVerified, token]() {
if (token.size() == 4) {
auto localToken =
mDir == LinphoneEnums::CallDir::Incoming ? token.left(2).toUpper() : token.right(2).toUpper();
auto remoteToken =
mDir == LinphoneEnums::CallDir::Outgoing ? token.left(2).toUpper() : token.right(2).toUpper();
setLocalSas(localToken);
setRemoteSas(remoteToken);
}
setEncryption(encryption);
setIsSecured((encryption == LinphoneEnums::MediaEncryption::Zrtp &&
tokenVerified)); // ||
// encryption == LinphoneEnums::MediaEncryption::Srtp ||
// encryption == LinphoneEnums::MediaEncryption::Dtls);
// TODO : change this when api available in sdk
});
auto isCaseMismatch = mCallModel->getZrtpCaseMismatch();
auto localToken = Utils::coreStringToAppString(mCallModel->getLocalAtuhenticationToken());
QStringList remoteTokens = mCallModel->getRemoteAtuhenticationTokens();
mCallModelConnection->invokeToCore(
[this, call, encryption, tokenVerified, localToken, remoteTokens, isCaseMismatch]() {
setLocalToken(localToken);
setRemoteTokens(remoteTokens);
setEncryption(encryption);
setIsMismatch(isCaseMismatch);
setIsSecured(
(encryption == LinphoneEnums::MediaEncryption::Zrtp && tokenVerified && !isCaseMismatch)); // ||
// encryption == LinphoneEnums::MediaEncryption::Srtp ||
// encryption == LinphoneEnums::MediaEncryption::Dtls);
// TODO : change this when api available in sdk
setTokenVerified(tokenVerified);
});
});
mCallModelConnection->makeConnectToCore(&CallCore::lSetSpeakerVolumeGain, [this](float gain) {
mCallModelConnection->invokeToModel([this, gain]() { mCallModel->setSpeakerVolumeGain(gain); });
@ -430,6 +434,17 @@ void CallCore::setPaused(bool paused) {
}
}
bool CallCore::getTokenVerified() const {
return mTokenVerified;
}
void CallCore::setTokenVerified(bool verified) {
if (mTokenVerified != verified) {
mTokenVerified = verified;
emit securityUpdated();
}
}
bool CallCore::isSecured() const {
return mIsSecured;
}
@ -441,6 +456,17 @@ void CallCore::setIsSecured(bool secured) {
}
}
bool CallCore::isMismatch() const {
return mIsMismatch;
}
void CallCore::setIsMismatch(bool mismatch) {
if (mIsMismatch != mismatch) {
mIsMismatch = mismatch;
emit securityUpdated();
}
}
ConferenceGui *CallCore::getConferenceGui() const {
return mConference ? new ConferenceGui(mConference) : nullptr;
}
@ -463,25 +489,25 @@ bool CallCore::isConference() const {
return mIsConference;
}
QString CallCore::getLocalSas() {
return mLocalSas;
QString CallCore::getLocalToken() {
return mLocalToken;
}
QString CallCore::getRemoteSas() {
return mRemoteSas;
QStringList CallCore::getRemoteTokens() {
return mRemoteTokens;
}
void CallCore::setLocalSas(const QString &sas) {
if (mLocalSas != sas) {
mLocalSas = sas;
emit localSasChanged();
void CallCore::setLocalToken(const QString &Token) {
if (mLocalToken != Token) {
mLocalToken = Token;
emit localTokenChanged();
}
}
void CallCore::setRemoteSas(const QString &sas) {
if (mRemoteSas != sas) {
mRemoteSas = sas;
emit remoteSasChanged();
void CallCore::setRemoteTokens(const QStringList &token) {
if (mRemoteTokens != token) {
mRemoteTokens = token;
emit remoteTokensChanged();
}
}

View file

@ -45,10 +45,12 @@ class CallCore : public QObject, public AbstractObject {
Q_PROPERTY(bool paused READ getPaused WRITE lSetPaused NOTIFY pausedChanged)
Q_PROPERTY(QString peerAddress READ getPeerAddress CONSTANT)
Q_PROPERTY(QString localAddress READ getLocalAddress CONSTANT)
Q_PROPERTY(bool isSecured READ isSecured NOTIFY securityUpdated)
Q_PROPERTY(bool tokenVerified READ getTokenVerified WRITE setTokenVerified NOTIFY securityUpdated)
// Q_PROPERTY(bool isSecured READ isSecured WRITE setIsSecured NOTIFY securityUpdated)
Q_PROPERTY(bool isMismatch READ isMismatch WRITE setIsMismatch NOTIFY securityUpdated)
Q_PROPERTY(LinphoneEnums::MediaEncryption encryption READ getEncryption NOTIFY securityUpdated)
Q_PROPERTY(QString localSas READ getLocalSas WRITE setLocalSas MEMBER mLocalSas NOTIFY localSasChanged)
Q_PROPERTY(QString remoteSas WRITE setRemoteSas MEMBER mRemoteSas NOTIFY remoteSasChanged)
Q_PROPERTY(QString localToken READ getLocalToken WRITE setLocalToken MEMBER mLocalToken NOTIFY localTokenChanged)
Q_PROPERTY(QStringList remoteTokens WRITE setRemoteTokens MEMBER mRemoteTokens NOTIFY remoteTokensChanged)
Q_PROPERTY(
bool remoteVideoEnabled READ getRemoteVideoEnabled WRITE setRemoteVideoEnabled NOTIFY remoteVideoEnabledChanged)
Q_PROPERTY(
@ -104,19 +106,25 @@ public:
bool getPaused() const;
void setPaused(bool paused);
bool getTokenVerified() const;
void setTokenVerified(bool verified);
bool isSecured() const;
void setIsSecured(bool secured);
bool isMismatch() const;
void setIsMismatch(bool mismatch);
ConferenceGui *getConferenceGui() const;
QSharedPointer<ConferenceCore> getConferenceCore() const;
void setConference(const QSharedPointer<ConferenceCore> &conference);
bool isConference() const;
QString getLocalSas();
void setLocalSas(const QString &sas);
QString getRemoteSas();
void setRemoteSas(const QString &sas);
QString getLocalToken();
void setLocalToken(const QString &token);
QStringList getRemoteTokens();
void setRemoteTokens(const QStringList &Tokens);
LinphoneEnums::MediaEncryption getEncryption() const;
void setEncryption(LinphoneEnums::MediaEncryption encryption);
@ -169,8 +177,9 @@ signals:
void pausedChanged();
void transferStateChanged();
void securityUpdated();
void localSasChanged();
void remoteSasChanged();
void tokenVerified();
void localTokenChanged();
void remoteTokensChanged();
void remoteVideoEnabledChanged(bool remoteVideoEnabled);
void localVideoEnabledChanged();
void recordingChanged();
@ -196,7 +205,8 @@ signals:
void lTransferCall(QString &est);
void lStartRecording();
void lStopRecording();
void lVerifyAuthenticationToken(bool verified);
void lCheckAuthenticationTokenSelected(const QString &token);
void lSkipZrtpAuthentication();
void lSetSpeakerVolumeGain(float gain);
void lSetMicrophoneVolumeGain(float gain);
void lSetInputAudioDevice(QString id);
@ -236,10 +246,12 @@ private:
QString mLastErrorMessage;
QString mPeerAddress;
QString mLocalAddress;
bool mIsSecured;
bool mTokenVerified = false;
bool mIsSecured = false;
bool mIsMismatch = false;
int mDuration = 0;
bool mSpeakerMuted;
bool mMicrophoneMuted;
bool mSpeakerMuted = false;
bool mMicrophoneMuted = false;
bool mLocalVideoEnabled = false;
bool mVideoEnabled = false;
bool mPaused = false;
@ -248,8 +260,8 @@ private:
bool mRemoteRecording = false;
bool mRecordable = false;
bool mIsConference = false;
QString mLocalSas;
QString mRemoteSas;
QString mLocalToken;
QStringList mRemoteTokens;
float mSpeakerVolumeGain;
float mMicrophoneVolume;
float mMicrophoneVolumeGain;

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M128,112a28,28,0,0,0-8,54.83V184a8,8,0,0,0,16,0V166.83A28,28,0,0,0,128,112Zm0,40a12,12,0,1,1,12-12A12,12,0,0,1,128,152Zm80-72H176V56a48,48,0,0,0-96,0V80H48A16,16,0,0,0,32,96V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V96A16,16,0,0,0,208,80ZM96,56a32,32,0,0,1,64,0V80H96ZM208,208H48V96H208V208Z"></path></svg>

After

Width:  |  Height:  |  Size: 417 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M208,80H96V56a32,32,0,0,1,32-32c15.37,0,29.2,11,32.16,25.59a8,8,0,0,0,15.68-3.18C171.32,24.15,151.2,8,128,8A48.05,48.05,0,0,0,80,56V80H48A16,16,0,0,0,32,96V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V96A16,16,0,0,0,208,80Zm0,128H48V96H208V208Z"></path></svg>

After

Width:  |  Height:  |  Size: 367 B

View file

@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.25 12.75V9C11.25 8.80109 11.329 8.61032 11.4697 8.46967C11.6103 8.32902 11.8011 8.25 12 8.25C12.1989 8.25 12.3897 8.32902 12.5303 8.46967C12.671 8.61032 12.75 8.80109 12.75 9V12.75C12.75 12.9489 12.671 13.1397 12.5303 13.2803C12.3897 13.421 12.1989 13.5 12 13.5C11.8011 13.5 11.6103 13.421 11.4697 13.2803C11.329 13.1397 11.25 12.9489 11.25 12.75ZM12 17.25C12.2225 17.25 12.44 17.184 12.625 17.0604C12.81 16.9368 12.9542 16.7611 13.0394 16.5555C13.1245 16.35 13.1468 16.1238 13.1034 15.9055C13.06 15.6873 12.9528 15.4868 12.7955 15.3295C12.6382 15.1722 12.4377 15.065 12.2195 15.0216C12.0012 14.9782 11.775 15.0005 11.5695 15.0856C11.3639 15.1708 11.1882 15.315 11.0646 15.5C10.941 15.685 10.875 15.9025 10.875 16.125C10.875 16.4234 10.9935 16.7095 11.2045 16.9205C11.4155 17.1315 11.7016 17.25 12 17.25ZM21 5.25V10.5C21 15.4425 18.6075 18.4378 16.6003 20.0803C14.4384 21.8484 12.2878 22.4494 12.1941 22.4738C12.0652 22.5088 11.9292 22.5088 11.8003 22.4738C11.7066 22.4494 9.55875 21.8484 7.39406 20.0803C5.3925 18.4378 3 15.4425 3 10.5V5.25C3 4.85218 3.15804 4.47064 3.43934 4.18934C3.72064 3.90804 4.10218 3.75 4.5 3.75H19.5C19.8978 3.75 20.2794 3.90804 20.5607 4.18934C20.842 4.47064 21 4.85218 21 5.25ZM19.5 5.25H4.5V10.5C4.5 13.9969 5.79562 16.8291 8.35031 18.9197C9.43805 19.8093 10.6733 20.5013 12 20.9644C13.3443 20.4931 14.595 19.7886 15.6947 18.8831C18.2194 16.7963 19.5 13.9753 19.5 10.5V5.25Z" fill="#364860"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M23 2.52647V9.2355C23 19.4652 14.3123 22.8591 12.5729 23.4356C12.2014 23.5614 11.7986 23.5614 11.4271 23.4356C9.68542 22.8591 1 19.4652 1 9.2355V2.52647C1 2.04205 1.19315 1.57747 1.53697 1.23493C1.88079 0.892387 2.3471 0.699951 2.83333 0.699951H21.1667C21.6529 0.699951 22.1192 0.892387 22.463 1.23493C22.8068 1.57747 23 2.04205 23 2.52647Z" fill="#364860"/>
<path d="M20.3333 1.59998H3.66667C3.22464 1.59998 2.80072 1.77557 2.48816 2.08813C2.17559 2.40069 2 2.82461 2 3.26664V9.38852C2 18.7229 9.89792 21.8198 11.4792 22.3458C11.8169 22.4607 12.1831 22.4607 12.5208 22.3458C14.1042 21.8198 22 18.7229 22 9.38852V3.26664C22 2.82461 21.8244 2.40069 21.5118 2.08813C21.1993 1.77557 20.7754 1.59998 20.3333 1.59998ZM16.7563 8.85623L10.9229 14.6896C10.8455 14.767 10.7536 14.8285 10.6525 14.8704C10.5513 14.9124 10.4428 14.934 10.3333 14.934C10.2238 14.934 10.1154 14.9124 10.0142 14.8704C9.91305 14.8285 9.82114 14.767 9.74375 14.6896L7.24375 12.1896C7.08738 12.0332 6.99954 11.8211 6.99954 11.6C6.99954 11.3788 7.08738 11.1668 7.24375 11.0104C7.40012 10.854 7.6122 10.7662 7.83333 10.7662C8.05447 10.7662 8.26655 10.854 8.42292 11.0104L10.3333 12.9208L15.5771 7.67706C15.6545 7.59963 15.7464 7.53822 15.8476 7.49631C15.9487 7.45441 16.0572 7.43285 16.1667 7.43285C16.2762 7.43285 16.3846 7.45441 16.4857 7.49631C16.5869 7.53822 16.6788 7.59963 16.7563 7.67706C16.8337 7.75448 16.8951 7.8464 16.937 7.94756C16.9789 8.04872 17.0005 8.15715 17.0005 8.26664C17.0005 8.37614 16.9789 8.48456 16.937 8.58572C16.8951 8.68688 16.8337 8.7788 16.7563 8.85623Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -270,16 +270,28 @@ bool CallModel::getAuthenticationTokenVerified() const {
return mMonitor->getAuthenticationTokenVerified();
}
void CallModel::setAuthenticationTokenVerified(bool verified) {
void CallModel::checkAuthenticationToken(const QString &token) {
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
mMonitor->setAuthenticationTokenVerified(verified);
emit authenticationTokenVerifiedChanged(verified);
mMonitor->checkAuthenticationTokenSelected(Utils::appStringToCoreString(token));
}
std::string CallModel::getAuthenticationToken() const {
mustBeInLinphoneThread(log().arg(Q_FUNC_INFO));
auto token = mMonitor->getAuthenticationToken();
return token;
void CallModel::skipZrtpAuthentication() {
mMonitor->skipZrtpAuthentication();
}
std::string CallModel::getLocalAtuhenticationToken() const {
return mMonitor->getLocalAuthenticationToken();
}
QStringList CallModel::getRemoteAtuhenticationTokens() const {
QStringList ret;
for (auto &token : mMonitor->getRemoteAuthenticationTokens())
ret.append(Utils::coreStringToAppString(token));
return ret;
}
bool CallModel::getZrtpCaseMismatch() const {
return mMonitor->getZrtpCacheMismatchFlag();
}
void CallModel::setConference(const std::shared_ptr<linphone::Conference> &conference) {
@ -459,3 +471,7 @@ void CallModel::onAudioDeviceChanged(const std::shared_ptr<linphone::Call> &call
void CallModel::onRemoteRecording(const std::shared_ptr<linphone::Call> &call, bool recording) {
emit remoteRecording(call, recording);
}
void CallModel::onAuthenticationTokenVerified(const std::shared_ptr<linphone::Call> &call, bool verified) {
emit authenticationTokenVerified(call, verified);
}

View file

@ -66,8 +66,11 @@ public:
std::string getRecordFile() const;
std::shared_ptr<const linphone::Address> getRemoteAddress();
bool getAuthenticationTokenVerified() const;
void setAuthenticationTokenVerified(bool verified);
std::string getAuthenticationToken() const;
void checkAuthenticationToken(const QString &token);
void skipZrtpAuthentication();
std::string getLocalAtuhenticationToken() const;
QStringList getRemoteAtuhenticationTokens() const;
bool getZrtpCaseMismatch() const;
LinphoneEnums::ConferenceLayout getConferenceVideoLayout() const;
void changeConferenceVideoLayout(LinphoneEnums::ConferenceLayout layout); // Make a call request
@ -91,7 +94,6 @@ signals:
void remoteVideoEnabledChanged(bool remoteVideoEnabled);
void localVideoEnabledChanged(bool enabled);
void recordingChanged(bool recording);
void authenticationTokenVerifiedChanged(bool verified);
void speakerVolumeGainChanged(float volume);
void microphoneVolumeGainChanged(float volume);
void inputAudioDeviceChanged(const std::string &id);
@ -143,6 +145,7 @@ private:
virtual void onAudioDeviceChanged(const std::shared_ptr<linphone::Call> &call,
const std::shared_ptr<linphone::AudioDevice> &audioDevice) override;
virtual void onRemoteRecording(const std::shared_ptr<linphone::Call> &call, bool recording) override;
virtual void onAuthenticationTokenVerified(const std::shared_ptr<linphone::Call> &call, bool verified);
signals:
void dtmfReceived(const std::shared_ptr<linphone::Call> &call, int dtmf);
@ -170,6 +173,7 @@ signals:
void audioDeviceChanged(const std::shared_ptr<linphone::Call> &call,
const std::shared_ptr<linphone::AudioDevice> &audioDevice);
void remoteRecording(const std::shared_ptr<linphone::Call> &call, bool recording);
void authenticationTokenVerified(const std::shared_ptr<linphone::Call> &call, bool verified);
};
#endif

View file

@ -31,7 +31,7 @@ AppWindow {
middleItemStackView.replace(inCallItem)
bottomButtonsLayout.visible = true
}
if(!call.core.isSecured && call.core.encryption === LinphoneEnums.MediaEncryption.Zrtp) {
if(call.core.encryption === LinphoneEnums.MediaEncryption.Zrtp && (!call.core.tokenVerified || call.core.isMismatch)) {
zrtpValidation.open()
}
}
@ -184,7 +184,7 @@ AppWindow {
ZrtpTokenAuthenticationDialog {
id: zrtpValidation
call: mainWindow.call
modal: false
modal: true
}
Popup {
id: waitingPopup
@ -334,20 +334,60 @@ AppWindow {
}
RowLayout {
spacing: 5 * DefaultStyle.dp
visible: mainWindow.call && mainWindow.call.core.isSecured
visible: mainWindow.callState != LinphoneEnums.CallState.End && mainWindow.callState != LinphoneEnums.CallState.Released
BusyIndicator {
visible: mainWindow.call && mainWindow.callState != LinphoneEnums.CallState.Connected && mainWindow.callState != LinphoneEnums.CallState.StreamsRunning
Layout.preferredWidth: 15 * DefaultStyle.dp
Layout.preferredHeight: 15 * DefaultStyle.dp
indicatorColor: DefaultStyle.grey_0
}
EffectImage {
Layout.preferredWidth: 15 * DefaultStyle.dp
Layout.preferredHeight: 15 * DefaultStyle.dp
colorizationColor: DefaultStyle.info_500_main
imageSource: AppIcons.lockSimple
colorizationColor: mainWindow.call.core.encryption === LinphoneEnums.MediaEncryption.Srtp
? DefaultStyle.info_500_main
: mainWindow.call.core.encryption === LinphoneEnums.MediaEncryption.Zrtp
? mainWindow.call.core.isMismatch || !mainWindow.call.core.tokenVerified
? DefaultStyle.warning_600
: DefaultStyle.info_500_main
: DefaultStyle.grey_0
visible: mainWindow.call && mainWindow.callState === LinphoneEnums.CallState.Connected || mainWindow.callState === LinphoneEnums.CallState.StreamsRunning
imageSource: mainWindow.call.core.encryption === LinphoneEnums.MediaEncryption.Srtp
? AppIcons.lockSimple
: mainWindow.call.core.encryption === LinphoneEnums.MediaEncryption.Zrtp
? mainWindow.call.core.isMismatch || !mainWindow.call.core.tokenVerified
? AppIcons.warningCircle
: AppIcons.lockKey
: AppIcons.lockSimpleOpen
}
Text {
text: qsTr("Appel chiffré de bout en bout")
color: DefaultStyle.info_500_main
text: mainWindow.call && mainWindow.callState === LinphoneEnums.CallState.Connected || mainWindow.callState === LinphoneEnums.CallState.StreamsRunning
? mainWindow.call.core.encryption === LinphoneEnums.MediaEncryption.Srtp
? qsTr("Appel chiffré de point à point")
: mainWindow.call.core.encryption === LinphoneEnums.MediaEncryption.Zrtp
? mainWindow.call.core.isMismatch || !mainWindow.call.core.tokenVerified
? qsTr("Vérification nécessaire")
: qsTr("Appel chiffré de bout en bout")
: qsTr("Appel non chiffré")
: qsTr("En attente de chiffrement")
color: mainWindow.call && mainWindow.callState === LinphoneEnums.CallState.Connected || mainWindow.callState === LinphoneEnums.CallState.StreamsRunning
? mainWindow.call.core.encryption === LinphoneEnums.MediaEncryption.Srtp
? DefaultStyle.info_500_main
: mainWindow.call.core.encryption === LinphoneEnums.MediaEncryption.Zrtp
? mainWindow.call.core.isMismatch || !mainWindow.call.core.tokenVerified
? DefaultStyle.warning_600
: DefaultStyle.info_500_main
: DefaultStyle.grey_0
: DefaultStyle.grey_0
font {
pixelSize: 12 * DefaultStyle.dp
weight: 400 * DefaultStyle.dp
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: containsMouse ? Qt.PointingHandCursor : Qt.ArrowCursor
}
}
Item {
Layout.fillWidth: true

View file

@ -152,4 +152,4 @@ ColumnLayout {
}
}
}
}

View file

@ -8,150 +8,311 @@ import UtilsCpp 1.0
// =============================================================================
Dialog {
id: mainItem
property var call
width: 436 * DefaultStyle.dp
height: 549 * DefaultStyle.dp
rightPadding: 15 * DefaultStyle.dp
leftPadding: 15 * DefaultStyle.dp
topPadding: 40 * DefaultStyle.dp
bottomPadding: 40 * DefaultStyle.dp
rightPadding: 0 * DefaultStyle.dp
leftPadding: 0 * DefaultStyle.dp
topPadding: 85 * DefaultStyle.dp + 23 * DefaultStyle.dp
bottomPadding: 24 * DefaultStyle.dp
modal: true
closePolicy: Popup.NoAutoClose
property var call
onCallChanged: if(!call) close()
property bool isTokenVerified: call && call.core.tokenVerified || false
property bool isCaseMismatch: call && call.core.isMismatch || false
property bool securityError: false
property bool firstTry: true
Connections {
enabled: call != undefined && call != null
target: call && call.core
onStatusChanged: if (status === CallModel.CallStatusEnded) close()
}
buttons: Layout.ColumnLayout {
spacing: 15 * DefaultStyle.dp
Button {
Layout.Layout.alignment: Qt.AlignHCenter
background: Item{}
contentItem: Text {
text: qsTr("Skip")
font {
pixelSize: 13 * DefaultStyle.dp
weight: 600 * DefaultStyle.dp
underline: true
}
}
onClicked: {
if(mainItem.call) mainItem.call.core.lVerifyAuthenticationToken(false)
mainItem.close()
}
onSecurityUpdated: {
if (!mainItem.isTokenVerified) {
mainItem.securityError = true
} else close()
}
Button {
text: qsTr("Letters doesn't match")
color: DefaultStyle.danger_500main
inversedColors: true
Layout.Layout.alignment: Qt.AlignHCenter
width: 330 * DefaultStyle.dp
onClicked: {
if(mainItem.call) mainItem.call.core.lVerifyAuthenticationToken(false)
mainItem.close()
}
onTokenVerified: {
if (!mainItem.isTokenVerified) {
mainItem.securityError = true
} else close()
}
}
content: Layout.ColumnLayout {
spacing: 32 * DefaultStyle.dp
Layout.Layout.alignment: Qt.AlignHCenter
Layout.ColumnLayout {
spacing: 10 * DefaultStyle.dp
Text {
Layout.Layout.preferredWidth: 330 * DefaultStyle.dp
Layout.Layout.alignment: Qt.AlignHCenter
text: qsTr("Vérifier l'appareil")
horizontalAlignment: Text.AlignLeft
font {
pixelSize: 16 * DefaultStyle.dp
weight: 800 * DefaultStyle.dp
}
}
Text {
Layout.Layout.preferredWidth: 330 * DefaultStyle.dp
Layout.Layout.alignment: Qt.AlignHCenter
horizontalAlignment: Text.AlignLeft
//: 'To raise the security level, you can check the following codes with your correspondent.' : Explanation to do a security check.
text: qsTr("Dites %1 et cliquez sur les lettres votre interlocuteur vous dit :".arg(mainItem.call && mainItem.call.core.localSas || ""))
wrapMode: Text.WordWrap
font.pixelSize: 14 * DefaultStyle.dp
}
}
Layout.GridLayout {
id: securityGridView
// Layout.Layout.fillWidth: true
Layout.Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
rows: 2
columns: 2
rowSpacing: 32 * DefaultStyle.dp
columnSpacing: 32 * DefaultStyle.dp
property var correctIndex
property var modelList
Connections {
enabled: mainItem.call
target: mainItem.call ? mainItem.call.core : null
// this connection is needed to get the remoteSas when available
// due to the asynchronous connection between core and ui
onRemoteSasChanged: {
securityGridView.correctIndex = UtilsCpp.getRandomIndex(4)
securityGridView.modelList = UtilsCpp.generateSecurityLettersArray(4, securityGridView.correctIndex, mainItem.call.core.remoteSas)
}
}
Repeater {
model: securityGridView.modelList
background: Item {
anchors.fill: parent
Rectangle {
id: backgroundItem
anchors.fill: parent
width: mainItem.width
height: mainItem.implicitHeight
color: mainItem.securityError
? DefaultStyle.danger_500main
: mainItem.isCaseMismatch
? DefaultStyle.warning_600
: DefaultStyle.info_500_main
radius: mainItem.radius
Layout.ColumnLayout {
anchors.top: parent.top
anchors.topMargin: 18 * DefaultStyle.dp
anchors.horizontalCenter: parent.horizontalCenter
Item {
// implicitWidth: 70 * DefaultStyle.dp
// implicitHeight: 70 * DefaultStyle.dp
width: 70 * DefaultStyle.dp
height: 70 * DefaultStyle.dp
Rectangle {
id: code
anchors.fill: parent
color: DefaultStyle.grey_0
radius: 71 * DefaultStyle.dp
Text {
anchors.fill: parent
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
text: modelData
font {
pixelSize: 32 * DefaultStyle.dp
weight: 400 * DefaultStyle.dp
}
// spacing: 14 * DefaultStyle.dp
width: childrenRect.width
height: childrenRect.height
Layout.Layout.fillWidth: true
Image {
id: trustShield
anchors.centerIn: parent
source: AppIcons.trustedWhite
sourceSize.width: 24 * DefaultStyle.dp
sourceSize.height: 24 * DefaultStyle.dp
width: 24 * DefaultStyle.dp
height: 24 * DefaultStyle.dp
}
EffectImage {
anchors.left: trustShield.right
anchors.leftMargin: 14 * DefaultStyle.dp
visible: mainItem.securityError
imageSource: AppIcons.shieldWarning
colorizationColor: DefaultStyle.main2_700
width: 24 * DefaultStyle.dp
height: 24 * DefaultStyle.dp
}
}
Text {
text: qsTr("Vérification de sécurité")
color: DefaultStyle.grey_0
Layout.Layout.alignment: Qt.AlignHCenter
font {
pixelSize: 14 * DefaultStyle.dp
weight: 700 * DefaultStyle.dp
}
}
Item{Layout.Layout.fillHeight: true}
}
Button {
visible: !mainItem.securityError
anchors.top: parent.top
anchors.right: parent.right
anchors.topMargin: 10 * DefaultStyle.dp
anchors.rightMargin: 17 * DefaultStyle.dp
background: Item{}
contentItem: Text {
text: qsTr("Passer")
color: DefaultStyle.grey_0
font {
pixelSize: 13 * DefaultStyle.dp
weight: 600 * DefaultStyle.dp
underline: true
}
}
onClicked: {
call.core.lSkipZrtpAuthentication()
mainItem.close()
}
}
}
Rectangle {
z: 1
width: mainItem.width
height: parent.height - 87 * DefaultStyle.dp
x: parent.x
y: parent.y + 85 * DefaultStyle.dp
color: DefaultStyle.grey_0
radius: mainItem.radius
}
MultiEffect {
anchors.fill: backgroundItem
source: backgroundItem
shadowEnabled: true
shadowColor: DefaultStyle.grey_900
shadowBlur: 1.0
shadowOpacity: 0.1
}
}
content: [
Layout.ColumnLayout {
visible: !mainItem.securityError
spacing: 20 * DefaultStyle.dp
Layout.Layout.alignment: Qt.AlignHCenter
Layout.Layout.fillWidth: true
Layout.ColumnLayout {
spacing: 10 * DefaultStyle.dp
Layout.Layout.alignment: Qt.AlignHCenter
Text {
Layout.Layout.preferredWidth: 343 * DefaultStyle.dp
Layout.Layout.alignment: Qt.AlignHCenter
horizontalAlignment: Text.AlignHCenter
text: !mainItem.isTokenVerified && mainItem.isCaseMismatch
? qsTr("Pour garantir le chiffrement, nous avons besoin de réauthentifier lappareil de votre correspondant. Echangez vos codes :")
: qsTr("Pour garantir le chiffrement, nous avons besoin dauthentifier lappareil de votre correspondant. Veuillez échanger vos codes : ")
wrapMode: Text.WordWrap
font.pixelSize: 14 * DefaultStyle.dp
}
Layout.ColumnLayout {
spacing: 0
Layout.Layout.alignment: Qt.AlignHCenter
Text {
text: qsTr("Votre code :")
horizontalAlignment: Text.AlignHCenter
Layout.Layout.alignment: Qt.AlignHCenter
font.pixelSize: 14 * DefaultStyle.dp
}
Text {
text: mainItem.call && mainItem.call.core.localToken || ""
horizontalAlignment: Text.AlignHCenter
Layout.Layout.alignment: Qt.AlignHCenter
font {
pixelSize: 18 * DefaultStyle.dp
weight: 700 * DefaultStyle.dp
}
MouseArea {
anchors.fill: parent
onClicked: {
console.log("correct", index == securityGridView.correctIndex, index)
if (index == securityGridView.correctIndex) {
if(mainItem.call) mainItem.call.core.lVerifyAuthenticationToken(true)
} else {
if(mainItem.call) mainItem.call.core.lVerifyAuthenticationToken(false)
mainItem.close()
}
}
}
Rectangle {
color: "transparent"
border.color: DefaultStyle.main2_200
border.width: Math.max(0.5, 1 * DefaultStyle.dp)
radius: 15 * DefaultStyle.dp
Layout.Layout.preferredWidth: 292 * DefaultStyle.dp
Layout.Layout.preferredHeight: 233 * DefaultStyle.dp
Layout.Layout.alignment: Qt.AlignHCenter
Layout.ColumnLayout {
anchors.fill: parent
anchors.topMargin: 10 * DefaultStyle.dp
Text {
text: qsTr("Code correspondant :")
font.pixelSize: 14 * DefaultStyle.dp
Layout.Layout.alignment: Qt.AlignHCenter
}
Layout.GridLayout {
id: securityGridView
Layout.Layout.alignment: Qt.AlignHCenter
rows: 2
columns: 2
rowSpacing: 32 * DefaultStyle.dp
columnSpacing: 32 * DefaultStyle.dp
property var correctIndex
property var modelList
Repeater {
model: mainItem.call && mainItem.call.core.remoteTokens || ""
Item {
width: 70 * DefaultStyle.dp
height: 70 * DefaultStyle.dp
Rectangle {
id: code
anchors.fill: parent
color: DefaultStyle.grey_0
radius: 71 * DefaultStyle.dp
Text {
anchors.fill: parent
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
text: modelData
font {
pixelSize: 32 * DefaultStyle.dp
weight: 400 * DefaultStyle.dp
}
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: containsMouse ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: {
console.log("check token", modelData)
if(mainItem.call) mainItem.call.core.lCheckAuthenticationTokenSelected(modelData)
}
}
}
MultiEffect {
source: code
anchors.fill: code
shadowEnabled: true
shadowOpacity: 0.1
shadowBlur: 1.0
}
}
}
}
MultiEffect {
source: code
anchors.fill: code
shadowEnabled: true
shadowOpacity: 0.1
shadowBlur: 1.0
}
}
}
},
Layout.ColumnLayout {
spacing: 0
Text {
visible: mainItem.securityError
width: 303 * DefaultStyle.dp
// Layout.Layout.preferredWidth: 343 * DefaultStyle.dp
Layout.Layout.alignment: Qt.AlignHCenter
Layout.Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
text: qsTr("Le code fourni ne correspond pas.")
wrapMode: Text.WordWrap
font.pixelSize: 14 * DefaultStyle.dp
}
Text {
visible: mainItem.securityError
width: 303 * DefaultStyle.dp
// Layout.Layout.preferredWidth: 343 * DefaultStyle.dp
Layout.Layout.alignment: Qt.AlignHCenter
Layout.Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
text: qsTr("La confidentialité de votre appel peut être compromise !")
wrapMode: Text.WordWrap
font.pixelSize: 14 * DefaultStyle.dp
}
}
]
buttons: Layout.ColumnLayout {
Layout.Layout.alignment: Qt.AlignHCenter
Button {
Layout.Layout.alignment: Qt.AlignHCenter
text: qsTr("Aucune correspondance")
color: DefaultStyle.danger_500main
inversedColors: true
textSize: 15 * DefaultStyle.dp
visible: !mainItem.securityError
leftPadding: 16 * DefaultStyle.dp
rightPadding: 16 * DefaultStyle.dp
topPadding: 10 * DefaultStyle.dp
bottomPadding: 10 * DefaultStyle.dp
width: 247 * DefaultStyle.dp
onClicked: {
if(mainItem.call) mainItem.call.core.lCheckAuthenticationTokenSelected(" ")
}
}
Button {
Layout.Layout.preferredWidth: 247 * DefaultStyle.dp
visible: mainItem.securityError && mainItem.firstTry
text: qsTr("Réessayer")
color: DefaultStyle.danger_500main
inversedColors: true
leftPadding: 16 * DefaultStyle.dp
rightPadding: 16 * DefaultStyle.dp
topPadding: 10 * DefaultStyle.dp
bottomPadding: 10 * DefaultStyle.dp
onClicked: {
mainItem.firstTry = false
mainItem.securityError = false
}
}
Button {
Layout.Layout.preferredWidth: 247 * DefaultStyle.dp
visible: mainItem.securityError
leftPadding: (247 * DefaultStyle.dp - contentItem.implicitWidth) /2
rightPadding: (247 * DefaultStyle.dp - contentItem.implicitWidth) /2
topPadding: 10 * DefaultStyle.dp
bottomPadding: 10 * DefaultStyle.dp
color: DefaultStyle.danger_500main
onClicked: mainItem.call.core.lTerminate()
spacing: 15 * DefaultStyle.dp
icon.source: AppIcons.endCall
contentImageColor: DefaultStyle.grey_0
text: qsTr("Raccrocher")
textColor: DefaultStyle.grey_0
}
}
}
}

View file

@ -6,6 +6,9 @@ QtObject {
property string welcomeLock: "image://internal/secured.svg"
property string lock: "image://internal/lock.svg"
property string lockSimple: "image://internal/lock-simple.svg"
property string lockSimpleOpen: "image://internal/lock-simple-open.svg"
property string lockKey: "image://internal/lock-key.svg"
property string shieldWarning: "image://internal/shield-warning.svg"
property string welcomeOpenSource: "image://internal/open_source.svg"
property string splashscreenLogo: "image://internal/splashscreen-logo.svg"
property string eyeHide: "image://internal/eye.svg"
@ -60,6 +63,7 @@ QtObject {
property string speaker: "image://internal/speaker-high.svg"
property string speakerSlash: "image://internal/speaker-slash.svg"
property string trusted: "image://internal/trusted.svg"
property string trustedWhite: "image://internal/trusted-white.svg"
property string avatar: "image://internal/randomAvatar.png"
property string pause: "image://internal/pause.svg"
property string play: "image://internal/play.svg"