You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdenetworkmanager/knetworkmanager-0.9/src/knetworkmanager-storage.cpp

635 lines
18 KiB

/***************************************************************************
*
* knetworkmanager-storage.cpp - A NetworkManager frontend for KDE
*
* Copyright (C) 2005, 2006 Novell, Inc.
*
* Author: Helmut Schaa <hschaa@suse.de>, <Helmut.Schaa@gmx.de>
* Author: Timothy Pearson <kb9vqf@pearsoncomputing.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
**************************************************************************/
#include <tqtimer.h>
#include <kglobal.h>
#include <kconfig.h>
#include <kstaticdeleter.h>
#include <kdebug.h>
#include "knetworkmanager-storage.h"
#include "knetworkmanager-connection_store.h"
#include "knetworkmanager-wireless_connection.h"
#include "knetworkmanager-wired_connection.h"
#include "knetworkmanager-cdma_connection.h"
#include "knetworkmanager-gsm_connection.h"
#include "knetworkmanager-vpn_connection.h"
#include "knetworkmanager-connection.h"
#include "knetworkmanager-connection_setting.h"
#include "xmlmarshaller.h"
#include "knetworkmanager-connection_setting_info.h"
#include "knetworkmanager-connection_setting_wired.h"
#include "knetworkmanager-connection_setting_wireless.h"
#include "knetworkmanager-connection_setting_wireless_security.h"
#include "knetworkmanager-connection_setting_ipv4.h"
using namespace ConnectionSettings;
static KStaticDeleter<Storage> sd2;
// private stuff
class StoragePrivate
{
public:
StoragePrivate() {};
~StoragePrivate() {};
static Storage* _instance;
};
Storage* StoragePrivate::_instance = NULL;
Storage*
Storage::getInstance()
{
if (StoragePrivate::_instance)
return StoragePrivate::_instance;
return sd2.setObject(StoragePrivate::_instance, new Storage());
}
Storage::Storage()
{
d = new StoragePrivate();
// defer the connection init a bit
TQTimer::singleShot(0, this, TQT_SLOT(slotInit()));
}
Storage::~Storage()
{
delete d;
}
void
Storage::slotInit()
{
ConnectionStore* cstore = ConnectionStore::getInstance();
// we want to get notified whenever a new connection is created, edited or deleted
connect(cstore, TQT_SIGNAL(signalConnectionAdded(ConnectionSettings::Connection*)), this, TQT_SLOT(slotConnectionAdded(ConnectionSettings::Connection*)));
connect(cstore, TQT_SIGNAL(signalConnectionRemoved(ConnectionSettings::Connection*)), this, TQT_SLOT(slotConnectionRemoved(ConnectionSettings::Connection*)));
}
void
Storage::slotConnectionAdded(Connection* con)
{
// connection added, save it
saveConnection(con);
KGlobal::config()->sync();
}
void
Storage::slotConnectionRemoved(Connection* con)
{
// find the appropriate connection and delete it from the storage
deleteConnection(con);
KGlobal::config()->sync();
}
Connection*
Storage::createConnectionByType(const TQString& cType)
{
// TODO: use a factory class here
if (cType == NM_SETTING_WIRELESS_SETTING_NAME)
return new WirelessConnection();
else if (cType == NM_SETTING_WIRED_SETTING_NAME)
return new WiredConnection();
else if(cType == NM_SETTING_CDMA_SETTING_NAME)
return new CDMAConnection();
else if(cType == NM_SETTING_GSM_SETTING_NAME)
return new GSMConnection();
else if (cType == NM_SETTING_VPN_SETTING_NAME)
return new VPNConnection();
else
return NULL;
}
void
Storage::restoreConnections()
{
kdDebug() << k_funcinfo << endl;
// let's read all connections from the config-file and add them to the connection-store
ConnectionStore* store = ConnectionStore::getInstance();
TQStringList groups = KGlobal::config()->groupList();
const TQStringList::Iterator end = groups.end();
for ( TQStringList::Iterator it = groups.begin(); it != end; ++it )
{
if ( !(*it).startsWith( "Connection_" ) )
continue;
// restore that connection
Connection* conn = NULL;
if ( (conn = restoreConnection(*it)) != NULL)
{
// add the connection to the store
store->addConnection(conn);
}
}
}
Connection*
Storage::restoreConnection(const TQString& grpname)
{
Connection* conn = NULL;
kdDebug() << k_funcinfo << " " << grpname << endl;
// we have a connection to restore
KConfigGroup grp( KGlobal::config(), grpname);
TQString id = grp.readEntry("Id");
TQString cType = grp.readEntry("Type");
// ID is needed!
if (id.isEmpty() || cType.isEmpty())
return NULL;
// create a new connection object by its type
conn = createConnectionByType(cType);
// check if the connection was successfully created
if (!conn)
return NULL;
// set the connection ID
conn->setID(id);
// restore all appropriate settings
TQStringList settings = grp.readListEntry("Settings");
for (TQStringList::ConstIterator it = settings.begin(); it != settings.end(); ++it)
{
if ( !restoreSetting(conn, *it) )
{
// setting could not be restored -> Error
kdDebug() << " Connection " << id.ascii() << " could not be restored." << endl;
kdError() << k_funcinfo << " Connection " << id << " could not be restored." << endl;
delete conn;
conn = NULL;
return NULL;
}
}
// restore all appropriate secrets
TQStringList secrets = grp.readListEntry("Secrets");
for (TQStringList::ConstIterator it = secrets.begin(); it != secrets.end(); ++it)
{
if ( !restoreSecrets(conn, *it) )
{
// setting could not be restored -> Error
kdDebug() << " Connection " << id.ascii() << " could not be restored." << endl;
kdError() << k_funcinfo << " Connection " << id << " could not be restored." << endl;
delete conn;
conn = NULL;
return NULL;
}
}
return conn;
}
bool
Storage::restoreSetting(Connection* conn, const TQString& setting_grp_name)
{
kdDebug() << k_funcinfo << " " << setting_grp_name << endl;
kdDebug() << "restore setting: " << setting_grp_name.ascii() << endl;
KConfigGroup setting_grp(KGlobal::config(), setting_grp_name);
TQMap<TQString, TQString> config_map = KGlobal::config()->entryMap(setting_grp_name);
TQString type = setting_grp.readEntry("Type");
// get the appropriate setting from the connection
ConnectionSetting* setting = conn->getSetting(type);
if (!setting)
{
kdWarning() << k_funcinfo << "Connection " << conn->getID() << ": Setting " << type << " could not be restored" << endl;
return false;
}
// read the SettingsMap from kconfig
SettingsMap map;
for(TQMap<TQString, TQString>::ConstIterator it = config_map.begin(); it != config_map.end(); ++it)
{
if (!it.key().startsWith("Value_"))
continue;
TQString key = it.key();
// get the original name
key.replace("Value_", "");
TQString xmldata = it.data();
TQT_DBusData dbusdata = XMLMarshaller::toTQT_DBusData(xmldata);
map.insert(key, dbusdata);
}
// restore the setting from the generated map
setting->fromMap(map);
return true;
}
bool
Storage::restoreSecrets(Connection* conn, const TQString& secrets_grp_name)
{
kdDebug() << k_funcinfo << " " << secrets_grp_name << endl;
kdDebug() << "restore secret: " << secrets_grp_name.ascii() << endl;
KConfigGroup secrets_grp(KGlobal::config(), secrets_grp_name);
TQMap<TQString, TQString> config_map = KGlobal::config()->entryMap(secrets_grp_name);
TQString type = secrets_grp.readEntry("Type");
// get the appropriate setting from the connection
ConnectionSetting* setting = conn->getSetting(type);
if (!setting)
{
kdWarning() << k_funcinfo << "Connection " << conn->getID() << ": Secrets for setting " << type << " could not be restored" << endl;
return false;
}
// read the SettingsMap from kconfig
SettingsMap map;
for(TQMap<TQString, TQString>::ConstIterator it = config_map.begin(); it != config_map.end(); ++it)
{
if (!it.key().startsWith("Value_"))
continue;
TQString key = it.key();
// get the original name
key.replace("Value_", "");
TQString xmldata = it.data();
TQT_DBusData dbusdata = XMLMarshaller::toTQT_DBusData(xmldata);
map.insert(key, dbusdata);
}
// restore the setting from the generated map
setting->fromSecretsMap(map);
return true;
}
bool
Storage::restoreVPNSecrets(Connection* conn, const TQString& secrets_grp_name)
{
kdDebug() << k_funcinfo << " " << secrets_grp_name << endl;
kdDebug() << "restore secret: " << secrets_grp_name.ascii() << endl;
KConfigGroup secrets_grp(KGlobal::config(), secrets_grp_name);
TQMap<TQString, TQString> config_map = KGlobal::config()->entryMap(secrets_grp_name);
TQString type = secrets_grp.readEntry("Type");
// get the appropriate setting from the connection
ConnectionSetting* setting = conn->getSetting(type);
if (!setting)
{
kdWarning() << k_funcinfo << "Connection " << conn->getID() << ": Secrets for setting " << type << " could not be restored" << endl;
return false;
}
// read the SettingsMap from kconfig
SettingsMap map;
for(TQMap<TQString, TQString>::ConstIterator it = config_map.begin(); it != config_map.end(); ++it)
{
if (!it.key().startsWith("Value_"))
continue;
TQString key = it.key();
// get the original name
key.replace("Value_", "");
TQString xmldata = it.data();
TQT_DBusData dbusdata = XMLMarshaller::toTQT_DBusData(xmldata);
map.insert(key, dbusdata);
}
// restore the setting from the generated map
setting->fromSecretsMap(map);
return true;
}
void
Storage::saveConnections()
{
kdDebug() << k_funcinfo << endl;
kdDebug() << "Storage::saveConnections" << endl;
printf("Storage::saveConnections\n\r");
// write all connections we get from the connection-store to disk
ConnectionStore* store = ConnectionStore::getInstance();
TQValueList<ConnectionSettings::Connection*> connections = store->getConnections();
for (TQValueList<ConnectionSettings::Connection*>::ConstIterator it = connections.begin(); it != connections.end(); ++it)
{
// save this connection
saveConnection(*it);
}
KGlobal::config()->sync();
}
bool
Storage::saveConnection(Connection* conn)
{
KConfig* config = KGlobal::config();
TQString id = conn->getID();
TQString cType = conn->getType();
kdDebug() << k_funcinfo << " <" << id << ">" << endl;
kdDebug() << "Storage::saveConnection " << id.ascii() << endl;
// connections without id are evil
if (id.isEmpty() || cType.isEmpty())
return false;
// let's get the config group for this connection
KConfigGroup grp(config, TQString("Connection_%1").arg(id));
TQStringList settings_grps;
TQStringList secrets_grps;
// save the connections settings to the configfile
if (saveConnectionSettings(conn, settings_grps, secrets_grps))
{
grp.writeEntry("Type", cType);
grp.writeEntry("Id", id);
// save the list of settings groups
grp.writeEntry("Settings", settings_grps);
grp.writeEntry("Secrets", secrets_grps);
}
return false;
}
bool
Storage::saveConnectionSettings(Connection* conn, TQStringList& settings_grps, TQStringList& secrets_grps)
{
TQString id = conn->getID();
// connections without id are evil
if (id.isEmpty())
return false;
// iterate over all settings
TQValueList<ConnectionSetting*> settings = conn->getSettings();
TQString setting_grp;
TQString secrets_grp;
// save all settings
for (TQValueList<ConnectionSetting*>::ConstIterator it = settings.begin(); it != settings.end(); ++it)
{
if (!saveConnectionSetting(conn, *it, setting_grp))
return false;
if ((*it)->hasSecrets())
{
if (!saveConnectionSecrets(conn, *it, secrets_grp))
return false;
secrets_grps.append(secrets_grp);
}
settings_grps.append(setting_grp);
}
return true;
}
bool
Storage::saveConnectionSetting(Connection* conn, ConnectionSetting* setting, TQString& setting_grp)
{
KConfig* config = KGlobal::config();
TQString id = conn->getID();
TQString type = setting->getType();
kdDebug() << k_funcinfo << " <" << id << "> <" << type << ">" << endl;
// ID is necessary
if (id.isEmpty())
return false;
// get a group for this setting
setting_grp = TQString("ConnectionSetting_%1_%2").arg(id).arg(type);
KConfigGroup grp(config, setting_grp);
// write the type
grp.writeEntry("Type", type);
// write the values
SettingsMap map = setting->toMap();
for (SettingsMap::ConstIterator it = map.begin(); it != map.end(); ++it)
{
kdDebug() << k_funcinfo << " " << TQString("Value_%1").arg(it.key()) << " = " << XMLMarshaller::fromTQT_DBusData( it.data() )<< endl;
grp.writeEntry(TQString("Value_%1").arg(it.key()), XMLMarshaller::fromTQT_DBusData( it.data() ));
}
return true;
}
bool
Storage::saveConnectionSecrets(Connection* conn, ConnectionSetting* setting, TQString& setting_grp)
{
KConfig* config = KGlobal::config();
TQString id = conn->getID();
TQString type = setting->getType();
bool storage_requested;
kdDebug() << k_funcinfo << " <" << id << "> <" << type << ">" << endl;
// ID is necessary
if (id.isEmpty())
return false;
// see if permanent storage was requested by the user
SettingsMap setting_map = setting->toMap();
storage_requested = true;
for (SettingsMap::ConstIterator it = setting_map.begin(); it != setting_map.end(); ++it)
{
if (it.key() == "Commit to disk") {
if (XMLMarshaller::fromTQT_DBusData(it.data()) == TQString("true")) {
storage_requested = true;
}
if (XMLMarshaller::fromTQT_DBusData(it.data()) == TQString("false")) {
storage_requested = false;
}
}
}
printf("Secrets storage requested: %d\n\r", storage_requested);
// get a group for this setting
setting_grp = TQString("ConnectionSecrets_%1_%2").arg(id).arg(type);
KConfigGroup grp(config, setting_grp);
// write the type
grp.writeEntry("Type", type);
// write the values
SettingsMap map = setting->toSecretsMap(false);
for (SettingsMap::ConstIterator it = map.begin(); it != map.end(); ++it)
{
kdDebug() << k_funcinfo << " " << TQString("Value_%1").arg(it.key()) << " = " << XMLMarshaller::fromTQT_DBusData( it.data() )<< endl;
if (storage_requested == true) {
grp.writeEntry(TQString("Value_%1").arg(it.key()), XMLMarshaller::fromTQT_DBusData( it.data() ));
}
else {
grp.writeEntry(TQString("Value_%1").arg(it.key()), TQString("") );
}
}
return true;
}
bool
Storage::hasSecretsStored(Connection* connection)
{
TQString id = connection->getID();
// ID is necessary
if (id.isEmpty())
return false;
TQValueList<ConnectionSetting*> settings = connection->getSettings();
for (TQValueList<ConnectionSetting*>::Iterator it = settings.begin(); it != settings.end(); ++it)
{
if (hasSecretsStored(connection, *it))
return true;
}
return false;
}
bool
Storage::hasSecretsStored(Connection* connection, ConnectionSetting* setting)
{
TQString id = connection->getID();
TQString type = setting->getType();
kdDebug() << "Storage::hasSecretsStored" << endl;
// ID is necessary
if (id.isEmpty())
return false;
// get a group for this setting
TQString setting_grp_name = TQString("ConnectionSecrets_%1_%2").arg(id).arg(type);
TQMap<TQString, TQString> config_map = KGlobal::config()->entryMap(setting_grp_name);
return !(config_map.isEmpty());
}
bool
Storage::restoreAllSecrets(Connection* connection)
{
TQString id = connection->getID();
bool retval = true;
if (id.isEmpty())
return false;
TQValueList<ConnectionSetting*> settings = connection->getSettings();
for (TQValueList<ConnectionSetting*>::Iterator it = settings.begin(); it != settings.end(); ++it)
{
if (hasSecretsStored(connection, *it))
if (!restoreSecrets(connection, *it))
retval = false;
}
return retval;
}
bool
Storage::restoreSecrets(Connection* connection, ConnectionSetting* setting)
{
TQString id = connection->getID();
TQString type = setting->getType();
kdDebug() << "Storage::restoreSecrets" << endl;
// ID is necessary
if (id.isEmpty())
return false;
// get a group for this setting
TQString setting_grp = TQString("ConnectionSecrets_%1_%2").arg(id).arg(type);
// restore the setting
return restoreSecrets(connection, setting_grp);
}
bool
Storage::restoreVPNSecrets(Connection* connection, ConnectionSetting* setting)
{
TQString id = connection->getID();
TQString type = setting->getType();
printf("Storage::restoreVPNSecrets\n\r");
kdDebug() << "Storage::restoreVPNSecrets" << endl;
// ID is necessary
if (id.isEmpty())
return false;
// get a group for this setting
TQString setting_grp = TQString("ConnectionSecrets_%1_%2").arg(id).arg(type);
// restore the setting
return restoreVPNSecrets(connection, setting_grp);
}
bool
Storage::deleteConnection(Connection* conn)
{
KConfig* config = KGlobal::config();
TQString id = conn->getID();
TQString cType = conn->getType();
kdDebug() << k_funcinfo << " <" << id << ">" << endl;
kdDebug() << "Storage::deleteConnection " << id.ascii() << endl;
// connections without id are evil
if (id.isEmpty() || cType.isEmpty())
return false;
// let's get the config group for this connection
KConfigGroup grp(config, TQString("Connection_%1").arg(id));
// delete all associated settings
TQStringList settings = grp.readListEntry("Settings");
for (TQStringList::ConstIterator it = settings.begin(); it != settings.end(); ++it)
{
KConfigGroup setting(config, *it);
setting.deleteGroup();
}
// delete all associated secrets
TQStringList secrets = grp.readListEntry("Secrets");
for (TQStringList::ConstIterator it = secrets.begin(); it != secrets.end(); ++it)
{
KConfigGroup setting(config, *it);
setting.deleteGroup();
}
grp.deleteGroup();
return true;
}
#include "knetworkmanager-storage.moc"