2009-09-21 10:07:05 +02:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2009 Intel Corporation
|
|
|
|
*
|
|
|
|
* 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) version 3.
|
|
|
|
*
|
|
|
|
* 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 Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
|
|
* 02110-1301 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "CmdlineSyncClient.h"
|
|
|
|
#ifdef USE_GNOME_KEYRING
|
|
|
|
extern "C" {
|
|
|
|
#include <gnome-keyring.h>
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-08-15 18:05:15 +02:00
|
|
|
#ifdef USE_KDE_KWALLET
|
|
|
|
#include <QtCore/QCoreApplication>
|
|
|
|
#include <QtCore/QString>
|
|
|
|
#include <QtCore/QLatin1String>
|
|
|
|
#include <QtCore/QDebug>
|
2011-03-30 18:51:45 +02:00
|
|
|
#include <QtDBus/QDBusConnection>
|
2010-08-15 18:05:15 +02:00
|
|
|
|
|
|
|
#include <KApplication>
|
|
|
|
#include <KAboutData>
|
|
|
|
#include <KCmdLineArgs>
|
|
|
|
|
|
|
|
#include <kwallet.h>
|
|
|
|
#endif
|
|
|
|
|
2009-10-05 14:49:32 +02:00
|
|
|
#include <syncevo/declarations.h>
|
2009-10-02 17:23:53 +02:00
|
|
|
SE_BEGIN_CXX
|
|
|
|
|
2009-09-21 10:07:05 +02:00
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
CmdlineSyncClient::CmdlineSyncClient(const string &server,
|
|
|
|
bool doLogging,
|
|
|
|
bool useKeyring):
|
2009-09-14 21:54:43 +02:00
|
|
|
SyncContext(server, doLogging),
|
2009-09-21 10:07:05 +02:00
|
|
|
m_keyring(useKeyring)
|
|
|
|
{
|
2010-08-15 18:05:15 +02:00
|
|
|
#ifdef USE_KDE_KWALLET
|
|
|
|
//QCoreApplication *app;
|
|
|
|
int argc = 1;
|
|
|
|
static const char *prog = "syncevolution";
|
|
|
|
static char *argv[] = { (char *)&prog, NULL };
|
|
|
|
//if (!qApp) {
|
|
|
|
//new QCoreApplication(argc, argv);
|
|
|
|
//}
|
|
|
|
KAboutData aboutData(// The program name used internally.
|
|
|
|
"syncevolution",
|
|
|
|
// The message catalog name
|
|
|
|
// If null, program name is used instead.
|
|
|
|
0,
|
|
|
|
// A displayable program name string.
|
|
|
|
ki18n("Syncevolution"),
|
|
|
|
// The program version string.
|
|
|
|
"1.0",
|
|
|
|
// Short description of what the app does.
|
|
|
|
ki18n("Lets Akonadi synchronize with a SyncML Peer"),
|
|
|
|
// The license this code is released under
|
|
|
|
KAboutData::License_GPL,
|
|
|
|
// Copyright Statement
|
|
|
|
ki18n("(c) 2010"),
|
|
|
|
// Optional text shown in the About box.
|
|
|
|
// Can contain any information desired.
|
|
|
|
ki18n(""),
|
|
|
|
// The program homepage string.
|
|
|
|
"http://www.syncevolution.org/",
|
|
|
|
// The bug report email address
|
|
|
|
"syncevolution@syncevolution.org");
|
|
|
|
|
|
|
|
KCmdLineArgs::init(argc, argv, &aboutData);
|
|
|
|
if (!kapp) {
|
|
|
|
new KApplication;
|
2011-03-30 18:51:45 +02:00
|
|
|
//To stop KApplication from spawning it's own DBus Service ... Will have to patch KApplication about this
|
|
|
|
QDBusConnection::sessionBus().unregisterService("org.syncevolution.syncevolution-"+QString::number(getpid()));
|
|
|
|
|
2010-08-15 18:05:15 +02:00
|
|
|
}
|
|
|
|
#endif
|
2009-09-21 10:07:05 +02:00
|
|
|
}
|
|
|
|
/**
|
|
|
|
* GNOME keyring distinguishes between empty and unset
|
|
|
|
* password keys. This function returns NULL for an
|
|
|
|
* empty std::string.
|
|
|
|
*/
|
|
|
|
inline const char *passwdStr(const std::string &str)
|
|
|
|
{
|
|
|
|
return str.empty() ? NULL : str.c_str();
|
|
|
|
}
|
|
|
|
|
2010-08-15 18:05:15 +02:00
|
|
|
string CmdlineSyncClient::askPassword(const string &passwordName,
|
|
|
|
const string &descr,
|
|
|
|
const ConfigPasswordKey &key)
|
2009-09-21 10:07:05 +02:00
|
|
|
{
|
|
|
|
string password;
|
2010-08-15 18:05:15 +02:00
|
|
|
|
|
|
|
#ifdef USE_KDE_KWALLET
|
|
|
|
/** here we use server sync url without protocol prefix and
|
|
|
|
* user account name as the key in the keyring */
|
|
|
|
/* Also since the KWallet's API supports only storing (key,passowrd)
|
|
|
|
* or Map<QString,QString> , the former is used */
|
|
|
|
bool isKde = true;
|
|
|
|
|
|
|
|
#ifdef USE_GNOME_KEYRING
|
|
|
|
//When Both GNOME KEYRING and KWALLET are available, Check if this is a KDE Session
|
|
|
|
//and Call KWallet if it is. else pick Gnome Keyring by default
|
2011-04-15 08:39:48 +02:00
|
|
|
if (!getenv("KDE_FULL_SESSION")) {
|
2010-08-15 18:05:15 +02:00
|
|
|
isKde = false;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (isKde && m_keyring) {
|
|
|
|
QString walletPassword;
|
|
|
|
const QString walletKey = QString::fromStdString(key.user + ',' +
|
|
|
|
key.domain + ',' + key.server + ',' + key.object + ',' +
|
|
|
|
key.protocol + ',' + key.authtype + ',') + QString::number(key.port);
|
|
|
|
|
|
|
|
const QString wallet_name = KWallet::Wallet::NetworkWallet();
|
|
|
|
//QString folder = QString::fromUtf8("Syncevolution");
|
|
|
|
const QLatin1String folder("Syncevolution");
|
|
|
|
|
|
|
|
if (!KWallet::Wallet::keyDoesNotExist(wallet_name, folder, walletKey)){
|
|
|
|
KWallet::Wallet *wallet = KWallet::Wallet::openWallet(wallet_name, -1, KWallet::Wallet::Synchronous);
|
|
|
|
|
|
|
|
if (wallet && wallet->setFolder(folder) &&
|
|
|
|
wallet->readPassword(walletKey, walletPassword) == 0) {
|
|
|
|
return walletPassword.toStdString();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-09-21 10:07:05 +02:00
|
|
|
#ifdef USE_GNOME_KEYRING
|
|
|
|
/** here we use server sync url without protocol prefix and
|
|
|
|
* user account name as the key in the keyring */
|
|
|
|
if(m_keyring) {
|
|
|
|
/* It is possible to let CmdlineSyncClient decide which of fields in ConfigPasswordKey it would use
|
|
|
|
* but currently only use passed key instead */
|
|
|
|
GnomeKeyringResult result;
|
|
|
|
GList* list;
|
|
|
|
|
|
|
|
result = gnome_keyring_find_network_password_sync(passwdStr(key.user),
|
|
|
|
passwdStr(key.domain),
|
|
|
|
passwdStr(key.server),
|
|
|
|
passwdStr(key.object),
|
|
|
|
passwdStr(key.protocol),
|
|
|
|
passwdStr(key.authtype),
|
|
|
|
key.port,
|
|
|
|
&list);
|
|
|
|
|
2010-08-15 18:05:15 +02:00
|
|
|
// if find password stored in gnome keyring
|
2009-09-21 10:07:05 +02:00
|
|
|
if(result == GNOME_KEYRING_RESULT_OK && list && list->data ) {
|
|
|
|
GnomeKeyringNetworkPasswordData *key_data;
|
|
|
|
key_data = (GnomeKeyringNetworkPasswordData*)list->data;
|
|
|
|
password = key_data->password;
|
|
|
|
gnome_keyring_network_password_list_free(list);
|
|
|
|
return password;
|
|
|
|
}
|
2010-08-15 18:05:15 +02:00
|
|
|
}
|
2009-09-21 10:07:05 +02:00
|
|
|
//if not found, then ask user to interactively input password
|
|
|
|
#endif
|
2010-08-15 18:05:15 +02:00
|
|
|
|
|
|
|
/** if not built with secrets support, directly ask user to
|
2009-09-21 10:07:05 +02:00
|
|
|
* input password */
|
2009-10-05 14:49:32 +02:00
|
|
|
password = SyncContext::askPassword(passwordName, descr, key);
|
2009-09-21 10:07:05 +02:00
|
|
|
return password;
|
|
|
|
}
|
|
|
|
|
2010-08-15 18:05:15 +02:00
|
|
|
bool CmdlineSyncClient::savePassword(const string &passwordName,
|
|
|
|
const string &password,
|
2009-09-21 10:07:05 +02:00
|
|
|
const ConfigPasswordKey &key)
|
|
|
|
{
|
2010-08-15 18:05:15 +02:00
|
|
|
#ifdef USE_KDE_KWALLET
|
|
|
|
bool isKde = true;
|
|
|
|
|
|
|
|
#ifdef USE_GNOME_KEYRING
|
|
|
|
// When both GNOME KEYRING and KWALLET are available, check if
|
|
|
|
// this is a KDE Session and call
|
2011-03-30 18:51:45 +02:00
|
|
|
if (getenv("KDE_FULL_SESSION")) {
|
2010-08-15 18:05:15 +02:00
|
|
|
isKde = false;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (m_keyring && isKde) {
|
|
|
|
/* It is possible to let CmdlineSyncClient decide which of fields in ConfigPasswordKey it would use
|
|
|
|
* but currently only use passed key instead */
|
|
|
|
|
|
|
|
// write password to keyring
|
|
|
|
const QString walletKey = QString::fromStdString(key.user + ',' +
|
|
|
|
key.domain + ',' + key.server + ',' + key.object + ',' +
|
|
|
|
key.protocol + ',' + key.authtype + ',')+ QString::number(key.port);
|
|
|
|
const QString walletPassword = QString::fromStdString(password);
|
|
|
|
|
|
|
|
bool write_success = false;
|
|
|
|
const QString wallet_name = KWallet::Wallet::NetworkWallet();
|
|
|
|
const QLatin1String folder("Syncevolution");
|
|
|
|
KWallet::Wallet *wallet = KWallet::Wallet::openWallet(wallet_name, -1,
|
|
|
|
KWallet::Wallet::Synchronous);
|
|
|
|
if (wallet) {
|
|
|
|
if (!wallet->hasFolder(folder)) {
|
|
|
|
wallet->createFolder(folder);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (wallet->setFolder(folder) &&
|
|
|
|
wallet->writePassword(walletKey, walletPassword) == 0) {
|
|
|
|
write_success = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!write_success) {
|
|
|
|
SyncContext::throwError("Try to save " + passwordName + " in KWallet but got an error. ");
|
|
|
|
}
|
|
|
|
return write_success;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_keyring) {
|
|
|
|
SyncContext::throwError("Try to save " + passwordName +
|
|
|
|
" in KWallet but get an error. "
|
|
|
|
"This syncevolution binary was compiled without support for storing "
|
|
|
|
"passwords in a Wallet. Either store passwords in your configuration "
|
|
|
|
"files or enter them interactively on each program run.\n");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-09-21 10:07:05 +02:00
|
|
|
#ifdef USE_GNOME_KEYRING
|
|
|
|
if(m_keyring) {
|
|
|
|
/* It is possible to let CmdlineSyncClient decide which of fields in ConfigPasswordKey it would use
|
|
|
|
* but currently only use passed key instead */
|
|
|
|
guint32 itemId;
|
|
|
|
GnomeKeyringResult result;
|
|
|
|
// write password to keyring
|
|
|
|
result = gnome_keyring_set_network_password_sync(NULL,
|
|
|
|
passwdStr(key.user),
|
|
|
|
passwdStr(key.domain),
|
|
|
|
passwdStr(key.server),
|
|
|
|
passwdStr(key.object),
|
|
|
|
passwdStr(key.protocol),
|
|
|
|
passwdStr(key.authtype),
|
|
|
|
key.port,
|
|
|
|
password.c_str(),
|
|
|
|
&itemId);
|
|
|
|
/* if set operation is failed */
|
|
|
|
if(result != GNOME_KEYRING_RESULT_OK) {
|
2009-09-25 04:21:03 +02:00
|
|
|
#ifdef GNOME_KEYRING_220
|
2009-10-05 14:49:32 +02:00
|
|
|
SyncContext::throwError("Try to save " + passwordName + " in gnome-keyring but get an error. " + gnome_keyring_result_to_message(result));
|
2009-09-25 04:21:03 +02:00
|
|
|
#else
|
|
|
|
/** if gnome-keyring version is below 2.20, it doesn't support 'gnome_keyring_result_to_message'. */
|
|
|
|
stringstream value;
|
|
|
|
value << (int)result;
|
2009-10-05 14:49:32 +02:00
|
|
|
SyncContext::throwError("Try to save " + passwordName + " in gnome-keyring but get an error. The gnome-keyring error code is " + value.str() + ".");
|
2009-09-25 04:21:03 +02:00
|
|
|
#endif
|
2009-09-21 10:07:05 +02:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2010-08-15 18:05:15 +02:00
|
|
|
#endif
|
|
|
|
|
2009-09-21 10:07:05 +02:00
|
|
|
/* if no keyring support, raise the error */
|
|
|
|
if(m_keyring) {
|
2009-10-05 14:49:32 +02:00
|
|
|
SyncContext::throwError("Try to save " + passwordName + " in gnome-keyring but get an error. " +
|
2009-09-21 10:07:05 +02:00
|
|
|
"This syncevolution binary was compiled without support for storing "
|
|
|
|
"passwords in a keyring. Either store passwords in your configuration "
|
|
|
|
"files or enter them interactively on each program run.\n");
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2009-10-02 17:23:53 +02:00
|
|
|
|
|
|
|
SE_END_CXX
|