From 865cd2927aa34fe284d8321fdc38b1ce1bd94e84 Mon Sep 17 00:00:00 2001
From: Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com>
Date: Wed, 4 Mar 2015 14:40:11 -0500
Subject: [PATCH] Get and parse the certificate for in progress calls

Refs #66481
---
 CMakeLists.txt                                |  2 +
 src/account.cpp                               |  1 +
 src/call.cpp                                  |  3 +-
 src/call.h                                    |  1 +
 src/certificate.cpp                           | 10 ++-
 src/certificate.h                             |  2 +
 src/certificatemodel.cpp                      | 72 ++++++++++++++++++-
 src/delegates/accountlistcolordelegate.h      |  1 -
 .../certificateserializationdelegate.cpp      | 56 +++++++++++++++
 .../certificateserializationdelegate.h        | 38 ++++++++++
 src/fallbackpersoncollection.cpp              |  2 +-
 src/typedefs.h                                |  2 +
 src/useractionmodel.cpp                       | 20 +++---
 xml/configurationmanager-introspec.xml        | 16 +++++
 14 files changed, 210 insertions(+), 16 deletions(-)
 create mode 100644 src/delegates/certificateserializationdelegate.cpp
 create mode 100644 src/delegates/certificateserializationdelegate.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index dc4af883..f7b51217 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -235,6 +235,7 @@ SET( libringclient_LIB_SRCS
   src/delegates/presenceserializationdelegate.cpp
   src/delegates/itemmodelstateserializationdelegate.cpp
   src/delegates/profilepersisterdelegate.cpp
+  src/delegates/certificateserializationdelegate.cpp
 
   #Other
   src/categorizedcompositenode.cpp
@@ -345,6 +346,7 @@ SET(libringclient_delegates_LIB_HDRS
   src/delegates/pixmapmanipulationdelegate.h
   src/delegates/numbercategorydelegate.h
   src/delegates/profilepersisterdelegate.h
+  src/delegates/certificateserializationdelegate.h
 )
 
 SET( libringclient_extra_LIB_HDRS
diff --git a/src/account.cpp b/src/account.cpp
index 33db2274..3a67ec1c 100644
--- a/src/account.cpp
+++ b/src/account.cpp
@@ -170,6 +170,7 @@ void AccountPrivate::slotUpdateCertificate()
                setAccountProperty(DRing::Account::ConfProperties::TLS::PRIVATE_KEY_FILE, cert->path().toString());
             break;
          case Certificate::Type::NONE:
+         case Certificate::Type::CALL:
             break;
       };
    }
diff --git a/src/call.cpp b/src/call.cpp
index 879d9abb..03541aeb 100644
--- a/src/call.cpp
+++ b/src/call.cpp
@@ -418,7 +418,8 @@ Call* Call::buildHistoryCall(const QMap<QString,QString>& hc)
    const QString& number          = hc[ Call::HistoryMapFields::PEER_NUMBER     ]          ;
    const QString& type            = hc[ Call::HistoryMapFields::STATE           ]          ;
    const QString& direction       = hc[ Call::HistoryMapFields::DIRECTION       ]          ;
-   const bool     missed          = hc[ Call::HistoryMapFields::MISSED          ] == "1";
+   const QString& cert_path       = hc[ Call::HistoryMapFields::CERT_PATH       ]          ;
+   const bool     missed          = hc[ Call::HistoryMapFields::MISSED          ] == "1"   ;
    time_t         startTimeStamp  = hc[ Call::HistoryMapFields::TIMESTAMP_START ].toUInt() ;
    time_t         stopTimeStamp   = hc[ Call::HistoryMapFields::TIMESTAMP_STOP  ].toUInt() ;
    QByteArray accId               = hc[ Call::HistoryMapFields::ACCOUNT_ID      ].toLatin1();
diff --git a/src/call.h b/src/call.h
index 6fe51cbc..0a9cda95 100644
--- a/src/call.h
+++ b/src/call.h
@@ -196,6 +196,7 @@ public:
       constexpr static const char* CONTACT_USED      = "contact_used"   ;
       constexpr static const char* CONTACT_UID       = "contact_uid"    ;
       constexpr static const char* NUMBER_TYPE       = "number_type"    ;
