From 7f14e58c53d4cd05807d04b06de6a609a5136913 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Blin?=
 <sebastien.blin@savoirfairelinux.com>
Date: Tue, 27 Feb 2018 16:40:14 -0500
Subject: [PATCH] ringaccount: add the ability to copy the account archive

Add a method for exporting the account's archive in a
file.

This patch updates configurationmanager interfaces and
fix an error with exportOnDHT for nodejs.

Change-Id: I9fdfcd20b66854ca768166e5198b8ae428192305
Reviewed-by: Philippe Gorley <philippe.gorley@savoirfairelinux.com>
---
 bin/dbus/cx.ring.Ring.ConfigurationManager.xml | 16 ++++++++++++++++
 bin/dbus/dbusconfigurationmanager.cpp          |  6 ++++++
 bin/dbus/dbusconfigurationmanager.h            |  1 +
 bin/jni/configurationmanager.i                 |  3 ++-
 bin/nodejs/configurationmanager.i              |  3 ++-
 configure.ac                                   |  2 +-
 doc/doxygen/core-doc.cfg.in                    |  2 +-
 src/client/configurationmanager.cpp            |  9 +++++++++
 src/dring/configurationmanager_interface.h     |  1 +
 src/ringdht/ringaccount.cpp                    | 16 ++++++++++++++++
 src/ringdht/ringaccount.h                      |  1 +
 11 files changed, 56 insertions(+), 4 deletions(-)

diff --git a/bin/dbus/cx.ring.Ring.ConfigurationManager.xml b/bin/dbus/cx.ring.Ring.ConfigurationManager.xml
index 78119db0c2..d78238d274 100644
--- a/bin/dbus/cx.ring.Ring.ConfigurationManager.xml
+++ b/bin/dbus/cx.ring.Ring.ConfigurationManager.xml
@@ -169,6 +169,22 @@
            </arg>
        </method>
 
+       <method name="exportToFile" tp:name-for-bindings="exportToFile">
+         <tp:added version="5.1.0"/>
+           <tp:docstring>
+               Copy the account archive to the path provided in argument.
+           </tp:docstring>
+           <arg type="s" name="accountID" direction="in">
+           </arg>
+           <arg type="s" name="destinationPath" direction="in">
+           </arg>
+           <arg type="b" name="success" direction="out">
+               <tp:docstring>
+                   True if the operation was initialized successfully.
+               </tp:docstring>
+           </arg>
+       </method>
+
        <signal name="exportOnRingEnded" tp:name-for-bindings="exportOnRingEnded">
            <tp:docstring>
                Notify clients when the exportOnRing operation ended.
diff --git a/bin/dbus/dbusconfigurationmanager.cpp b/bin/dbus/dbusconfigurationmanager.cpp
index 696ed15d48..0d11510b0a 100644
--- a/bin/dbus/dbusconfigurationmanager.cpp
+++ b/bin/dbus/dbusconfigurationmanager.cpp
@@ -81,6 +81,12 @@ DBusConfigurationManager::exportOnRing(const std::string& accountID, const std::
     return DRing::exportOnRing(accountID, password);
 }
 
