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.
635 lines
18 KiB
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"
|