2008-01-25 01:36:40 -05:00
/*
* libretroshare / src / pqi : p3cfgmgr . cc
*
* 3 P / PQI network interface for RetroShare .
*
* Copyright 2007 - 2008 by Robert Fernie .
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation .
*
* 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
* Library General Public License for more details .
*
* You should have received a copy of the GNU Library General Public
* License along with this library ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307
* USA .
*
* Please report all bugs and problems to " retroshare@lunamutt.com " .
*
*/
2009-03-29 09:58:28 -04:00
# include "util/rsdir.h"
2009-03-20 19:37:06 -04:00
# include "rsiface/rspeers.h"
2008-01-25 01:36:40 -05:00
# include "pqi/p3cfgmgr.h"
2010-01-13 15:56:55 -05:00
# include "pqi/authssl.h"
2008-01-25 01:36:40 -05:00
# include "pqi/pqibin.h"
2009-05-08 20:19:54 -04:00
# include "pqi/pqistore.h"
2009-03-26 09:24:27 -04:00
# include "pqi/pqinotify.h"
# include <errno.h>
2010-05-21 16:49:48 -04:00
# include <util/rsdiscspace.h>
2008-01-25 01:36:40 -05:00
2008-02-07 11:18:34 -05:00
# include "serialiser/rsconfigitems.h"
2008-01-25 01:36:40 -05:00
2010-03-28 16:46:45 -04:00
/*
2010-03-10 09:08:52 -05:00
# define CONFIG_DEBUG 1
2010-03-28 16:46:45 -04:00
*/
2010-03-12 10:37:48 -05:00
# define BACKEDUP_SAVE
2010-03-03 13:20:24 -05:00
2008-01-25 01:36:40 -05:00
2010-01-13 15:56:55 -05:00
p3ConfigMgr : : p3ConfigMgr ( std : : string dir , std : : string fname , std : : string signame )
: basedir ( dir ) , metafname ( fname ) , metasigfname ( signame ) ,
2008-02-07 11:18:34 -05:00
mConfigSaveActive ( true )
2008-01-25 01:36:40 -05:00
{
}
void p3ConfigMgr : : tick ( )
{
bool toSave = false ;
2008-02-07 11:18:34 -05:00
{
RsStackMutex stack ( cfgMtx ) ; /***** LOCK STACK MUTEX ****/
2008-01-25 01:36:40 -05:00
/* iterate through and check if any have changed */
std : : map < uint32_t , pqiConfig * > : : iterator it ;
for ( it = configs . begin ( ) ; it ! = configs . end ( ) ; it + + )
{
2008-02-07 11:18:34 -05:00
if ( it - > second - > HasConfigChanged ( 0 ) )
2008-01-25 01:36:40 -05:00
{
2008-02-07 11:18:34 -05:00
2010-04-15 07:26:44 -04:00
# ifdef CONFIG_DEBUG
2008-02-07 11:18:34 -05:00
std : : cerr < < " p3ConfigMgr::tick() Config Changed - Element: " ;
std : : cerr < < it - > first ;
std : : cerr < < std : : endl ;
# endif
2008-01-25 01:36:40 -05:00
toSave = true ;
}
}
2008-02-07 11:18:34 -05:00
/* disable saving before exit */
if ( ! mConfigSaveActive )
{
toSave = false ;
}
}
2008-01-25 01:36:40 -05:00
if ( toSave )
{
saveConfiguration ( ) ;
}
}
void p3ConfigMgr : : saveConfiguration ( )
{
2010-05-21 16:49:48 -04:00
if ( ! RsDiscSpace : : checkForDiscSpace ( RS_CONFIG_DIRECTORY ) )
return ;
2008-02-07 11:18:34 -05:00
RsStackMutex stack ( cfgMtx ) ; /***** LOCK STACK MUTEX ****/
2010-04-15 07:26:44 -04:00
# ifdef CONFIG_DEBUG
2008-02-07 11:18:34 -05:00
std : : cerr < < " p3ConfigMgr::saveConfiguration() " ;
std : : cerr < < std : : endl ;
# endif
RsConfigKeyValueSet * item = new RsConfigKeyValueSet ( ) ;
2008-01-25 01:36:40 -05:00
std : : map < uint32_t , pqiConfig * > : : iterator it ;
for ( it = configs . begin ( ) ; it ! = configs . end ( ) ; it + + )
{
2008-02-07 11:18:34 -05:00
if ( it - > second - > HasConfigChanged ( 1 ) )
2008-01-25 01:36:40 -05:00
{
2010-04-15 07:26:44 -04:00
# ifdef CONFIG_DEBUG
2008-02-07 11:18:34 -05:00
std : : cerr < < " p3ConfigMgr::saveConfiguration() Saving Element: " ;
std : : cerr < < it - > first ;
std : : cerr < < std : : endl ;
# endif
it - > second - > saveConfiguration ( ) ;
2008-01-25 01:36:40 -05:00
}
/* save metaconfig */
2008-02-07 11:18:34 -05:00
2010-04-15 07:26:44 -04:00
# ifdef CONFIG_DEBUG
2008-02-07 11:18:34 -05:00
std : : cerr < < " p3ConfigMgr::saveConfiguration() Element: " ;
std : : cerr < < it - > first < < " Hash: " < < it - > second - > Hash ( ) ;
std : : cerr < < std : : endl ;
# endif
2008-02-08 07:39:40 -05:00
if ( it - > second - > Hash ( ) = = " " )
{
/* skip if no hash */
continue ;
}
2008-02-07 11:18:34 -05:00
RsTlvKeyValue kv ;
{
std : : ostringstream out ;
out < < it - > first ;
kv . key = out . str ( ) ;
}
kv . value = it - > second - > Hash ( ) ;
item - > tlvkvs . pairs . push_back ( kv ) ;
2008-01-25 01:36:40 -05:00
}
2010-04-15 07:26:44 -04:00
# ifdef CONFIG_DEBUG
2008-02-07 11:18:34 -05:00
std : : cerr < < " p3ConfigMgr::saveConfiguration() Complete MetaConfigItem: " ;
std : : cerr < < std : : endl ;
item - > print ( std : : cerr , 20 ) ;
# endif
2008-03-23 15:11:36 -04:00
/* construct filename */
2010-03-10 09:08:52 -05:00
std : : string fname = basedir ;
std : : string sign_fname = basedir ;
std : : string fname_backup , sign_fname_backup ; // back up files
2010-03-03 13:20:24 -05:00
2008-03-23 15:11:36 -04:00
if ( basedir ! = " " )
{
2010-03-10 09:08:52 -05:00
fname + = " / " ;
sign_fname + = " / " ;
2008-03-23 15:11:36 -04:00
}
2010-03-10 09:08:52 -05:00
fname + = metafname ;
sign_fname + = metasigfname ;
fname_backup = fname + " .tmp " ;
sign_fname_backup = sign_fname + " .tmp " ;
2008-02-07 11:18:34 -05:00
/* Write the data to a stream */
2008-02-08 07:39:40 -05:00
uint32_t bioflags = BIN_FLAGS_WRITEABLE ;
2010-03-10 09:08:52 -05:00
BinMemInterface * configbio = new BinMemInterface ( 1000 , bioflags ) ;
2008-02-07 11:18:34 -05:00
RsSerialiser * rss = new RsSerialiser ( ) ;
rss - > addSerialType ( new RsGeneralConfigSerialiser ( ) ) ;
2010-03-10 09:08:52 -05:00
pqistore store ( rss , " CONFIG " , configbio , BIN_FLAGS_WRITEABLE ) ;
2008-02-07 11:18:34 -05:00
2009-05-12 17:55:50 -04:00
store . SendItem ( item ) ;
2008-02-07 11:18:34 -05:00
2008-02-08 07:39:40 -05:00
/* sign data */
std : : string signature ;
2010-03-10 09:08:52 -05:00
AuthSSL : : getAuthSSL ( ) - > SignData ( configbio - > memptr ( ) , configbio - > memsize ( ) , signature ) ;
/* write signature to configuration */
BinMemInterface * signbio = new BinMemInterface ( signature . c_str ( ) ,
signature . length ( ) , BIN_FLAGS_READABLE ) ;
2008-02-07 11:18:34 -05:00
2010-04-15 07:26:44 -04:00
# ifdef CONFIG_DEBUG
2008-02-08 07:39:40 -05:00
std : : cerr < < " p3ConfigMgr::saveConfiguration() MetaFile Signature: " ;
std : : cerr < < std : : endl ;
std : : cerr < < signature ;
std : : cerr < < std : : endl ;
# endif
2010-03-10 09:08:52 -05:00
// begin two pass save
backedUpFileSave ( fname , fname_backup , sign_fname , sign_fname_backup , configbio , signbio ) ;
delete signbio ;
}
bool p3ConfigMgr : : backedUpFileSave ( const std : : string & fname , const std : : string & fname_backup , const std : : string & sign_fname ,
const std : : string & sign_fname_backup , BinMemInterface * configbio , BinMemInterface * signbio ) {
FILE * file = NULL , * sign = NULL ;
2010-03-28 16:46:45 -04:00
char * config_buff = NULL , * sign_buff = NULL ;
int size_file = 0 , size_sign = 0 ;
2010-03-10 09:08:52 -05:00
// begin two pass saving by writing to back up file instead
if ( ! configbio - > writetofile ( fname_backup . c_str ( ) ) | | ! signbio - > writetofile ( sign_fname_backup . c_str ( ) ) )
2008-02-08 07:39:40 -05:00
{
2010-03-10 09:08:52 -05:00
# ifdef CONFIG_DEBUG
std : : cerr < < " p3ConfigMgr::backedupFileSave() Failed write to Backup MetaFiles " < < fname_backup
< < " and " < < sign_fname_backup ;
2008-02-08 07:39:40 -05:00
std : : cerr < < std : : endl ;
# endif
2010-03-12 10:37:48 -05:00
return false ;
2008-02-08 07:39:40 -05:00
}
2008-01-25 01:36:40 -05:00
2010-03-10 09:08:52 -05:00
# ifdef CONFIG_DEBUG
std : : cerr < < " p3Config::backedUpFileSave() Save file and keeps a back up " < < std : : endl ;
# endif
2008-01-25 01:36:40 -05:00
2010-03-10 09:08:52 -05:00
// open file from which to collect buffer
file = fopen ( fname . c_str ( ) , " rb " ) ;
sign = fopen ( sign_fname . c_str ( ) , " rb " ) ;
2008-02-08 07:39:40 -05:00
2010-03-12 10:37:48 -05:00
// if failed then create files
2010-03-10 09:08:52 -05:00
if ( ( file = = NULL ) | | ( sign = = NULL ) ) {
# ifdef CONFIG_DEBUG
std : : cerr < < " p3Config::backedUpFileSave() failed to open meta files " < < fname < < std : : endl ;
2010-03-03 13:20:24 -05:00
# endif
2010-03-10 09:08:52 -05:00
2010-03-12 10:37:48 -05:00
file = fopen ( fname . c_str ( ) , " wb " ) ;
sign = fopen ( sign_fname . c_str ( ) , " wb " ) ;
2010-03-10 09:08:52 -05:00
if ( ( file = = NULL ) | | ( sign = = NULL ) ) {
std : : cerr < < " p3Config::backedUpFileSave() failed to open backup meta files " < < fname_backup < < std : : endl ;
return false ;
}
2010-03-03 13:20:24 -05:00
}
2010-03-10 09:08:52 -05:00
//determine file size
fseek ( file , 0L , SEEK_END ) ;
size_file = ftell ( file ) ;
fseek ( file , 0L , SEEK_SET ) ;
2010-03-03 13:20:24 -05:00
2010-03-10 09:08:52 -05:00
fseek ( sign , 0L , SEEK_END ) ;
size_sign = ftell ( sign ) ;
fseek ( sign , 0L , SEEK_SET ) ;
2010-03-12 10:37:48 -05:00
if ( ( size_file ) > 0 & & ( size_sign > 0 ) ) {
//read this into a buffer
config_buff = new char [ size_file ] ;
fread ( config_buff , 1 , size_file , file ) ;
2010-03-10 09:08:52 -05:00
2010-03-12 10:37:48 -05:00
//read this into a buffer
sign_buff = new char [ size_sign ] ;
fread ( sign_buff , 1 , size_sign , sign ) ;
}
fclose ( file ) ;
2010-03-10 09:08:52 -05:00
fclose ( sign ) ;
// rename back-up to current file
if ( ! RsDirUtil : : renameFile ( fname_backup , fname ) | | ! RsDirUtil : : renameFile ( sign_fname_backup , sign_fname ) ) {
2010-03-12 10:37:48 -05:00
# ifdef CONFIG_DEBUG
2010-03-10 09:08:52 -05:00
std : : cerr < < " p3Config::backedUpFileSave() Failed to rename backup meta files: " < < std : : endl
< < fname_backup < < " to " < < fname < < std : : endl
< < sign_fname_backup < < " to " < < sign_fname < < std : : endl ;
2010-03-12 10:37:48 -05:00
# endif
return true ;
2010-03-10 09:08:52 -05:00
}
2010-03-12 10:37:48 -05:00
if ( ( size_file ) > 0 & & ( size_sign > 0 ) ) {
2010-03-10 09:08:52 -05:00
2010-03-12 10:37:48 -05:00
// now write actual back-up file
file = fopen ( fname_backup . c_str ( ) , " wb " ) ;
sign = fopen ( sign_fname_backup . c_str ( ) , " wb " ) ;
if ( ( file = = NULL ) | | ( sign = = NULL ) ) {
2010-03-03 13:20:24 -05:00
# ifdef CONFIG_DEBUG
2010-03-12 10:37:48 -05:00
std : : cerr < < " p3Config::backedUpFileSave() fopen failed for file: " < < fname_backup < < std : : endl ;
2008-02-08 07:39:40 -05:00
# endif
2010-03-12 10:37:48 -05:00
return true ;
}
2008-02-07 11:18:34 -05:00
2010-05-28 10:00:35 -04:00
if ( size_file ! = fwrite ( config_buff , 1 , size_file , file ) )
getPqiNotify ( ) - > AddSysMessage ( 0 , RS_SYS_WARNING , " Write error " , " Error while writing backup configuration file " + fname_backup + " \n Is your disc full or out of quota ? " ) ;
if ( size_sign ! = fwrite ( sign_buff , 1 , size_sign , sign ) )
getPqiNotify ( ) - > AddSysMessage ( 0 , RS_SYS_WARNING , " Write error " , " Error while writing main signature file " + sign_fname_backup + " \n Is your disc full or out of quota ? " ) ;
2010-03-12 10:37:48 -05:00
fclose ( file ) ;
fclose ( sign ) ;
2010-03-03 13:20:24 -05:00
2010-03-10 09:08:52 -05:00
# ifdef CONFIG_DEBUG
2010-03-12 10:37:48 -05:00
std : : cerr < < " p3Config::backedUpFileSave() finished backed up save. " < < std : : endl ;
2010-03-10 09:08:52 -05:00
# endif
2008-02-07 11:18:34 -05:00
2010-03-12 10:37:48 -05:00
delete [ ] config_buff ;
delete [ ] sign_buff ;
}
2010-03-10 09:08:52 -05:00
return true ;
2008-01-25 01:36:40 -05:00
}
void p3ConfigMgr : : loadConfiguration ( )
{
2008-02-07 11:18:34 -05:00
RsStackMutex stack ( cfgMtx ) ; /***** LOCK STACK MUTEX ****/
2008-01-25 01:36:40 -05:00
2010-04-15 07:26:44 -04:00
# ifdef CONFIG_DEBUG
2008-02-07 11:18:34 -05:00
std : : cerr < < " p3ConfigMgr::loadConfiguration() " ;
std : : cerr < < std : : endl ;
# endif
2008-03-23 15:11:36 -04:00
/* construct filename */
2010-03-10 09:08:52 -05:00
std : : string fname = basedir ;
std : : string sign_fname = basedir ;
std : : string fname_backup , sign_fname_backup ;
2010-03-03 13:20:24 -05:00
2008-03-23 15:11:36 -04:00
if ( basedir ! = " " )
{
2010-03-10 09:08:52 -05:00
fname + = " / " ;
sign_fname + = " / " ;
2008-03-23 15:11:36 -04:00
}
2010-03-03 13:20:24 -05:00
2010-03-10 09:08:52 -05:00
fname + = metafname ;
sign_fname + = metasigfname ;
2008-03-23 15:11:36 -04:00
2010-03-03 13:20:24 -05:00
// temporary files
2010-03-10 09:08:52 -05:00
fname_backup = fname + " .tmp " ;
sign_fname_backup = sign_fname + " .tmp " ;
2009-10-27 16:39:47 -04:00
2010-03-03 13:20:24 -05:00
BinMemInterface * membio = new BinMemInterface ( 1000 , BIN_FLAGS_READABLE ) ;
2008-02-08 07:39:40 -05:00
2010-03-10 09:08:52 -05:00
// Will attempt to get signature first from meta file then if that fails try temporary meta files, these will correspond to temp configs
bool pass = getSignAttempt ( fname , sign_fname , membio ) ;
2008-02-08 07:39:40 -05:00
2010-03-03 13:20:24 -05:00
// if first attempt fails then try and temporary files
if ( ! pass ) {
2008-02-08 07:39:40 -05:00
2010-03-03 13:20:24 -05:00
# ifdef CONFIG_DEBUG
std : : cerr < < " \n p3ConfigMgr::loadConfiguration(): Trying to load METACONFIG item and METASIGN with temporary files " ;
2008-02-08 07:39:40 -05:00
std : : cerr < < std : : endl ;
2010-03-03 13:20:24 -05:00
# endif
2008-02-08 07:39:40 -05:00
2010-03-10 09:08:52 -05:00
pass = getSignAttempt ( fname_backup , sign_fname_backup , membio ) ;
2008-02-08 07:39:40 -05:00
2010-03-03 13:20:24 -05:00
if ( ! pass ) {
# ifdef CONFIG_DEBUG
std : : cerr < < " \n p3ConfigMgr::loadConfiguration(): failed to load METACONFIG item and METASIGN " ;
std : : cerr < < std : : endl ;
# endif
2008-02-08 07:39:40 -05:00
2010-03-03 13:20:24 -05:00
return ;
}
2008-02-08 07:39:40 -05:00
}
2010-03-03 13:20:24 -05:00
membio - > fseek ( 0 ) ; /* go back to start of file */
2008-02-07 11:18:34 -05:00
RsSerialiser * rss = new RsSerialiser ( ) ;
rss - > addSerialType ( new RsGeneralConfigSerialiser ( ) ) ;
2009-05-13 16:18:03 -04:00
pqistore stream ( rss , " CONFIG " , membio , BIN_FLAGS_READABLE ) ;
2008-02-07 11:18:34 -05:00
RsItem * rsitem = stream . GetItem ( ) ;
RsConfigKeyValueSet * item = dynamic_cast < RsConfigKeyValueSet * > ( rsitem ) ;
if ( ! item )
{
delete rsitem ;
return ;
}
2008-01-25 01:36:40 -05:00
2010-04-15 07:26:44 -04:00
# ifdef CONFIG_DEBUG
2008-02-07 11:18:34 -05:00
std : : cerr < < " p3ConfigMgr::loadConfiguration() Loaded MetaConfigItem: " ;
std : : cerr < < std : : endl ;
item - > print ( std : : cerr , 20 ) ;
# endif
/* extract info from KeyValueSet */
std : : list < RsTlvKeyValue > : : iterator it ;
for ( it = item - > tlvkvs . pairs . begin ( ) ; it ! = item - > tlvkvs . pairs . end ( ) ; it + + )
{
/* find the configuration */
uint32_t confId = atoi ( it - > key . c_str ( ) ) ;
std : : string hashin = it - > value ;
2008-06-16 16:37:48 -04:00
/*********************** HACK TO CHANGE CACHE CONFIG ID *********
* REMOVE IN A MONTH OR TWO
*/
if ( confId = = CONFIG_TYPE_CACHE_OLDID )
{
confId = CONFIG_TYPE_CACHE ;
}
/*********************** HACK TO CHANGE CACHE CONFIG ID *********/
2008-02-07 11:18:34 -05:00
std : : map < uint32_t , pqiConfig * > : : iterator cit ;
cit = configs . find ( confId ) ;
if ( cit ! = configs . end ( ) )
{
2010-04-15 07:26:44 -04:00
# ifdef CONFIG_DEBUG
2008-02-07 11:18:34 -05:00
std : : cerr < < " p3ConfigMgr::loadConfiguration() Element: " ;
std : : cerr < < confId < < " Hash: " < < hashin ;
std : : cerr < < std : : endl ;
# endif
( cit - > second ) - > loadConfiguration ( hashin ) ;
/* force config to NOT CHANGED */
cit - > second - > HasConfigChanged ( 0 ) ;
cit - > second - > HasConfigChanged ( 1 ) ;
}
}
2008-04-02 09:55:45 -04:00
delete item ;
2008-02-07 11:18:34 -05:00
2010-04-15 07:26:44 -04:00
# ifdef CONFIG_DEBUG
2008-02-07 11:18:34 -05:00
std : : cerr < < " p3ConfigMgr::loadConfiguration() Done! " ;
std : : cerr < < std : : endl ;
# endif
2008-01-25 01:36:40 -05:00
}
2010-03-03 13:20:24 -05:00
bool p3ConfigMgr : : getSignAttempt ( std : : string & metaConfigFname , std : : string & metaSignFname , BinMemInterface * membio ) {
# ifdef CONFIG_DEBUG
std : : cerr < < " p3ConfigMgr::getSignAttempt() metaConfigFname : " < < metaConfigFname ;
std : : cerr < < std : : endl ;
std : : cerr < < " p3ConfigMgr::getSignAttempt() metaSignFname : " < < metaSignFname ;
std : : cerr < < std : : endl ;
# endif
/* read signature */
BinMemInterface * signbio = new BinMemInterface ( 1000 , BIN_FLAGS_READABLE ) ;
if ( ! signbio - > readfromfile ( metaSignFname . c_str ( ) ) )
{
# ifdef CONFIG_DEBUG
std : : cerr < < " p3ConfigMgr::getSignAttempt() Failed to Load MetaSignFile " ;
std : : cerr < < std : : endl ;
# endif
/* HACK to load the old one (with the wrong directory)
* THIS SHOULD BE REMOVED IN A COUPLE OF VERSIONS . . . .
* ONLY HERE TO CORRECT BAD MISTAKE IN EARLIER VERSIONS .
*/
metaSignFname = metasigfname ;
metaConfigFname = metafname ;
if ( ! signbio - > readfromfile ( metaSignFname . c_str ( ) ) )
{
# ifdef CONFIG_DEBUG
std : : cerr < < " p3ConfigMgr::getSignAttempt() HACK: Failed to Load ALT MetaSignFile " ;
std : : cerr < < std : : endl ;
# endif
}
else
{
# ifdef CONFIG_DEBUG
std : : cerr < < " p3ConfigMgr::getSignAttempt() HACK: Loaded ALT MetaSignFile " ;
std : : cerr < < std : : endl ;
# endif
}
}
std : : string oldsignature ( ( char * ) signbio - > memptr ( ) , signbio - > memsize ( ) ) ;
delete signbio ;
if ( ! membio - > readfromfile ( metaConfigFname . c_str ( ) ) )
{
# ifdef CONFIG_DEBUG
std : : cerr < < " p3ConfigMgr::getSignAttempt() Failed to Load MetaFile " ;
std : : cerr < < std : : endl ;
# endif
// delete membio;
// return ;
}
/* get signature */
std : : string signature ;
AuthSSL : : getAuthSSL ( ) - > SignData ( membio - > memptr ( ) , membio - > memsize ( ) , signature ) ;
# ifdef CONFIG_DEBUG
std : : cerr < < " p3ConfigMgr::getSignAttempt() New MetaFile Signature: " ;
std : : cerr < < std : : endl ;
std : : cerr < < signature ;
std : : cerr < < std : : endl ;
# endif
# ifdef CONFIG_DEBUG
std : : cerr < < " p3ConfigMgr::getSignAttempt() Orig MetaFile Signature: " ;
std : : cerr < < std : : endl ;
std : : cerr < < oldsignature ;
std : : cerr < < std : : endl ;
# endif
if ( signature ! = oldsignature )
{
/* Failed */
# ifdef CONFIG_DEBUG
std : : cerr < < " p3ConfigMgr::getSignAttempt() Signature Check Failed " ;
std : : cerr < < std : : endl ;
# endif
return false ;
}
# ifdef CONFIG_DEBUG
std : : cerr < < " p3ConfigMgr::getSignAttempt() Signature Check Passed! " ;
std : : cerr < < std : : endl ;
# endif
return true ;
}
2008-02-07 11:18:34 -05:00
void p3ConfigMgr : : addConfiguration ( std : : string file , pqiConfig * conf )
2008-01-25 01:36:40 -05:00
{
2008-02-07 11:18:34 -05:00
RsStackMutex stack ( cfgMtx ) ; /***** LOCK STACK MUTEX ****/
/* construct filename */
std : : string filename = basedir ;
if ( basedir ! = " " )
{
filename + = " / " ;
}
filename + = file ;
conf - > setFilename ( filename ) ;
configs [ conf - > Type ( ) ] = conf ;
2008-01-25 01:36:40 -05:00
}
2008-02-07 11:18:34 -05:00
void p3ConfigMgr : : completeConfiguration ( )
{
saveConfiguration ( ) ;
RsStackMutex stack ( cfgMtx ) ; /***** LOCK STACK MUTEX ****/
mConfigSaveActive = false ;
}
p3Config : : p3Config ( uint32_t t )
: pqiConfig ( t )
2008-01-25 01:36:40 -05:00
{
return ;
}
2010-03-03 13:20:24 -05:00
2008-02-07 11:18:34 -05:00
bool p3Config : : loadConfiguration ( std : : string & loadHash )
2008-01-25 01:36:40 -05:00
{
2010-03-12 10:37:48 -05:00
bool pass = false ;
2010-03-10 09:08:52 -05:00
std : : string cfg_fname = Filename ( ) ;
std : : string cfg_fname_backup = cfg_fname + " .tmp " ;
2010-03-03 13:20:24 -05:00
std : : string hashstr ;
std : : list < RsItem * > load ;
# ifdef CONFIG_DEBUG
2010-03-10 09:08:52 -05:00
std : : string success_fname = cfg_fname ;
std : : cerr < < " p3Config::loadConfiguration(): Attempting to load configuration file " < < cfg_fname < < std : : endl ;
2010-03-03 13:20:24 -05:00
# endif
2010-03-12 10:37:48 -05:00
pass = getHashAttempt ( loadHash , hashstr , cfg_fname , load ) ;
2010-03-03 13:20:24 -05:00
if ( ! pass ) {
2010-03-10 11:19:28 -05:00
load . clear ( ) ;
2010-03-10 09:08:52 -05:00
pass = getHashAttempt ( loadHash , hashstr , cfg_fname_backup , load ) ;
2010-03-03 13:20:24 -05:00
# ifdef CONFIG_DEBUG
2010-03-10 09:08:52 -05:00
std : : cerr < < " p3Config::loadConfiguration() ERROR: Failed to get Hash from " < < success_fname < < std : : endl ;
success_fname = cfg_fname_backup ;
2010-03-03 13:20:24 -05:00
# endif
if ( ! pass ) {
# ifdef CONFIG_DEBUG
2010-03-10 09:08:52 -05:00
std : : cerr < < " p3Config::loadConfiguration() ERROR: Failed to get Hash from " < < success_fname < < std : : endl ;
2010-03-03 13:20:24 -05:00
# endif
2010-03-10 09:08:52 -05:00
return false ;
2010-03-03 13:20:24 -05:00
}
}
# ifdef CONFIG_DEBUG
std : : cerr < < " p3Config::loadConfiguration(): SUCCESS: configuration file loaded " < < success_fname < < std : : endl ;
# endif
setHash ( hashstr ) ;
return loadList ( load ) ;
}
2010-03-10 09:08:52 -05:00
bool p3Config : : getHashAttempt ( const std : : string & loadHash , std : : string & hashstr , const std : : string & cfg_fname ,
2010-03-03 13:20:24 -05:00
std : : list < RsItem * > & load ) {
std : : list < RsItem * > : : iterator it ;
2008-02-07 11:18:34 -05:00
uint32_t bioflags = BIN_FLAGS_HASH_DATA | BIN_FLAGS_READABLE ;
uint32_t stream_flags = BIN_FLAGS_READABLE ;
2008-01-25 01:36:40 -05:00
2010-03-10 09:08:52 -05:00
BinInterface * bio = new BinFileInterface ( cfg_fname . c_str ( ) , bioflags ) ;
2009-05-12 17:55:50 -04:00
pqistore stream ( setupSerialiser ( ) , " CONFIG " , bio , stream_flags ) ;
2008-01-25 01:36:40 -05:00
RsItem * item = NULL ;
2008-02-07 11:18:34 -05:00
while ( NULL ! = ( item = stream . GetItem ( ) ) )
2008-01-25 01:36:40 -05:00
{
2010-04-15 07:26:44 -04:00
# ifdef CONFIG_DEBUG
2008-02-07 11:18:34 -05:00
std : : cerr < < " p3Config::loadConfiguration() loaded item: " ;
std : : cerr < < std : : endl ;
item - > print ( std : : cerr , 0 ) ;
std : : cerr < < std : : endl ;
# endif
2008-01-25 01:36:40 -05:00
load . push_back ( item ) ;
}
2008-02-07 11:18:34 -05:00
2010-04-15 07:26:44 -04:00
# ifdef CONFIG_DEBUG
2008-02-07 11:18:34 -05:00
std : : cerr < < " p3Config::loadConfiguration() loaded " < < load . size ( ) ;
2010-03-10 09:08:52 -05:00
std : : cerr < < " Elements from File: " < < cfg_fname ;
2008-02-07 11:18:34 -05:00
std : : cerr < < std : : endl ;
# endif
2008-01-25 01:36:40 -05:00
/* check hash */
2010-03-03 13:20:24 -05:00
hashstr = bio - > gethash ( ) ;
2008-01-25 01:36:40 -05:00
2010-03-03 13:20:24 -05:00
// if hash then atmpt load with temporary file
2008-01-25 01:36:40 -05:00
if ( hashstr ! = loadHash )
{
2008-02-07 11:18:34 -05:00
2010-04-15 07:26:44 -04:00
# ifdef CONFIG_DEBUG
2008-02-07 11:18:34 -05:00
std : : cerr < < " p3Config::loadConfiguration() ERROR: Hash != MATCHloaded " ;
std : : cerr < < std : : endl ;
# endif
2008-01-25 01:36:40 -05:00
/* bad load */
for ( it = load . begin ( ) ; it ! = load . end ( ) ; it + + )
{
delete ( * it ) ;
}
2008-02-08 07:39:40 -05:00
setHash ( " " ) ;
2010-03-03 13:20:24 -05:00
2008-01-25 01:36:40 -05:00
return false ;
}
2010-03-03 13:20:24 -05:00
//delete bio;
return true ;
2008-01-25 01:36:40 -05:00
}
2008-02-07 11:18:34 -05:00
bool p3Config : : saveConfiguration ( )
2008-01-25 01:36:40 -05:00
{
2008-02-07 11:18:34 -05:00
bool cleanup = true ;
std : : list < RsItem * > toSave = saveList ( cleanup ) ;
2010-03-03 13:20:24 -05:00
2010-03-10 09:08:52 -05:00
std : : string cfg_fname = Filename ( ) ; // get configuration file name
std : : string cfg_fname_backup = Filename ( ) + " .tmp " ; // backup file for two pass save
2008-02-07 11:18:34 -05:00
2010-04-15 07:26:44 -04:00
# ifdef CONFIG_DEBUG
2010-03-10 09:08:52 -05:00
std : : cerr < < " Writting p3config file " < < cfg_fname < < std : : endl ;
2010-02-07 16:28:40 -05:00
std : : cerr < < " p3Config::saveConfiguration() toSave " < < toSave . size ( ) ;
2010-03-10 09:08:52 -05:00
std : : cerr < < " Elements to File: " < < cfg_fname ;
2008-02-07 11:18:34 -05:00
std : : cerr < < std : : endl ;
# endif
2008-01-25 01:36:40 -05:00
2010-03-10 09:08:52 -05:00
// saves current config and keeps back-up (old configuration)
2010-03-12 10:37:48 -05:00
if ( ! backedUpFileSave ( cfg_fname , cfg_fname_backup , toSave , cleanup ) ) {
# ifdef CONFIG_DEBUG
std : : cerr < < " p3Config::saveConfiguration(): Failed to save file " < < std : : endl ;
# endif
2010-03-10 09:08:52 -05:00
return false ;
2010-03-12 10:37:48 -05:00
}
2010-03-10 09:08:52 -05:00
2010-03-11 09:14:55 -05:00
saveDone ( ) ; // callback to inherited class to unlock any Mutexes protecting saveList() data
2010-03-10 09:08:52 -05:00
return true ;
}
bool p3Config : : backedUpFileSave ( const std : : string & cfg_fname , const std : : string & cfg_fname_backup , std : : list < RsItem * > & itemList ,
bool cleanup ) {
2008-02-07 11:18:34 -05:00
uint32_t bioflags = BIN_FLAGS_HASH_DATA | BIN_FLAGS_WRITEABLE ;
2010-03-12 10:37:48 -05:00
uint32_t stream_flags = BIN_FLAGS_WRITEABLE ;
bool written = true ;
FILE * cfg_file = NULL ;
2010-03-28 16:46:45 -04:00
char * buff = NULL ;
2010-03-12 10:37:48 -05:00
int size_file = 0 ;
2009-03-20 19:37:06 -04:00
2010-03-12 10:37:48 -05:00
if ( ! cleanup )
2008-02-07 11:18:34 -05:00
stream_flags | = BIN_FLAGS_NO_DELETE ;
2010-03-12 10:37:48 -05:00
2010-03-10 09:08:52 -05:00
BinInterface * bio = new BinFileInterface ( cfg_fname_backup . c_str ( ) , bioflags ) ;
2009-05-12 17:55:50 -04:00
pqistore * stream = new pqistore ( setupSerialiser ( ) , " CONFIG " , bio , stream_flags ) ;
2009-03-20 19:37:06 -04:00
2008-01-25 01:36:40 -05:00
std : : list < RsItem * > : : iterator it ;
2009-03-20 19:37:06 -04:00
2010-03-10 09:08:52 -05:00
for ( it = itemList . begin ( ) ; it ! = itemList . end ( ) ; it + + )
2008-01-25 01:36:40 -05:00
{
2010-03-12 10:37:48 -05:00
# ifdef CONFIG_DEBUG
std : : cerr < < " p3Config::backedUpFileSave() save item: " ;
2008-02-07 11:18:34 -05:00
std : : cerr < < std : : endl ;
( * it ) - > print ( std : : cerr , 0 ) ;
std : : cerr < < std : : endl ;
# endif
2009-03-20 19:37:06 -04:00
written = written & & stream - > SendItem ( * it ) ;
2010-03-12 10:37:48 -05:00
# ifdef CONFIG_DEBUG
std : : cerr < < " p3Config::backedUpFileSave() saved " ;
# endif
2008-01-25 01:36:40 -05:00
}
/* store the hash */
2008-02-07 11:18:34 -05:00
setHash ( bio - > gethash ( ) ) ;
2009-03-20 19:37:06 -04:00
2010-03-10 09:08:52 -05:00
// bio is taken care of in stream's destructor
delete stream ;
2010-03-03 13:20:24 -05:00
2010-03-12 10:37:48 -05:00
# ifdef CONFIG_DEBUG
std : : cerr < < " p3Config::backedUpFileSave() Save file and keeps a back up " < < std : : endl ;
# endif
2009-03-20 19:37:06 -04:00
2010-03-10 09:08:52 -05:00
// open file from which to collect buffer
cfg_file = fopen ( cfg_fname . c_str ( ) , " rb " ) ;
2009-03-20 19:37:06 -04:00
2010-03-12 10:37:48 -05:00
// if it fails to open, create file,but back-up file will now be empty
2010-03-10 09:08:52 -05:00
if ( cfg_file = = NULL ) {
# ifdef CONFIG_DEBUG
std : : cerr < < " p3Config::backedUpFileSave() fopen failed for file: " < < cfg_fname < < std : : endl ;
# endif
2010-03-12 10:37:48 -05:00
cfg_file = fopen ( cfg_fname . c_str ( ) , " wb " ) ;
if ( cfg_file = = NULL )
2010-06-05 15:16:39 -04:00
{
2010-03-12 10:37:48 -05:00
std : : cerr < < " p3Config::backedUpFileSave() fopen failed for file: " < < cfg_fname < < std : : endl ;
2010-06-05 15:16:39 -04:00
return false ;
}
2010-03-10 09:08:52 -05:00
}
2010-03-03 13:20:24 -05:00
2010-03-10 09:08:52 -05:00
//determine file size
fseek ( cfg_file , 0L , SEEK_END ) ;
size_file = ftell ( cfg_file ) ;
2010-06-05 15:16:39 -04:00
if ( size_file < 0 ) // ftell returns -1 when fails
{
fclose ( cfg_file ) ;
size_file = 0 ;
}
2010-03-10 09:08:52 -05:00
fseek ( cfg_file , 0L , SEEK_SET ) ;
2010-03-03 13:20:24 -05:00
2010-03-12 10:37:48 -05:00
# ifdef CONFIG_DEBUG
std : : cerr < < " p3Config::backedUpFileSave(): Size of file: " < < size_file < < std : : endl ;
# endif
// no point continuing, empty files all have same hash
if ( size_file > 0 ) {
//read this into a data buffer
buff = new char [ size_file ] ;
fread ( buff , 1 , size_file , cfg_file ) ;
}
2010-03-10 09:08:52 -05:00
fclose ( cfg_file ) ;
2010-03-03 13:20:24 -05:00
2010-03-12 10:37:48 -05:00
// rename back-up to current file, if this fails should return false hash's will not match at startup
2010-03-10 09:08:52 -05:00
if ( ! RsDirUtil : : renameFile ( cfg_fname_backup , cfg_fname ) ) {
2010-03-12 10:37:48 -05:00
# ifdef CONFIG_DEBUG
2010-03-10 09:08:52 -05:00
std : : cerr < < " p3Config::backedUpFileSave() Failed to rename file " < < cfg_fname_backup < < " to "
< < cfg_fname < < std : : endl ;
2010-03-12 10:37:48 -05:00
# endif
written & = false ; // at least one file save should be successful
2010-03-10 09:08:52 -05:00
}
2010-03-03 13:20:24 -05:00
2010-05-28 10:00:35 -04:00
if ( size_file > 0 )
{
2010-03-03 13:20:24 -05:00
2010-03-12 10:37:48 -05:00
// now write actual back-up file
cfg_file = fopen ( cfg_fname_backup . c_str ( ) , " wb " ) ;
if ( cfg_file = = NULL ) {
2010-03-10 09:08:52 -05:00
# ifdef CONFIG_DEBUG
2010-03-12 10:37:48 -05:00
std : : cerr < < " p3Config::backedUpFileSave() fopen failed for file: " < < cfg_fname_backup < < std : : endl ;
2010-03-10 09:08:52 -05:00
# endif
2010-03-12 10:37:48 -05:00
}
2010-05-28 10:00:35 -04:00
if ( size_file ! = fwrite ( buff , 1 , size_file , cfg_file ) )
2010-05-29 09:17:09 -04:00
{
2010-05-28 10:00:35 -04:00
getPqiNotify ( ) - > AddSysMessage ( 0 , RS_SYS_WARNING , " Write error " , " Error while writing backup configuration file " + cfg_fname_backup + " \n Is your disc full or out of quota ? " ) ;
2010-05-29 09:17:09 -04:00
fclose ( cfg_file ) ;
return false ;
}
2010-05-28 10:00:35 -04:00
2010-03-12 10:37:48 -05:00
fclose ( cfg_file ) ;
# ifdef CONFIG_DEBUG
std : : cerr < < " p3Config::backedUpFileSave() finished backed up save. " < < std : : endl ;
# endif
delete [ ] buff ;
written | = true ; // either backup or current file should have been saved
2010-03-10 09:08:52 -05:00
}
2010-03-03 13:20:24 -05:00
2010-03-10 09:08:52 -05:00
# ifdef CONFIG_DEBUG
2010-03-12 10:37:48 -05:00
std : : cerr < < " p3Config::backedUpFileSave() finished backed up save. " < < std : : endl ;
2010-03-10 09:08:52 -05:00
# endif
2010-03-03 13:20:24 -05:00
2010-03-12 10:37:48 -05:00
return written ;
2008-01-25 01:36:40 -05:00
}
/**************************** CONFIGURATION CLASSES ********************/
p3GeneralConfig : : p3GeneralConfig ( )
2008-02-07 11:18:34 -05:00
: p3Config ( CONFIG_TYPE_GENERAL )
2008-01-25 01:36:40 -05:00
{
return ;
}
// General Configuration System
std : : string p3GeneralConfig : : getSetting ( std : : string opt )
{
2010-04-15 07:26:44 -04:00
# ifdef CONFIG_DEBUG
2008-02-07 11:18:34 -05:00
std : : cerr < < " p3GeneralConfig::getSetting( " < < opt < < " ) " ;
std : : cerr < < std : : endl ;
# endif
RsStackMutex stack ( cfgMtx ) ; /***** LOCK STACK MUTEX ****/
2008-01-25 01:36:40 -05:00
/* extract from config */
std : : map < std : : string , std : : string > : : iterator it ;
if ( settings . end ( ) = = ( it = settings . find ( opt ) ) )
{
std : : string nullstring ;
return nullstring ;
}
return it - > second ;
}
void p3GeneralConfig : : setSetting ( std : : string opt , std : : string val )
{
2010-04-15 07:26:44 -04:00
# ifdef CONFIG_DEBUG
2008-02-07 11:18:34 -05:00
std : : cerr < < " p3GeneralConfig::setSetting( " < < opt < < " = " < < val < < " ) " ;
std : : cerr < < std : : endl ;
# endif
{
RsStackMutex stack ( cfgMtx ) ; /***** LOCK STACK MUTEX ****/
2008-01-25 01:36:40 -05:00
/* extract from config */
std : : map < std : : string , std : : string > : : iterator it ;
if ( settings . end ( ) ! = ( it = settings . find ( opt ) ) )
{
if ( it - > second = = val )
{
/* no change */
return ;
}
}
settings [ opt ] = val ;
2008-02-07 11:18:34 -05:00
}
/* outside mutex */
IndicateConfigChanged ( ) ;
2008-01-25 01:36:40 -05:00
return ;
}
RsSerialiser * p3GeneralConfig : : setupSerialiser ( )
{
2008-02-07 11:18:34 -05:00
RsSerialiser * rss = new RsSerialiser ( ) ;
rss - > addSerialType ( new RsGeneralConfigSerialiser ( ) ) ;
2008-01-25 01:36:40 -05:00
return rss ;
}
std : : list < RsItem * > p3GeneralConfig : : saveList ( bool & cleanup )
{
2008-02-07 11:18:34 -05:00
RsStackMutex stack ( cfgMtx ) ; /***** LOCK STACK MUTEX ****/
2010-04-15 07:26:44 -04:00
# ifdef CONFIG_DEBUG
2008-02-07 11:18:34 -05:00
std : : cerr < < " p3GeneralConfig::saveList() KV sets: " < < settings . size ( ) ;
std : : cerr < < std : : endl ;
# endif
cleanup = true ;
2008-01-25 01:36:40 -05:00
std : : list < RsItem * > savelist ;
2008-02-07 11:18:34 -05:00
RsConfigKeyValueSet * item = new RsConfigKeyValueSet ( ) ;
2008-01-25 01:36:40 -05:00
std : : map < std : : string , std : : string > : : iterator it ;
for ( it = settings . begin ( ) ; it ! = settings . end ( ) ; it + + )
{
2008-02-07 11:18:34 -05:00
RsTlvKeyValue kv ;
kv . key = it - > first ;
kv . value = it - > second ;
item - > tlvkvs . pairs . push_back ( kv ) ;
2008-01-25 01:36:40 -05:00
2008-02-07 11:18:34 -05:00
/* make sure we don't overload it */
if ( item - > tlvkvs . TlvSize ( ) > 4000 )
{
savelist . push_back ( item ) ;
item = new RsConfigKeyValueSet ( ) ;
}
}
2008-01-25 01:36:40 -05:00
2008-02-07 11:18:34 -05:00
if ( item - > tlvkvs . pairs . size ( ) > 0 )
{
savelist . push_back ( item ) ;
2008-01-25 01:36:40 -05:00
}
2008-02-07 11:18:34 -05:00
2008-01-25 01:36:40 -05:00
return savelist ;
}
2010-04-15 07:26:44 -04:00
2008-01-25 01:36:40 -05:00
bool p3GeneralConfig : : loadList ( std : : list < RsItem * > load )
{
2010-04-15 07:26:44 -04:00
# ifdef CONFIG_DEBUG
2008-02-07 11:18:34 -05:00
std : : cerr < < " p3GeneralConfig::loadList() count: " < < load . size ( ) ;
std : : cerr < < std : : endl ;
# endif
RsStackMutex stack ( cfgMtx ) ; /***** LOCK STACK MUTEX ****/
2008-01-25 01:36:40 -05:00
/* add into settings */
2008-02-07 11:18:34 -05:00
RsConfigKeyValueSet * item = NULL ;
std : : list < RsItem * > : : iterator it ;
std : : list < RsTlvKeyValue > : : iterator kit ;
for ( it = load . begin ( ) ; it ! = load . end ( ) ; )
{
item = dynamic_cast < RsConfigKeyValueSet * > ( * it ) ;
if ( item )
{
2010-04-15 07:26:44 -04:00
for ( kit = item - > tlvkvs . pairs . begin ( ) ;
2008-02-07 11:18:34 -05:00
kit ! = item - > tlvkvs . pairs . end ( ) ; kit + + )
{
settings [ kit - > key ] = kit - > value ;
}
}
/* cleanup */
delete ( * it ) ;
it = load . erase ( it ) ;
}
return true ;
}
/**** MUTEX NOTE:
2010-04-15 07:26:44 -04:00
* have protected all , but think that
2008-02-07 11:18:34 -05:00
* only the Indication and hash really need it
*/
pqiConfig : : pqiConfig ( uint32_t t )
: ConfInd ( 2 ) , type ( t )
{
return ;
}
pqiConfig : : ~ pqiConfig ( )
2010-04-15 07:26:44 -04:00
{
return ;
2008-02-07 11:18:34 -05:00
}
2010-04-15 07:26:44 -04:00
uint32_t pqiConfig : : Type ( )
{
2008-02-07 11:18:34 -05:00
RsStackMutex stack ( cfgMtx ) ; /***** LOCK STACK MUTEX ****/
2010-04-15 07:26:44 -04:00
return type ;
2008-02-07 11:18:34 -05:00
}
2010-04-15 07:26:44 -04:00
std : : string pqiConfig : : Filename ( )
{
2008-02-07 11:18:34 -05:00
RsStackMutex stack ( cfgMtx ) ; /***** LOCK STACK MUTEX ****/
2010-04-15 07:26:44 -04:00
return filename ;
}
2008-02-07 11:18:34 -05:00
2010-04-15 07:26:44 -04:00
std : : string pqiConfig : : Hash ( )
{
2008-02-07 11:18:34 -05:00
RsStackMutex stack ( cfgMtx ) ; /***** LOCK STACK MUTEX ****/
2010-04-15 07:26:44 -04:00
return hash ;
2008-02-07 11:18:34 -05:00
}
2010-04-15 07:26:44 -04:00
void pqiConfig : : IndicateConfigChanged ( )
{
2008-02-07 11:18:34 -05:00
RsStackMutex stack ( cfgMtx ) ; /***** LOCK STACK MUTEX ****/
2010-04-15 07:26:44 -04:00
ConfInd . IndicateChanged ( ) ;
2008-02-07 11:18:34 -05:00
}
2010-04-15 07:26:44 -04:00
bool pqiConfig : : HasConfigChanged ( uint16_t idx )
{
2008-02-07 11:18:34 -05:00
RsStackMutex stack ( cfgMtx ) ; /***** LOCK STACK MUTEX ****/
2010-04-15 07:26:44 -04:00
return ConfInd . Changed ( idx ) ;
2008-02-07 11:18:34 -05:00
}
2010-04-15 07:26:44 -04:00
void pqiConfig : : setFilename ( std : : string name )
{
2008-02-07 11:18:34 -05:00
RsStackMutex stack ( cfgMtx ) ; /***** LOCK STACK MUTEX ****/
2010-04-15 07:26:44 -04:00
filename = name ;
2008-02-07 11:18:34 -05:00
}
2008-01-25 01:36:40 -05:00
2010-04-15 07:26:44 -04:00
void pqiConfig : : setHash ( std : : string h )
{
2008-02-07 11:18:34 -05:00
RsStackMutex stack ( cfgMtx ) ; /***** LOCK STACK MUTEX ****/
2010-04-15 07:26:44 -04:00
hash = h ;
2008-01-25 01:36:40 -05:00
}