+      constexpr static const char* CERT_PATH         = "cert_path"      ;
    };
 
    //TODO should be deprecated when a better factory system is implemented
diff --git a/src/certificate.cpp b/src/certificate.cpp
index c239783f..94c2ab93 100644
--- a/src/certificate.cpp
+++ b/src/certificate.cpp
@@ -300,7 +300,15 @@ void CertificatePrivate::loadDetails()
 void CertificatePrivate::loadChecks()
 {
    if (!m_pCheckCache) {
-      const MapStringString checks = DBus::ConfigurationManager::instance().validateCertificate(QString(),m_Path.toString(),QString());
+      MapStringString checks;
+      switch(m_LoadingType) {
+         case LoadingType::FROM_PATH:
+            checks = DBus::ConfigurationManager::instance().validateCertificate(QString(),m_Path.toString(),QString());
+            break;
+         case LoadingType::FROM_CONTENT:
+            checks = DBus::ConfigurationManager::instance().validateCertificateRaw(QString(),m_Content);
+            break;
+      }
       m_pCheckCache = new ChecksCache(checks);
    }
 }
diff --git a/src/certificate.h b/src/certificate.h
index e35bd980..6b4232d5 100644
--- a/src/certificate.h
+++ b/src/certificate.h
@@ -169,6 +169,7 @@ public:
       UNSUPPORTED, /** The operating system doesn't support or require the check         */
       COUNT__,
    };
+   Q_ENUMS(CheckValues)
 
    //Getter
    QUrl path() const;
@@ -239,5 +240,6 @@ Q_SIGNALS:
    void changed();
 };
 Q_DECLARE_METATYPE(Certificate*)
+Q_DECLARE_METATYPE(Certificate::CheckValues)
 
 #endif
diff --git a/src/certificatemodel.cpp b/src/certificatemodel.cpp
index 1b27c7a0..8e7a8c53 100644
--- a/src/certificatemodel.cpp
+++ b/src/certificatemodel.cpp
@@ -21,12 +21,16 @@
 #include <QtCore/QCoreApplication>
 #include <QtCore/QObject>
 #include <QtCore/QCryptographicHash>
+#include <QtCore/QThread>
+#include <QtCore/QMutex>
+#include <QtCore/QMutexLocker>
 
 //LibSTDC++
 #include <functional>
 
 //Ring
 #include "certificate.h"