+auto
+DBusConfigurationManager::exportToFile(const std::string& accountID, const std::string& destinationPath) -> decltype(DRing::exportToFile(accountID, destinationPath))
+{
+    return DRing::exportToFile(accountID, destinationPath);
+}
+
 auto
 DBusConfigurationManager::revokeDevice(const std::string& accountID, const std::string& password, const std::string& device) -> decltype(DRing::revokeDevice(accountID, password, device))
 {
diff --git a/bin/dbus/dbusconfigurationmanager.h b/bin/dbus/dbusconfigurationmanager.h
index f37ac08ec4..2d76ab8d2b 100644
--- a/bin/dbus/dbusconfigurationmanager.h
+++ b/bin/dbus/dbusconfigurationmanager.h
@@ -68,6 +68,7 @@ class DBusConfigurationManager :
         std::map<std::string, std::string> getAccountTemplate(const std::string& accountType);
         std::string addAccount(const std::map<std::string, std::string>& details);
         bool exportOnRing(const std::string& accountID, const std::string& password);
+        bool exportToFile(const std::string& accountID, const std::string& destinationPath);
         bool revokeDevice(const std::string& accountID, const std::string& password, const std::string& device);
         std::map<std::string, std::string> getKnownRingDevices(const std::string& accountID);
         bool changeAccountPassword(const std::string& accountID, const std::string& password_old, const std::string& password_new);
diff --git a/bin/jni/configurationmanager.i b/bin/jni/configurationmanager.i
index 871c64ee8e..71179f58a6 100644
--- a/bin/jni/configurationmanager.i
+++ b/bin/jni/configurationmanager.i
@@ -88,7 +88,8 @@ std::vector<std::string> getSupportedCiphers(const std::string& accountID);
 std::map<std::string, std::string> getCodecDetails(const std::string& accountID, const unsigned& codecId);
 bool setCodecDetails(const std::string& accountID, const unsigned& codecId, const std::map<std::string, std::string>& details);
 std::vector<unsigned> getActiveCodecList(const std::string& accountID);
-std::string exportOnRing(const std::string& accountID, const std::string& password);
+bool exportOnRing(const std::string& accountID, const std::string& password);
+bool exportToFile(const std::string& accountID, const std::string& destinationPath);
 
 std::map<std::string, std::string> getKnownRingDevices(const std::string& accountID);
 bool revokeDevice(const std::string& accountID, const std::string& password, const std::string& deviceID);
diff --git a/bin/nodejs/configurationmanager.i b/bin/nodejs/configurationmanager.i
index afc44e9d94..c56c99e81e 100644
--- a/bin/nodejs/configurationmanager.i
+++ b/bin/nodejs/configurationmanager.i
@@ -85,7 +85,8 @@ std::vector<std::string> getSupportedCiphers(const std::string& accountID);
 std::map<std::string, std::string> getCodecDetails(const std::string& accountID, const unsigned& codecId);
 bool setCodecDetails(const std::string& accountID, const unsigned& codecId, const std::map<std::string, std::string>& details);
 std::vector<unsigned> getActiveCodecList(const std::string& accountID);
-std::string exportOnRing(const std::string& accountID, const std::string& password);
+bool exportOnRing(const std::string& accountID, const std::string& password);
+bool exportToFile(const std::string& accountID, const std::string& destinationPath);
 
 std::map<std::string, std::string> getKnownRingDevices(const std::string& accountID);
 bool revokeDevice(const std::string& accountID, const std::string& password, const std::string& deviceID);
diff --git a/configure.ac b/configure.ac
index 7f4cbf3cf9..6924d6393a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@ dnl Ring - configure.ac for automake 1.9 and autoconf 2.59
 
 dnl Process this file with autoconf to produce a configure script.
 AC_PREREQ([2.65])
-AC_INIT([Ring Daemon],[5.0.0],[ring@gnu.org],[ring])
+AC_INIT([Ring Daemon],[5.1.0],[ring@gnu.org],[ring])
 
 AC_COPYRIGHT([[Copyright (c) Savoir-faire Linux 2004-2018]])
 AC_REVISION([$Revision$])
diff --git a/doc/doxygen/core-doc.cfg.in b/doc/doxygen/core-doc.cfg.in
index eb3fa6b388..b1a27ce320 100644
--- a/doc/doxygen/core-doc.cfg.in
+++ b/doc/doxygen/core-doc.cfg.in
@@ -31,7 +31,7 @@ PROJECT_NAME           = "Ring Daemon"
 # This could be handy for archiving the generated documentation or
 # if some version control system is used.
 
-PROJECT_NUMBER         = 5.0.0
+PROJECT_NUMBER         = 5.1.0
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer
diff --git a/src/client/configurationmanager.cpp b/src/client/configurationmanager.cpp
index 319d3e87d6..1f4d11c341 100644
--- a/src/client/configurationmanager.cpp
+++ b/src/client/configurationmanager.cpp
@@ -286,6 +286,15 @@ exportOnRing(const std::string& accountID, const std::string& password)
     return false;
 }
 
+bool
+exportToFile(const std::string& accountID, const std::string& destinationPath)
+{
+    if (const auto account = ring::Manager::instance().getAccount<ring::RingAccount>(accountID)) {
+        return account->exportArchive(destinationPath);
+    }
+    return false;
+}
+
 bool
 revokeDevice(const std::string& accountID, const std::string& password, const std::string& deviceID)
 {
diff --git a/src/dring/configurationmanager_interface.h b/src/dring/configurationmanager_interface.h
index 3e78409a4a..1e107cbe49 100644
--- a/src/dring/configurationmanager_interface.h
+++ b/src/dring/configurationmanager_interface.h
@@ -50,6 +50,7 @@ void setAccountActive(const std::string& accountID, bool active);
 std::map<std::string, std::string> getAccountTemplate(const std::string& accountType);
 std::string addAccount(const std::map<std::string, std::string>& details);
 bool exportOnRing(const std::string& accountID, const std::string& password);
+bool exportToFile(const std::string& accountID, const std::string& destinationPath);
 bool revokeDevice(const std::string& accountID, const std::string& password, const std::string& deviceID);
 std::map<std::string, std::string> getKnownRingDevices(const std::string& accountID);
 bool changeAccountPassword(const std::string& accountID, const std::string& password_old, const std::string& password_new);
diff --git a/src/ringdht/ringaccount.cpp b/src/ringdht/ringaccount.cpp
index 6158f43c63..573659388f 100644
--- a/src/ringdht/ringaccount.cpp
+++ b/src/ringdht/ringaccount.cpp
@@ -1052,6 +1052,22 @@ RingAccount::addDevice(const std::string& password)
     });
 }
 
+bool
+RingAccount::exportArchive(const std::string& destinationPath)
+{
+    try {
+        auto sourcePath = fileutils::getFullPath(idPath_, archivePath_);
+        std::ifstream src(sourcePath, std::ios::in | std::ios::binary);
+        if (!src) return false;
+        std::ofstream dst(destinationPath, std::ios::out | std::ios::binary);
+        dst << src.rdbuf();
+    } catch (const std::runtime_error& ex) {
+        RING_ERR("[Account %s] Can't export archive: %s", getAccountID().c_str(), ex.what());
+        return false;
+    }
+    return true;
+}
+
 bool
 RingAccount::revokeDevice(const std::string& password, const std::string& device)
 {
diff --git a/src/ringdht/ringaccount.h b/src/ringdht/ringaccount.h
index 369c2fa590..d5c80a77fa 100644
--- a/src/ringdht/ringaccount.h
+++ b/src/ringdht/ringaccount.h
@@ -300,6 +300,7 @@ class RingAccount : public SIPAccountBase {
 
         /* Devices */
         void addDevice(const std::string& password);
+        bool exportArchive(const std::string& destinationPath);
         bool revokeDevice(const std::string& password, const std::string& device);
         std::map<std::string, std::string> getKnownDevices() const;
 
-- 
GitLab