+#include "delegates/certificateserializationdelegate.h"
 
 struct CertificateNode {
 
@@ -53,6 +57,36 @@ struct CertificateNode {
    bool                      m_IsLoaded    ;
 };
 
+class BackgroundLoader : public QThread
+{
+   Q_OBJECT
+public:
+
+   //Attributes
+   QList<QByteArray> m_lIdList    ;
+   QMutex            m_LoaderMutex;
+   QList<QByteArray> m_lQueue     ;
+
+   QByteArray        loadCert(const QByteArray& id);
+
+protected:
+   virtual void run() override;
+
+Q_SIGNALS:
+   void listLoaded(const QList<QByteArray>& list);
+};
+
+QByteArray BackgroundLoader::loadCert(const QByteArray& id)
+{
+   if (m_lIdList.isEmpty()) //WARNING potential race
+      QList<QByteArray> m_lIdList = CertificateSerializationDelegate::instance()->listCertificates();
+
+   if (m_lIdList.indexOf(id) == -1) //TODO use an hash map for this
+      return QByteArray();
+
+   return CertificateSerializationDelegate::instance()->loadCertificate(id);
+}
+
 class CertificateModelPrivate
 {
 public:
@@ -67,6 +101,7 @@ public:
    QVector<CertificateNode*>   m_lTopLevelNodes  ;
    QHash<QString,Certificate*> m_hCertificates   ;
    CertificateNode*            m_pDefaultCategory;
+   QMutex                      m_CertLoader;
 
    //Singleton
    static CertificateModel* m_spInstance;
@@ -92,7 +127,7 @@ CertificateNode::CertificateNode(int index, Level level, CertificateNode* parent
 }
 
 CertificateModelPrivate::CertificateModelPrivate(CertificateModel* parent) : q_ptr(parent),
- m_pDefaultCategory(nullptr)
+ m_pDefaultCategory(nullptr),m_CertLoader()
 {
 
 }
@@ -115,6 +150,18 @@ CertificateModel* CertificateModel::instance()
    return CertificateModelPrivate::m_spInstance;
 }
 
+void BackgroundLoader::run()
+{
+   if (m_lIdList.isEmpty()) //WARNING potential race
+      QList<QByteArray> m_lIdList = CertificateSerializationDelegate::instance()->listCertificates();
+
+   QMutexLocker(&this->m_LoaderMutex);
+   for(const QByteArray& id : m_lIdList) {
+      CertificateModel::instance()->getCertificateFromContent(loadCert(id),false);
+   }
+   exit(0);
+}
+
 QHash<int,QByteArray> CertificateModel::roleNames() const
 {
    static QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
@@ -151,6 +198,8 @@ CertificateNode* CertificateModelPrivate::defaultCategory()
 
 CertificateNode* CertificateModelPrivate::addToTree(Certificate* cert, CertificateNode* category)
 {
+   QMutexLocker(&this->m_CertLoader);
+
    if (!category)
       category = defaultCategory();
 
@@ -299,6 +348,7 @@ Certificate* CertificateModel::getCertificate(const QUrl& path, Certificate::Typ
    //The certificate is not loaded yet
    if (!cert) {
       cert = new Certificate(path);
+      d_ptr->m_hCertificates[path.toString().toLatin1()] = cert;
 
       //Add it to the model
       d_ptr->addToTree(cert);
@@ -310,6 +360,24 @@ Certificate* CertificateModel::getCertificate(const QUrl& path, Certificate::Typ
 Certificate* CertificateModel::getCertificateFromContent(const QByteArray& rawContent, bool save)
 {
    QCryptographicHash hash(QCryptographicHash::Sha1);
+
+   //Create a reproducible key for this file
+   QByteArray id = hash.result().toHex();
+
    hash.addData(rawContent);
-   return nullptr;
+   Certificate* cert = d_ptr->m_hCertificates[id];
+   if (!cert) {
+      cert = new Certificate(rawContent);
+      d_ptr->m_hCertificates[id] = cert;
+
+      d_ptr->addToTree(cert);
+
+      if (save) {
+         CertificateSerializationDelegate::instance()->saveCertificate(id,rawContent);
+      }
+   }
+
+   return cert;
 }
+
+#include <certificatemodel.moc>
diff --git a/src/delegates/accountlistcolordelegate.h b/src/delegates/accountlistcolordelegate.h
index 54a284ef..04a2c465 100644
--- a/src/delegates/accountlistcolordelegate.h
+++ b/src/delegates/accountlistcolordelegate.h
@@ -15,7 +15,6 @@
  *   You should have received a copy of the GNU General Public License      *
  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
  ***************************************************************************/
-
 #ifndef ACCOUNTLISTCOLORVISITOR_H
 #define ACCOUNTLISTCOLORVISITOR_H
 
diff --git a/src/delegates/certificateserializationdelegate.cpp b/src/delegates/certificateserializationdelegate.cpp
new file mode 100644
index 00000000..974c6624
--- /dev/null
+++ b/src/delegates/certificateserializationdelegate.cpp
@@ -0,0 +1,56 @@
+/****************************************************************************
+ *   Copyright (C) 2015 by Savoir-Faire Linux                               *
+ *   Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> *
+ *                                                                          *
+ *   This library is free software; you can redistribute it and/or          *
+ *   modify it under the terms of the GNU Lesser General Public             *
+ *   License as published by the Free Software Foundation; either           *
+ *   version 2.1 of the License, or (at your option) any later version.     *
+ *                                                                          *
+ *   This library is distributed in the hope that it will be useful,        *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU      *
+ *   Lesser General Public License for more details.                        *
+ *                                                                          *
+ *   You should have received a copy of the GNU General Public License      *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
+ ***************************************************************************/
+#include "certificateserializationdelegate.h"
+
+#include <QtCore/QUrl>
+
+CertificateSerializationDelegate* CertificateSerializationDelegate::m_spInstance = new CertificateSerializationDelegate();
+
+CertificateSerializationDelegate* CertificateSerializationDelegate::instance()
+{
+   return m_spInstance;
+}
+
+void CertificateSerializationDelegate::setInstance(CertificateSerializationDelegate* visitor)
+{
+   m_spInstance = visitor;
+}
+
+QByteArray CertificateSerializationDelegate::loadCertificate(const QByteArray& id)
+{
+   Q_UNUSED(id)
+   return QByteArray();
+}
+
+QUrl CertificateSerializationDelegate::saveCertificate(const QByteArray& id, const QByteArray& content)
+{
+   Q_UNUSED(id)
+   Q_UNUSED(content)
+   return QUrl();
+}
+
+QList<QByteArray> CertificateSerializationDelegate::listCertificates()
+{
+   return QList<QByteArray>();
+}
+
+bool CertificateSerializationDelegate::deleteCertificate(const QByteArray& id)
+{
+   Q_UNUSED(id)
+   return false;
+}
diff --git a/src/delegates/certificateserializationdelegate.h b/src/delegates/certificateserializationdelegate.h
new file mode 100644
index 00000000..df53c1be
--- /dev/null
+++ b/src/delegates/certificateserializationdelegate.h
@@ -0,0 +1,38 @@
+/****************************************************************************
+ *   Copyright (C) 2015 by Savoir-Faire Linux                               *
+ *   Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> *
+ *                                                                          *
+ *   This library is free software; you can redistribute it and/or          *
+ *   modify it under the terms of the GNU Lesser General Public             *
+ *   License as published by the Free Software Foundation; either           *
+ *   version 2.1 of the License, or (at your option) any later version.     *
+ *                                                                          *
+ *   This library is distributed in the hope that it will be useful,        *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU      *
+ *   Lesser General Public License for more details.                        *
+ *                                                                          *
+ *   You should have received a copy of the GNU General Public License      *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
+ ***************************************************************************/
+#ifndef CERTIFICATESERIALIZATIONDELEGATE_H
+#define CERTIFICATESERIALIZATIONDELEGATE_H
+
+#include <typedefs.h>
+
+class LIB_EXPORT CertificateSerializationDelegate
+{
+public:
+   virtual QByteArray loadCertificate(const QByteArray& id);
+   virtual QUrl      saveCertificate(const QByteArray& id, const QByteArray& content);
+   virtual bool       deleteCertificate(const QByteArray& id);
+   virtual QList<QByteArray> listCertificates();
+
+   static CertificateSerializationDelegate* instance();
+   static void setInstance(CertificateSerializationDelegate* visitor);
+protected:
+   virtual ~CertificateSerializationDelegate(){}
+   static CertificateSerializationDelegate* m_spInstance;
+};
+
+#endif
diff --git a/src/fallbackpersoncollection.cpp b/src/fallbackpersoncollection.cpp
index bff3e538..4d37a045 100644
--- a/src/fallbackpersoncollection.cpp
+++ b/src/fallbackpersoncollection.cpp
@@ -1,5 +1,5 @@
 /************************************************************************************
- *   Copyright (C) 2014-2015 by Savoir-Faire Linux                                       *
+ *   Copyright (C) 2014-2015 by Savoir-Faire Linux                                  *
  *   Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com>         *
  *                                                                                  *
  *   This library is free software; you can redistribute it and/or                  *
diff --git a/src/typedefs.h b/src/typedefs.h
index c41ca8fb..25ace979 100644
--- a/src/typedefs.h
+++ b/src/typedefs.h
@@ -51,6 +51,7 @@ struct TypedStateMachine
 
    T& operator[](E v) {
    if (size_t(v) >= size_t(E::COUNT__)) {
+      Q_ASSERT(false);
       qDebug() << "State Machine Out of Bound" << size_t(v);
       throw v;
    }
@@ -59,6 +60,7 @@ struct TypedStateMachine
 
    const T& operator[](E v) const {
    if (size_t(v) >= size_t(E::COUNT__)) {
+      Q_ASSERT(false);
       qDebug() << "State Machine Out of Bound" << size_t(v);
       throw v;
    }
diff --git a/src/useractionmodel.cpp b/src/useractionmodel.cpp
index 055cc6e6..f8bcbf7e 100644
--- a/src/useractionmodel.cpp
+++ b/src/useractionmodel.cpp
@@ -103,16 +103,16 @@ public Q_SLOTS:
 
 //Enabled actions
 const TypedStateMachine< TypedStateMachine< bool , Call::State > , UserActionModel::Action > UserActionModelPrivate::availableActionMap = {{
- /*                   INCOMING  RINGING CURRENT DIALING  HOLD  FAILURE BUSY  TRANSFERRED TRANSF_HOLD  OVER  ERROR CONFERENCE CONFERENCE_HOLD:*/
- /*ACCEPT          */ {{ true   , false , false,  true , false, false, false,   false,     false,    false, false,  false,      false    }},
- /*HOLD            */ {{ false  , false,  true ,  false, true , false, false,   false,     false,    false, false,  true ,      false    }},
- /*MUTE_AUDIO      */ {{ false  , true ,  true ,  false, false, false, false,   false,     false,    false, false,  false,      false    }},
- /*MUTE_VIDEO      */ {{ false  , true ,  true ,  false, false, false, false,   false,     false,    false, false,  false,      false    }},
- /*SERVER_TRANSFER */ {{ false  , false,  true ,  false, true , false, false,   false,     false,    false, false,  false,      false    }},
- /*RECORD          */ {{ false  , true ,  true ,  false, true , false, false,   true ,     true ,    false, false,  true ,      true     }},
- /*HANGUP          */ {{ true   , true ,  true ,  true , true , true , true ,   true ,     true ,    false, true ,  true ,      true     }},
-
- /*JOIN            */ {{ false  , true ,  true ,  false, true , false, false,   true ,     true ,    false, false,  true ,      true     }},
+ /*                   INCOMING  RINGING CURRENT DIALING  HOLD  FAILURE BUSY  TRANSFERRED TRANSF_HOLD  OVER  ERROR CONFERENCE CONFERENCE_HOLD  INITIALIZATION*/
+ /*ACCEPT          */ {{ true   , false,  false,  true , false, false, false,   false,     false,    false, false,  false,       false,           false}},
+ /*HOLD            */ {{ false  , false,  true ,  false, true , false, false,   false,     false,    false, false,  true ,       false,           false}},
+ /*MUTE_AUDIO      */ {{ false  , true ,  true ,  false, false, false, false,   false,     false,    false, false,  false,       false,           false}},
+ /*MUTE_VIDEO      */ {{ false  , true ,  true ,  false, false, false, false,   false,     false,    false, false,  false,       false,           false}},
+ /*SERVER_TRANSFER */ {{ false  , false,  true ,  false, true , false, false,   false,     false,    false, false,  false,       false,           false}},
+ /*RECORD          */ {{ false  , true ,  true ,  false, true , false, false,   true ,     true ,    false, false,  true ,       true ,           false}},
+ /*HANGUP          */ {{ true   , true ,  true ,  true , true , true , true ,   true ,     true ,    false, true ,  true ,       true ,           false}},
+
+ /*JOIN            */ {{ false  , true ,  true ,  false, true , false, false,   true ,     true ,    false, false,  true ,       true ,           false }},
 }};
 
 /**
diff --git a/xml/configurationmanager-introspec.xml b/xml/configurationmanager-introspec.xml
index 6b0f3896..1bebf00e 100644
--- a/xml/configurationmanager-introspec.xml
+++ b/xml/configurationmanager-introspec.xml
@@ -649,6 +649,22 @@
            </arg>
        </method>
 
+       <method name="validateCertificateRaw" tp:name-for-bindings="validateCertificateRaw">
+           <arg type="s" name="accountId" direction="in"></arg>
+           <arg type="ay" name="certificateRaw" direction="in">
+              <tp:docstring>
+               <p>A certificate path</p>
+              </tp:docstring>
+           </arg>
+           <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="MapStringString"/>
+           <arg type="a{ss}" name="details" direction="out">
+              <tp:docstring>
+               <p>A key-value list of all certificate validation</p>
+               The constants used as keys are defined in the "security.h" constants header file
+              </tp:docstring>
+           </arg>
+       </method>
+
        <method name="getCertificateDetails" tp:name-for-bindings="getCertificateDetails">
            <arg type="s" name="certificatePath" direction="in">
               <tp:docstring>
-- 
GitLab