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.
1688 lines
44 KiB
1688 lines
44 KiB
/*
|
|
* kioskrun.cpp
|
|
*
|
|
* Copyright (C) 2004 Waldo Bastian <bastian@kde.org>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* 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 "kioskrun.h"
|
|
|
|
#include "config.h"
|
|
|
|
#include <assert.h>
|
|
#include <stdlib.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
|
|
#include <tqdir.h>
|
|
#include <tqfile.h>
|
|
|
|
#include <kapplication.h>
|
|
#include <kcmdlineargs.h>
|
|
#include <kconfig.h>
|
|
#include <kdebug.h>
|
|
#include <klocale.h>
|
|
#include <kmessagebox.h>
|
|
#include <kprocess.h>
|
|
#include <ksavefile.h>
|
|
#include <ksimpleconfig.h>
|
|
#include <kstandarddirs.h>
|
|
#include <kurl.h>
|
|
#include <kuser.h>
|
|
|
|
#include "kiosksync.h"
|
|
|
|
#include <kio/netaccess.h>
|
|
#define NETACCESS KIO::NetAccess
|
|
|
|
#undef DEBUG_ENTRIES
|
|
|
|
KioskRun *KioskRun::s_self = 0;
|
|
|
|
KioskRun::KioskRun( TQObject* parent, const char* name)
|
|
: TQObject(parent, name), m_dcopClient(0), m_instance(0), m_localKdercConfig(0)
|
|
{
|
|
m_noRestrictions = false;
|
|
m_forceSycocaUpdate = false;
|
|
s_self = this;
|
|
m_saveConfigCache.setAutoDelete(true);
|
|
m_immutableStatusCache.setAutoDelete(true);
|
|
m_homeDir = TQDir::homeDirPath()+"/.kde-test";
|
|
KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
|
|
m_kderc = TQFile::decodeName(args->getOption("kderc"));
|
|
m_isRoot = (getuid() == 0);
|
|
}
|
|
|
|
KioskRun::~KioskRun()
|
|
{
|
|
shutdownRuntimeEnv();
|
|
s_self = 0;
|
|
}
|
|
|
|
void
|
|
KioskRun::setUser(const TQString &user)
|
|
{
|
|
if (m_user == user) return;
|
|
|
|
shutdownRuntimeEnv();
|
|
shutdownConfigEnv();
|
|
m_user = user;
|
|
}
|
|
|
|
static void filterDupes(TQStringList &list)
|
|
{
|
|
TQStringList tmp;
|
|
for(TQStringList::ConstIterator it = list.begin();
|
|
it != list.end(); ++it)
|
|
{
|
|
if (!tmp.contains(*it))
|
|
tmp.append(*it);
|
|
}
|
|
list = tmp;
|
|
}
|
|
|
|
void
|
|
KioskRun::setKdeDirs(const TQStringList &dirs)
|
|
{
|
|
if (m_kdeDirs == dirs) return;
|
|
|
|
shutdownRuntimeEnv();
|
|
shutdownConfigEnv();
|
|
m_kdeDirs = dirs;
|
|
TQStringList xdgDataDirs = TQStringList::split(':', TQFile::decodeName(getenv("XDG_DATA_DIRS")));
|
|
if (xdgDataDirs.isEmpty())
|
|
{
|
|
xdgDataDirs = TQStringList::split(':', KGlobal::dirs()->kfsstnd_prefixes());
|
|
xdgDataDirs.pop_front();
|
|
for(TQStringList::Iterator it = xdgDataDirs.begin();
|
|
it != xdgDataDirs.end(); ++it)
|
|
{
|
|
*it += "share";
|
|
}
|
|
xdgDataDirs << "/usr/local/share" << "/usr/share";
|
|
}
|
|
|
|
m_xdgDataDirs.clear();
|
|
for(TQStringList::ConstIterator it = dirs.begin();
|
|
it != dirs.end(); ++it)
|
|
{
|
|
m_xdgDataDirs.append(*it+"/share");
|
|
}
|
|
m_xdgDataDirs += xdgDataDirs;
|
|
filterDupes(m_xdgDataDirs);
|
|
|
|
TQStringList xdgConfigDirs = TQStringList::split(':', TQFile::decodeName(getenv("XDG_CONFIG_DIRS")));
|
|
if (xdgConfigDirs.isEmpty())
|
|
{
|
|
xdgConfigDirs << "/etc/xdg";
|
|
TQString sysconfMenuDir = KGlobal::dirs()->findDirs("xdgconf-menu", TQString()).last();
|
|
if (sysconfMenuDir.endsWith("/menus/"))
|
|
xdgConfigDirs << sysconfMenuDir.left(sysconfMenuDir.length()-7);
|
|
|
|
}
|
|
|
|
m_xdgConfigDirs.clear();
|
|
for(TQStringList::ConstIterator it = dirs.begin();
|
|
it != dirs.end(); ++it)
|
|
{
|
|
m_xdgConfigDirs.append(*it+"/etc/xdg");
|
|
}
|
|
|
|
m_xdgConfigDirs += xdgConfigDirs;
|
|
filterDupes(m_xdgConfigDirs);
|
|
}
|
|
|
|
void
|
|
KioskRun::deleteDir(const TQString &dir)
|
|
{
|
|
if (dir.length() <= 1) // Safety
|
|
return;
|
|
if (!dir.startsWith("/")) // Safety
|
|
return;
|
|
Q_ASSERT(dir.startsWith(m_homeDir));
|
|
|
|
KProcess proc;
|
|
proc << "rm" << "-rf" << dir;
|
|
proc.start(KProcess::Block);
|
|
}
|
|
|
|
void
|
|
KioskRun::applyEnvironment(KProcess *p)
|
|
{
|
|
p->setEnvironment("HOME", m_homeDir);
|
|
p->setEnvironment("TDEHOME", m_homeDir+"/.kde");
|
|
p->setEnvironment("TDEROOTHOME", m_homeDir+"/.kde");
|
|
p->setEnvironment("TDEDIRS", m_kdeDirs.join(":"));
|
|
p->setEnvironment("XDG_DATA_HOME", m_homeDir+"/.local/share");
|
|
p->setEnvironment("XDG_DATA_DIRS", m_xdgDataDirs.join(":"));
|
|
p->setEnvironment("XDG_CONFIG_HOME", m_homeDir+"/.config");
|
|
p->setEnvironment("XDG_CONFIG_DIRS", m_xdgConfigDirs.join(":"));
|
|
p->setEnvironment("DCOPAUTHORITY", m_homeDir+"/.kde/DCOPserver");
|
|
p->setEnvironment("KDE_KIOSK_NO_PROFILES", "true");
|
|
if (m_noRestrictions)
|
|
p->setEnvironment("KDE_KIOSK_NO_RESTRICTIONS", "true");
|
|
}
|
|
|
|
bool
|
|
KioskRun::prepare()
|
|
{
|
|
bool result = setupRuntimeEnv();
|
|
|
|
deleteDir(m_configDir);
|
|
deleteDir(locateLocal("data"));
|
|
deleteDir(m_desktopPath);
|
|
deleteDir(m_homeDir+"/.config");
|
|
deleteDir(m_homeDir+"/.local/share");
|
|
return result;
|
|
}
|
|
|
|
void
|
|
KioskRun::updateSycoca()
|
|
{
|
|
// Force update
|
|
TQString sycocaUpdateFile = KioskRun::self()->locateLocal("services", "update_ksycoca");
|
|
TQFile file(sycocaUpdateFile);
|
|
file.remove();
|
|
file.open(IO_WriteOnly);
|
|
file.close();
|
|
|
|
dcopRef("kded", "kbuildsycoca").call("recreate");
|
|
}
|
|
|
|
KProcess*
|
|
KioskRun::run(const TQString &cmd, const TQStringList &args)
|
|
{
|
|
KProcess *proc = new KProcess(this);
|
|
|
|
applyEnvironment(proc);
|
|
|
|
*proc << cmd;
|
|
*proc << args;
|
|
|
|
proc->start(KProcess::NotifyOnExit);
|
|
return proc;
|
|
}
|
|
|
|
class SetEnv
|
|
{
|
|
public:
|
|
SetEnv(const char *key, const TQString &value) : m_key(key)
|
|
{
|
|
m_oldValue = getenv(m_key);
|
|
setenv(m_key, TQFile::encodeName(value), 1);
|
|
}
|
|
|
|
~SetEnv()
|
|
{
|
|
if (m_oldValue.isEmpty())
|
|
setenv(m_key,"",1);
|
|
else
|
|
setenv(m_key,m_oldValue.data(),1);
|
|
}
|
|
|
|
private:
|
|
const char* m_key;
|
|
TQCString m_oldValue;
|
|
};
|
|
|
|
void
|
|
KioskRun::setupConfigEnv()
|
|
{
|
|
if (m_instance) return;
|
|
|
|
// ::locateLocal must be called before we change the env. vars!
|
|
TQString newTmpDir = ::locateLocal("tmp", "kioskdir");
|
|
TQString newSocketDir = ::locateLocal("socket", "kioskdir");
|
|
|
|
SetEnv home("HOME", m_homeDir);
|
|
TQString kdeHome = m_homeDir+"/.kde";
|
|
SetEnv tdehome("TDEHOME", kdeHome);
|
|
SetEnv tderoothome("TDEROOTHOME", kdeHome);
|
|
SetEnv tdedirs("TDEDIRS", m_kdeDirs.join(":"));
|
|
SetEnv xdgDataHome("XDG_DATA_HOME", m_homeDir+"/.local/share");
|
|
SetEnv xdgDataDirs("XDG_DATA_DIRS", m_xdgDataDirs.join(":"));
|
|
SetEnv xdgConfigHome("XDG_CONFIG_HOME", m_homeDir+"/.config");
|
|
SetEnv xdgConfigDirs("XDG_CONFIG_DIRS", m_xdgConfigDirs.join(":"));
|
|
|
|
::mkdir(TQFile::encodeName(m_homeDir), 0700);
|
|
::mkdir(TQFile::encodeName(kdeHome), 0700);
|
|
|
|
// Create temp & socket dirs.
|
|
char hostname[256];
|
|
hostname[0] = 0;
|
|
gethostname(hostname, 255);
|
|
|
|
TQString tmpDir = TQString("%1/%2-%3").arg(kdeHome).arg("tmp").arg(hostname);
|
|
deleteDir(tmpDir);
|
|
::mkdir(TQFile::encodeName(newTmpDir), 0700);
|
|
::symlink(TQFile::encodeName(newTmpDir), TQFile::encodeName(tmpDir));
|
|
|
|
TQString socketDir = TQString("%1/%2-%3").arg(kdeHome).arg("socket").arg(hostname);
|
|
deleteDir(socketDir);
|
|
::mkdir(TQFile::encodeName(newSocketDir), 0700);
|
|
::symlink(TQFile::encodeName(newSocketDir), TQFile::encodeName(socketDir));
|
|
|
|
m_configDir = TQString("%1/.kde/share/config/").arg(m_homeDir);
|
|
|
|
m_instance = new KInstance("kioskrun");
|
|
(void) m_instance->dirs(); // Create KStandardDirs obj
|
|
|
|
m_desktopPath = m_homeDir + "/Desktop/";
|
|
m_desktopPath = m_instance->config()->readPathEntry( "Desktop", m_desktopPath);
|
|
m_desktopPath = TQDir::cleanDirPath( m_desktopPath );
|
|
if ( !m_desktopPath.endsWith("/") )
|
|
m_desktopPath.append('/');
|
|
|
|
{
|
|
SetEnv tdehome("TDEHOME", "-");
|
|
SetEnv tderoothome("TDEROOTHOME", "-");
|
|
SetEnv xdgDataHome("XDG_DATA_HOME", m_xdgDataDirs.first());
|
|
SetEnv xdgConfigHome("XDG_CONFIG_HOME", m_xdgConfigDirs.first());
|
|
|
|
m_saveInstance = new KInstance("kioskrun");
|
|
(void) m_saveInstance->dirs(); // Create KStandardDirs obj
|
|
}
|
|
}
|
|
|
|
TQString
|
|
KioskRun::locate(const char *resource, const TQString &filename)
|
|
{
|
|
setupConfigEnv();
|
|
|
|
return m_saveInstance->dirs()->findResource(resource, filename);
|
|
}
|
|
|
|
TQString
|
|
KioskRun::locateSave(const char *resource, const TQString &filename)
|
|
{
|
|
setupConfigEnv();
|
|
|
|
// split path from filename
|
|
int slash = filename.findRev('/')+1;
|
|
TQString dir = filename.left(slash);
|
|
TQString file = filename.mid(slash);
|
|
return m_saveInstance->dirs()->saveLocation(resource, dir, false) + file;
|
|
}
|
|
|
|
TQString
|
|
KioskRun::locateLocal(const char *resource, const TQString &filename)
|
|
{
|
|
setupConfigEnv();
|
|
|
|
// split path from filename
|
|
int slash = filename.findRev('/')+1;
|
|
TQString dir = filename.left(slash);
|
|
TQString file = filename.mid(slash);
|
|
return m_instance->dirs()->saveLocation(resource, dir, true) + file;
|
|
}
|
|
|
|
|
|
void
|
|
KioskRun::shutdownConfigEnv()
|
|
{
|
|
if (!m_instance) return;
|
|
|
|
delete m_instance;
|
|
m_instance = 0;
|
|
}
|
|
|
|
class ImmutableStatus
|
|
{
|
|
public:
|
|
bool m_fileScope;
|
|
TQDict<int> m_lines;
|
|
TQString m_tmpFile;
|
|
bool m_dirty;
|
|
};
|
|
|
|
|
|
bool
|
|
KioskRun::isConfigImmutable(const TQString &filename, const TQString &group)
|
|
{
|
|
(void) configFile(filename);
|
|
ImmutableStatus *status = m_immutableStatusCache.find(filename);
|
|
assert(status);
|
|
if (group.isEmpty())
|
|
return status->m_fileScope;
|
|
|
|
return status->m_lines.find(group);
|
|
}
|
|
|
|
void
|
|
KioskRun::setConfigImmutable(const TQString &filename, const TQString &_group, bool bImmutable)
|
|
{
|
|
(void) configFile(filename);
|
|
ImmutableStatus *status = m_immutableStatusCache.find(filename);
|
|
assert(status);
|
|
if (_group.isEmpty())
|
|
{
|
|
if (status->m_fileScope != bImmutable)
|
|
{
|
|
status->m_fileScope = bImmutable;
|
|
status->m_dirty = true;
|
|
m_forceSycocaUpdate = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TQString group = TQString("[%1]").arg(_group);
|
|
if (status->m_lines.find(group))
|
|
{
|
|
if (!bImmutable)
|
|
{
|
|
status->m_lines.remove(group);
|
|
status->m_dirty = true;
|
|
m_forceSycocaUpdate = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (bImmutable)
|
|
{
|
|
status->m_lines.insert(group, (int *) 1);
|
|
status->m_dirty = true;
|
|
m_forceSycocaUpdate = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void stripImmutable(TQString &ext)
|
|
{
|
|
ext.replace("i", "");
|
|
if (ext == "[$]")
|
|
ext = TQString();
|
|
}
|
|
|
|
static void addImmutable(TQString &ext)
|
|
{
|
|
ext.replace("[$", "[$i");
|
|
}
|
|
|
|
TQString
|
|
KioskRun::saveImmutableStatus(const TQString &filename)
|
|
{
|
|
ImmutableStatus *status = new ImmutableStatus;
|
|
status->m_fileScope = false;
|
|
status->m_dirty = false;
|
|
m_immutableStatusCache.insert(filename, status);
|
|
|
|
KTempFile tmp;
|
|
tmp.close();
|
|
|
|
TQString newPath = tmp.name();
|
|
status->m_tmpFile = tmp.name();
|
|
|
|
TQString path = m_saveInstance->dirs()->findResource("config", filename);
|
|
if (path.isEmpty())
|
|
return newPath; // Nothing to do
|
|
|
|
TQFile oldCfg(path);
|
|
|
|
if (!oldCfg.open( IO_ReadOnly ))
|
|
return newPath; // Error
|
|
|
|
TQFile newCfg(newPath);
|
|
if (!newCfg.open( IO_WriteOnly ))
|
|
return newPath; // Error
|
|
|
|
TQTextStream txtIn(&oldCfg);
|
|
txtIn.setEncoding(TQTextStream::UnicodeUTF8);
|
|
|
|
TQTextStream pTxtOut(&newCfg);
|
|
pTxtOut.setEncoding(TQTextStream::UnicodeUTF8);
|
|
|
|
TQRegExp immutable("(\\[\\$e?ie?\\])$");
|
|
|
|
// TODO: Use "group+key" instead of "key" as index, otherwise it might not be unique
|
|
|
|
while(! txtIn.atEnd())
|
|
{
|
|
TQString line = txtIn.readLine().stripWhiteSpace();
|
|
|
|
if (line.startsWith("#"))
|
|
{
|
|
// Comment, do nothing...
|
|
}
|
|
else if (line.startsWith("["))
|
|
{
|
|
int pos = immutable.searchRev(line);
|
|
if (pos != -1)
|
|
{
|
|
TQString group = line.left(pos);
|
|
TQString ext = immutable.cap(0);
|
|
stripImmutable(ext);
|
|
if (pos == 0)
|
|
{
|
|
status->m_fileScope = true;
|
|
continue;
|
|
}
|
|
status->m_lines.replace(group, (int *)1 );
|
|
line = group + ext;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int equal = line.find('=');
|
|
if (equal != -1)
|
|
{
|
|
TQString key = line.left(equal).stripWhiteSpace();
|
|
int pos = immutable.searchRev(key);
|
|
if (pos != -1)
|
|
{
|
|
key = key.left(pos);
|
|
TQString ext = immutable.cap(0);
|
|
stripImmutable(ext);
|
|
status->m_lines.replace(key, (int *)1 );
|
|
line = key + ext + line.mid(equal);
|
|
}
|
|
}
|
|
}
|
|
|
|
pTxtOut << line << endl;
|
|
}
|
|
oldCfg.close();
|
|
newCfg.close();
|
|
|
|
if (newCfg.status() != IO_Ok )
|
|
{
|
|
kdWarning() << "Error writing " << newPath << endl;
|
|
return newPath;
|
|
}
|
|
return newPath;
|
|
}
|
|
|
|
bool
|
|
KioskRun::restoreImmutableStatus(const TQString &filename, bool force)
|
|
{
|
|
ImmutableStatus *status = m_immutableStatusCache.take(filename);
|
|
if (!status)
|
|
{
|
|
kdDebug() << "KioskRun::restoreImmutableStatus(" << filename << ") status info missing" << endl;
|
|
return true;
|
|
}
|
|
if (!force && !status->m_dirty)
|
|
{
|
|
kdDebug() << "KioskRun::restoreImmutableStatus(" << filename << ") not changed" << endl;
|
|
delete status;
|
|
return true;
|
|
}
|
|
kdDebug() << "KioskRun::restoreImmutableStatus(" << filename << ") restoring" << endl;
|
|
|
|
TQString path = status->m_tmpFile;
|
|
|
|
KSaveFile newCfg(path);
|
|
if (newCfg.status() != 0)
|
|
{
|
|
delete status;
|
|
return true; // Continue
|
|
}
|
|
|
|
TQTextStream *pTxtOut = newCfg.textStream();
|
|
pTxtOut->setEncoding(TQTextStream::UnicodeUTF8);
|
|
|
|
TQRegExp option("(\\[\\$e\\])$");
|
|
|
|
if (status->m_fileScope)
|
|
{
|
|
kdDebug() << "Marking file " << filename << " immutable" << endl;
|
|
(*pTxtOut) << "[$i]" << endl;
|
|
}
|
|
|
|
TQFile oldCfg(path);
|
|
if (oldCfg.open( IO_ReadOnly ))
|
|
{
|
|
|
|
TQTextStream txtIn(&oldCfg);
|
|
txtIn.setEncoding(TQTextStream::UnicodeUTF8);
|
|
|
|
while(! txtIn.atEnd())
|
|
{
|
|
TQString line = txtIn.readLine().stripWhiteSpace();
|
|
|
|
if (line.startsWith("#"))
|
|
{
|
|
// Comment, do nothing...
|
|
}
|
|
else if (line.startsWith("["))
|
|
{
|
|
if (status->m_lines.take(line))
|
|
line += "[$i]";
|
|
}
|
|
else
|
|
{
|
|
int equal = line.find('=');
|
|
if (equal != -1)
|
|
{
|
|
TQString key = line.left(equal).stripWhiteSpace();
|
|
int pos = option.searchRev(key);
|
|
if (pos != -1)
|
|
{
|
|
key = key.left(pos);
|
|
TQString ext = option.cap(0);
|
|
if (status->m_lines.take(key))
|
|
addImmutable(ext);
|
|
line = key + ext + line.mid(equal);
|
|
}
|
|
else
|
|
{
|
|
if (status->m_lines.take(key))
|
|
line = key + "[$i]" + line.mid(equal);
|
|
}
|
|
}
|
|
}
|
|
|
|
(*pTxtOut) << line << endl;
|
|
}
|
|
oldCfg.close();
|
|
}
|
|
|
|
// Create remaining groups that were marked as immutable
|
|
TQDictIterator<int> it( status->m_lines );
|
|
for( ; it.current(); ++it )
|
|
{
|
|
TQString group = it.currentKey();
|
|
if ( it.current() )
|
|
(*pTxtOut) << endl << group << "[$i]" << endl;
|
|
}
|
|
|
|
if (!newCfg.close())
|
|
{
|
|
kdWarning() << "Error writing" << path << endl;
|
|
delete status;
|
|
return true; // Continue
|
|
}
|
|
|
|
TQString installLocation = m_saveInstance->dirs()->saveLocation("config", TQString(), false) + filename;
|
|
if (!install(path, installLocation))
|
|
{
|
|
m_immutableStatusCache.insert(filename, status); // Keep it around
|
|
return false;
|
|
}
|
|
delete status;
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
KioskRun::flushConfigCache()
|
|
{
|
|
while ( !m_saveConfigCache.isEmpty() )
|
|
{
|
|
TQDictIterator<KConfig> it( m_saveConfigCache );
|
|
TQString file = it.currentKey();
|
|
KConfig *config = it.current();
|
|
bool dirty = config->isDirty();
|
|
config->sync(); // Save
|
|
if (!restoreImmutableStatus(file, dirty))
|
|
return false;
|
|
m_saveConfigCache.remove(file);
|
|
}
|
|
|
|
if (m_forceSycocaUpdate)
|
|
forceSycocaUpdate();
|
|
return true;
|
|
}
|
|
|
|
KConfig *
|
|
KioskRun::configFile(const TQString &filename)
|
|
{
|
|
KConfig *config = m_saveConfigCache.find(filename);
|
|
if (config)
|
|
return config;
|
|
|
|
kdDebug() << "KioskRun::configFile(" << filename << ") loading file" << endl;
|
|
|
|
setupConfigEnv();
|
|
|
|
TQString saveLocation = saveImmutableStatus(filename);
|
|
config = new KSimpleConfig(saveLocation);
|
|
m_saveConfigCache.insert(filename, config);
|
|
|
|
return config;
|
|
}
|
|
|
|
void
|
|
KioskRun::makeMutable(bool bMutable)
|
|
{
|
|
KConfig *config = configFile("kdeglobals");
|
|
|
|
m_noRestrictions = bMutable;
|
|
if (KDE::version() < TDE_MAKE_VERSION(3,2,4))
|
|
{
|
|
config->setGroup("KDE Action Restrictions");
|
|
if (bMutable)
|
|
{
|
|
KUser thisUser;
|
|
config->writeEntry("kiosk_exception", thisUser.loginName()+":"); // This user, all hosts
|
|
}
|
|
else
|
|
{
|
|
config->writeEntry("kiosk_exception", TQString());
|
|
}
|
|
}
|
|
// Propagate to tdeinit
|
|
dcopRef("klauncher", "klauncher").call("setLaunchEnv",
|
|
TQCString("KDE_KIOSK_NO_RESTRICTIONS"), TQCString(m_noRestrictions ? "true" : ""));
|
|
|
|
setConfigImmutable("kdeglobals", "KDE Action Restrictions", true);
|
|
}
|
|
|
|
TQStringList
|
|
KioskRun::newConfigFiles()
|
|
{
|
|
setupConfigEnv();
|
|
|
|
TQStringList exceptions;
|
|
exceptions << "kconf_updaterc";
|
|
|
|
TQStringList result;
|
|
TQDir dir(m_configDir);
|
|
dir.setFilter( TQDir::Files | TQDir::NoSymLinks );
|
|
|
|
const TQFileInfoList *list = dir.entryInfoList();
|
|
if (!list) return result;
|
|
|
|
TQFileInfoListIterator it( *list );
|
|
TQFileInfo *fi;
|
|
while ( (fi = it.current()) != 0 )
|
|
{
|
|
TQString file = fi->fileName();
|
|
if (!file.endsWith("~") && !exceptions.contains(file)) // Skip backup files & exceptions
|
|
result.append(file);
|
|
++it;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void
|
|
KioskRun::mergeConfigFile(const TQString &filename)
|
|
{
|
|
KConfig *saveCfg = configFile(filename);
|
|
|
|
kdDebug() << "KioskRun::mergeConfigFile(" << (m_configDir + filename) << ")" << endl;
|
|
KSimpleConfig newCfg(m_configDir + filename);
|
|
|
|
TQStringList groups = newCfg.groupList();
|
|
for(TQStringList::ConstIterator it = groups.begin();
|
|
it != groups.end(); ++it)
|
|
{
|
|
saveCfg->setGroup(*it);
|
|
TQMap<TQString, TQString> map = newCfg.entryMap(*it);
|
|
for(TQMap<TQString, TQString>::Iterator it2 = map.begin();
|
|
it2 != map.end(); ++it2)
|
|
{
|
|
#ifdef DEBUG_ENTRIES
|
|
tqWarning("[%s] %s --> %s", (*it).latin1(), it2.key().latin1(), it2.data().latin1());
|
|
#endif
|
|
saveCfg->writeEntry(it2.key(), it2.data());
|
|
}
|
|
}
|
|
}
|
|
|
|
bool
|
|
KioskRun::setupRuntimeEnv()
|
|
{
|
|
if (m_dcopClient) return true;
|
|
|
|
KioskRunProgressDialog dlg(kapp->mainWidget(), "kioskrun_progress",
|
|
i18n("Setting Up Configuration Environment"),
|
|
i18n("Setting up configuration environment."));
|
|
|
|
char hostname[256];
|
|
hostname[0] = 0;
|
|
gethostname(hostname, 255);
|
|
TQString cacheDir = TQString("%1/.kde/cache-%2").arg(m_homeDir).arg(hostname);
|
|
|
|
deleteDir(cacheDir);
|
|
KStandardDirs::makeDir(cacheDir);
|
|
deleteDir(m_homeDir+"/.qt");
|
|
::unlink(TQFile::encodeName(m_homeDir+".kderc"));
|
|
|
|
|
|
TQString iceAuth = TQString("%1/.ICEauthority").arg(TQDir::homeDirPath());
|
|
setenv("ICEAUTHORITY", TQFile::encodeName(iceAuth), 0); // Don't overwrite existing setting
|
|
|
|
TQString xAuth = TQString("%1/.Xauthority").arg(TQDir::homeDirPath());
|
|
setenv("XAUTHORITY", TQFile::encodeName(xAuth), 0); // Don't overwrite existing setting
|
|
|
|
TQString dcopServerFile = m_homeDir+"/.kde/DCOPserver";
|
|
|
|
KProcess tdeinit;
|
|
|
|
applyEnvironment(&tdeinit);
|
|
|
|
tdeinit << "tdeinit";
|
|
|
|
connect(&tdeinit, TQT_SIGNAL(processExited(KProcess *)), &dlg, TQT_SLOT(slotFinished()));
|
|
|
|
tdeinit.start(KProcess::NotifyOnExit);
|
|
|
|
dlg.exec();
|
|
|
|
TQCString dcopSrv;
|
|
TQFile f(dcopServerFile);
|
|
if (f.open(IO_ReadOnly))
|
|
{
|
|
int size = TQMIN( 1024, f.size() ); // protection against a huge file
|
|
TQCString contents( size+1 );
|
|
if ( f.readBlock( contents.data(), size ) == size )
|
|
{
|
|
contents[size] = '\0';
|
|
int pos = contents.find('\n');
|
|
if ( pos == -1 ) // Shouldn't happen
|
|
dcopSrv = contents;
|
|
else
|
|
dcopSrv = contents.left( pos );
|
|
}
|
|
}
|
|
|
|
if (dcopSrv.isEmpty())
|
|
{
|
|
kdWarning() << "Error reading " << dcopServerFile << endl;
|
|
m_dcopClient = new DCOPClient;
|
|
shutdownRuntimeEnv();
|
|
return false;
|
|
}
|
|
|
|
m_dcopClient = new DCOPClient;
|
|
m_dcopClient->setServerAddress(dcopSrv);
|
|
unsetenv("DCOPSERVER"); // Don't propagate it
|
|
m_dcopClient->attach();
|
|
return true;
|
|
}
|
|
|
|
void
|
|
KioskRun::shutdownRuntimeEnv()
|
|
{
|
|
if (!m_dcopClient) return;
|
|
|
|
delete m_dcopClient;
|
|
m_dcopClient = 0;
|
|
|
|
KProcess tdeinit;
|
|
applyEnvironment(&tdeinit);
|
|
|
|
tdeinit << "tdeinit_shutdown";
|
|
|
|
tdeinit.start(KProcess::Block);
|
|
|
|
KProcess dcopserver;
|
|
applyEnvironment(&dcopserver);
|
|
|
|
dcopserver << "dcopserver_shutdown";
|
|
|
|
dcopserver.start(KProcess::Block);
|
|
}
|
|
|
|
DCOPRef
|
|
KioskRun::dcopRef(const TQCString &appId, const TQCString &objId)
|
|
{
|
|
if (!setupRuntimeEnv())
|
|
return DCOPRef();
|
|
DCOPRef ref(appId, objId);
|
|
ref.setDCOPClient(m_dcopClient);
|
|
return ref;
|
|
}
|
|
|
|
// Lookup the setting for a custom action
|
|
bool
|
|
KioskRun::lookupCustomAction(const TQString &action)
|
|
{
|
|
KConfig *cfg = KioskRun::self()->configFile("kdeglobals");
|
|
cfg->setGroup("KDE Custom Restrictions");
|
|
return cfg->readBoolEntry(action, false);
|
|
}
|
|
|
|
// Change the setting for a custom action
|
|
void
|
|
KioskRun::setCustomAction(const TQString &action, bool checked)
|
|
{
|
|
KConfig *cfg = KioskRun::self()->configFile("kdeglobals");
|
|
cfg->setGroup("KDE Custom Restrictions");
|
|
if (cfg->readBoolEntry(action, false) != checked)
|
|
{
|
|
cfg->writeEntry(action, checked);
|
|
KioskRun::self()->scheduleSycocaUpdate();
|
|
|
|
if (action == "restrict_file_browsing")
|
|
{
|
|
setCustomRestrictionFileBrowsing(checked);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Create directory
|
|
bool
|
|
KioskRun::createDir(const TQString &dir)
|
|
{
|
|
if (TQDir(dir).exists())
|
|
return true; // Exists already
|
|
|
|
KURL dest;
|
|
if (!m_isRoot || (m_user != "root"))
|
|
{
|
|
dest.setProtocol("fish");
|
|
dest.setHost("localhost");
|
|
dest.setUser(m_user);
|
|
}
|
|
dest.setPath(dir);
|
|
|
|
if (dir.length() > 1)
|
|
{
|
|
KURL parent = dest.upURL();
|
|
|
|
bool result = createDir(parent.path());
|
|
if (!result)
|
|
return false;
|
|
}
|
|
|
|
do
|
|
{
|
|
if (NETACCESS::exists(dest, false, kapp->mainWidget()))
|
|
return true;
|
|
|
|
bool result = NETACCESS::mkdir(dest, kapp->mainWidget(), 0755);
|
|
if (result == true)
|
|
return true;
|
|
|
|
TQString error = NETACCESS::lastErrorString();
|
|
TQString msg;
|
|
|
|
if (error.isEmpty())
|
|
msg = i18n("<qt>The directory <b>%1</b> could not be created because of an unspecified problem.<p>")
|
|
.arg(dir);
|
|
else
|
|
msg = i18n("<qt>The directory <b>%1</b> could not be created because of the following problem:"
|
|
"<p>%2<p>")
|
|
.arg(dir, NETACCESS::lastErrorString());
|
|
|
|
msg += i18n("Without this directory your changes can not be saved.<p>"
|
|
"Do you want to retry creating the directory or abort the saving of changes?</qt>");
|
|
|
|
int msgResult = KMessageBox::warningYesNo(kapp->mainWidget(), msg, TQString(),
|
|
i18n("&Retry"), i18n("&Abort"));
|
|
|
|
if (msgResult == KMessageBox::No)
|
|
return false;
|
|
|
|
// Maybe the user created it in the meantime
|
|
if (TQDir(dir).exists())
|
|
return true; // Exists already
|
|
}
|
|
while (true);
|
|
return false;
|
|
}
|
|
|
|
// Create directory
|
|
bool
|
|
KioskRun::createRemoteDirRecursive(const KURL &dest, bool ask)
|
|
{
|
|
if (NETACCESS::exists(dest, false, kapp->mainWidget()))
|
|
return true;
|
|
|
|
KURL parent = dest.upURL();
|
|
|
|
if (NETACCESS::exists(dest, false, kapp->mainWidget()))
|
|
{
|
|
return createRemoteDir(dest);
|
|
}
|
|
|
|
if (ask)
|
|
{
|
|
// Parent doesn't exist,
|
|
int result = KMessageBox::warningContinueCancel(kapp->mainWidget(),
|
|
i18n("<qt>The directory <b>%1</b> does not yet exist. "
|
|
"Do you want to create it?").arg(parent.prettyURL()), TQString(),
|
|
i18n("Create &Dir"));
|
|
if (result != KMessageBox::Continue)
|
|
return false;
|
|
}
|
|
|
|
TQString path = dest.path(1);
|
|
int i = 0;
|
|
while ( (i = path.find('/', i+1)) != -1)
|
|
{
|
|
parent.setPath(path.left(i+1));
|
|
if (! createRemoteDir(parent))
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// Create directory
|
|
bool
|
|
KioskRun::createRemoteDir(const KURL &dest)
|
|
{
|
|
do
|
|
{
|
|
if (NETACCESS::exists(dest, false, kapp->mainWidget()))
|
|
return true;
|
|
|
|
if (NETACCESS::mkdir(dest, kapp->mainWidget(), 0755))
|
|
return true;
|
|
|
|
#if KDE_IS_VERSION(3,2,91)
|
|
if (NETACCESS::lastError() == KIO::ERR_DIR_ALREADY_EXIST)
|
|
return true;
|
|
#endif
|
|
|
|
//TODO Check directory already exists error
|
|
TQString error = NETACCESS::lastErrorString();
|
|
TQString msg;
|
|
|
|
if (error.isEmpty())
|
|
msg = i18n("<qt>The directory <b>%1</b> could not be created because of an unspecified problem.<p>")
|
|
.arg(dest.prettyURL());
|
|
else
|
|
msg = i18n("<qt>The directory <b>%1</b> could not be created because of the following problem:"
|
|
"<p>%2<p>")
|
|
.arg(dest.prettyURL(), NETACCESS::lastErrorString());
|
|
|
|
msg += i18n("Without this directory your files can not be uploaded.<p>"
|
|
"Do you want to retry creating the directory or abort uploading?</qt>");
|
|
|
|
int msgResult = KMessageBox::warningYesNo(kapp->mainWidget(), msg, TQString(),
|
|
i18n("&Retry"), i18n("&Abort"));
|
|
|
|
if (msgResult == KMessageBox::No)
|
|
return false;
|
|
}
|
|
while (true);
|
|
return false;
|
|
}
|
|
|
|
// Install file
|
|
bool
|
|
KioskRun::install(const TQString &file, const TQString &destination)
|
|
{
|
|
KURL dest;
|
|
if (!m_isRoot || (m_user != "root"))
|
|
{
|
|
dest.setProtocol("fish");
|
|
dest.setHost("localhost");
|
|
dest.setUser(m_user);
|
|
}
|
|
dest.setPath(destination);
|
|
|
|
if (!createDir(dest.upURL().path()))
|
|
return false;
|
|
|
|
do
|
|
{
|
|
KURL src;
|
|
src.setPath(file);
|
|
bool result = NETACCESS::file_copy(src, dest, 0644, true, false, kapp->mainWidget());
|
|
if (result == true)
|
|
{
|
|
::unlink(TQFile::encodeName(file));
|
|
return true;
|
|
}
|
|
|
|
TQString error = NETACCESS::lastErrorString();
|
|
TQString msg;
|
|
if (error.isEmpty())
|
|
msg = i18n("<qt>The file <b>%1</b> could not be installed because of an unspecified problem.")
|
|
.arg(destination);
|
|
else
|
|
msg = i18n("<qt>The file <b>%1</b> could not be installed because of the following problem:"
|
|
"<p>%2<p>")
|
|
.arg(destination, NETACCESS::lastErrorString());
|
|
|
|
msg += i18n("Do you want to retry the installation or abort the saving of changes?</qt>");
|
|
|
|
int msgResult = KMessageBox::warningYesNo(kapp->mainWidget(), msg, TQString(),
|
|
i18n("&Retry"), i18n("&Abort"));
|
|
|
|
if (msgResult == KMessageBox::No)
|
|
return false;
|
|
}
|
|
while (true);
|
|
return false;
|
|
}
|
|
|
|
// Upload file
|
|
bool
|
|
KioskRun::uploadRemote(const TQString &file, const KURL &dest)
|
|
{
|
|
do
|
|
{
|
|
KURL src;
|
|
src.setPath(file);
|
|
bool result = NETACCESS::file_copy(src, dest, 0644, true, false, kapp->mainWidget());
|
|
if (result == true)
|
|
return true;
|
|
|
|
TQString error = NETACCESS::lastErrorString();
|
|
TQString msg;
|
|
if (error.isEmpty())
|
|
msg = i18n("<qt>The file <b>%1</b> could not be uploaded to <b>%2</b> because of an unspecified problem.")
|
|
.arg(file, dest.prettyURL());
|
|
else
|
|
msg = i18n("<qt>The file <b>%1</b> could not be uploaded to <b>%2</b> because of the following problem:"
|
|
"<p>%3<p>")
|
|
.arg(file, dest.prettyURL(),NETACCESS::lastErrorString());
|
|
|
|
msg += i18n("Do you want to retry or abort the uploading?</qt>");
|
|
|
|
int msgResult = KMessageBox::warningYesNo(kapp->mainWidget(), msg, TQString(),
|
|
i18n("&Retry"), i18n("&Abort"));
|
|
|
|
if (msgResult == KMessageBox::No)
|
|
return false;
|
|
}
|
|
while (true);
|
|
return false;
|
|
}
|
|
|
|
// Remove file
|
|
bool
|
|
KioskRun::remove(const TQString &destination)
|
|
{
|
|
KURL dest;
|
|
if (!m_isRoot || (m_user != "root"))
|
|
{
|
|
dest.setProtocol("fish");
|
|
dest.setHost("localhost");
|
|
dest.setUser(m_user);
|
|
}
|
|
dest.setPath(destination);
|
|
|
|
return NETACCESS::del(dest, kapp->mainWidget());
|
|
}
|
|
|
|
// Move file or directory
|
|
bool
|
|
KioskRun::move(const TQString &source, const TQString &destination, const TQStringList &files)
|
|
{
|
|
KURL src;
|
|
KURL dest;
|
|
if (!m_isRoot || (m_user != "root"))
|
|
{
|
|
dest.setProtocol("fish");
|
|
dest.setHost("localhost");
|
|
dest.setUser(m_user);
|
|
src.setProtocol("fish");
|
|
src.setHost("localhost");
|
|
src.setUser(m_user);
|
|
}
|
|
|
|
for(TQStringList::ConstIterator it = files.begin();
|
|
it != files.end(); ++it)
|
|
{
|
|
src.setPath(source + *it);
|
|
dest.setPath(destination + *it);
|
|
|
|
kdDebug() << "Moving " << src << " --> " << dest << endl;
|
|
if (!createRemoteDirRecursive(dest.upURL(), false))
|
|
return false;
|
|
|
|
if (!NETACCESS::file_move(src, dest, -1, true, false, kapp->mainWidget()))
|
|
{
|
|
// TODO add error message + retry
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// Read information of profile @p profile
|
|
void
|
|
KioskRun::getProfileInfo(const TQString &profile, TQString &description, TQString &installDir, TQString &installUser)
|
|
{
|
|
KConfig *config = kapp->config();
|
|
|
|
TQString defaultInstallDir = getProfilePrefix();
|
|
if (defaultInstallDir.isEmpty())
|
|
{
|
|
defaultInstallDir = "/etc/kde-profile/";
|
|
}
|
|
if (!defaultInstallDir.endsWith("/"))
|
|
defaultInstallDir.append("/");
|
|
TQString tmp = profile;
|
|
tmp.replace(" ", "_");
|
|
tmp.replace(":", "_");
|
|
tmp.replace("/", "_");
|
|
defaultInstallDir += tmp+"/";
|
|
|
|
TQString group = TQString("Directories-%1").arg(profile);
|
|
config->setGroup(group);
|
|
|
|
installDir = config->readEntry("prefixes", defaultInstallDir);
|
|
if (!installDir.endsWith("/"))
|
|
installDir.append("/");
|
|
|
|
TQString profileInfoFile = installDir + ".kdeprofile";
|
|
if (TQFile::exists(profileInfoFile))
|
|
{
|
|
KSimpleConfig profileInfo(profileInfoFile, true);
|
|
description = profileInfo.readEntry("Description");
|
|
installUser = profileInfo.readEntry("InstallUser", "root");
|
|
return;
|
|
}
|
|
|
|
TQString defaultDescription;
|
|
if (profile == "default")
|
|
defaultDescription = i18n("Default profile");
|
|
|
|
description = config->readEntry("ProfileDescription", defaultDescription);
|
|
installUser = config->readEntry("ProfileInstallUser", "root");
|
|
}
|
|
|
|
KSimpleConfig *
|
|
KioskRun::openKderc()
|
|
{
|
|
if (m_localKdercConfig)
|
|
return m_localKdercConfig;
|
|
|
|
KURL settingsUrl;
|
|
settingsUrl.setPath(m_kderc);
|
|
|
|
m_localKderc = ::locateLocal("tmp", "kderc_"+kapp->randomString(5));
|
|
::unlink(TQFile::encodeName(m_localKderc));
|
|
|
|
KURL localCopyUrl;
|
|
localCopyUrl.setPath(m_localKderc);
|
|
|
|
if (TQFile::exists(settingsUrl.path()))
|
|
{
|
|
|
|
while (!NETACCESS::copy(settingsUrl, localCopyUrl, kapp->mainWidget()))
|
|
{
|
|
TQString error = NETACCESS::lastErrorString();
|
|
TQString msg;
|
|
if (error.isEmpty())
|
|
msg = i18n("<qt>The file <b>%1</b> could not be accessed because of an unspecified problem.")
|
|
.arg(settingsUrl.path());
|
|
else
|
|
msg = i18n("<qt>The file <b>%1</b> could not be accessed because of the following problem:"
|
|
"<p>%2<p>")
|
|
.arg(settingsUrl.path(), error);
|
|
|
|
msg += i18n("Do you want to retry the operation or abort the saving of changes?</qt>");
|
|
|
|
int msgResult = KMessageBox::warningYesNo(kapp->mainWidget(), msg, TQString(),
|
|
i18n("&Retry"), i18n("&Abort"));
|
|
|
|
if (msgResult == KMessageBox::No)
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
m_localKdercConfig = new KSimpleConfig(m_localKderc);
|
|
return m_localKdercConfig;
|
|
}
|
|
|
|
bool
|
|
KioskRun::closeKderc()
|
|
{
|
|
if (!m_localKdercConfig)
|
|
return false;
|
|
m_localKdercConfig->sync();
|
|
delete m_localKdercConfig;
|
|
m_localKdercConfig = 0;
|
|
|
|
TQString saveUser = m_user;
|
|
m_user = "root";
|
|
bool result = install(m_localKderc, m_kderc);
|
|
m_localKderc = TQString();
|
|
m_user = saveUser;
|
|
kapp->config()->reparseConfiguration();
|
|
return result;
|
|
}
|
|
|
|
// Store information for profile @p profile
|
|
bool
|
|
KioskRun::setProfileInfo(const TQString &profile, const TQString &description, const TQString &_installDir, const TQString &installUser, bool deleteProfile, bool deleteFiles)
|
|
{
|
|
TQString installDir = _installDir;
|
|
if (!installDir.endsWith("/"))
|
|
installDir.append("/");
|
|
|
|
TQString saveProfileInfo = installDir + ".kdeprofile";
|
|
KSimpleConfig profileInfo(saveProfileInfo, true);
|
|
TQString oldDescription = profileInfo.readEntry("Description");
|
|
TQString oldInstallUser = profileInfo.readEntry("InstallUser");
|
|
if (deleteProfile && !installDir.isEmpty())
|
|
{
|
|
bool result = true;
|
|
KioskSync profileDir(kapp->mainWidget());
|
|
profileDir.addDir(installDir, KURL());
|
|
TQStringList allFiles = profileDir.listFiles();
|
|
allFiles.remove(".kdeprofile");
|
|
if (allFiles.isEmpty())
|
|
{
|
|
if (TQDir(installDir).exists())
|
|
{
|
|
m_user = installUser;
|
|
remove(installDir);
|
|
m_user = TQString();
|
|
}
|
|
}
|
|
else if (deleteFiles)
|
|
{
|
|
int msgResult = KMessageBox::warningYesNoCancelList(kapp->mainWidget(),
|
|
i18n("<qt>The profile directory <b>%1</b> contains the following files, "
|
|
"do you wish to delete these files?").arg(installDir),
|
|
allFiles,
|
|
i18n("Deleting Profile"),
|
|
#if KDE_IS_VERSION(3,2,91)
|
|
KStdGuiItem::del(),
|
|
#else
|
|
i18n("&Delete"),
|
|
#endif
|
|
i18n("&Keep Files")
|
|
);
|
|
switch(msgResult)
|
|
{
|
|
case KMessageBox::Yes:
|
|
// Delete files
|
|
m_user = installUser;
|
|
result = remove(installDir);
|
|
m_user = TQString();
|
|
if (!result)
|
|
return false;
|
|
break;
|
|
|
|
case KMessageBox::No:
|
|
// Keep files
|
|
break;
|
|
|
|
default:
|
|
// Cancel
|
|
return false;
|
|
}
|
|
}
|
|
|
|
m_user = installUser;
|
|
if (TQFile::exists(saveProfileInfo))
|
|
result = remove(saveProfileInfo);
|
|
m_user = TQString();
|
|
if (!result)
|
|
return false;
|
|
}
|
|
else if ((description != oldDescription) ||
|
|
(installUser != oldInstallUser))
|
|
{
|
|
TQString localProfileInfo = ::locateLocal("tmp", "kdeprofile_"+kapp->randomString(5));
|
|
::unlink(TQFile::encodeName(localProfileInfo));
|
|
KSimpleConfig newProfileInfo(localProfileInfo);
|
|
newProfileInfo.writeEntry("Description", description);
|
|
newProfileInfo.writeEntry("InstallUser", installUser);
|
|
newProfileInfo.sync();
|
|
bool result = install(localProfileInfo, saveProfileInfo);
|
|
if (!result)
|
|
return false;
|
|
}
|
|
|
|
KUser thisUser;
|
|
TQString newAdmin = thisUser.loginName()+":"; // This user, all hosts
|
|
|
|
KConfig *config = kapp->config();
|
|
|
|
config->setGroup("Directories");
|
|
TQString oldAdmin = config->readEntry("kioskAdmin");
|
|
|
|
TQString group = TQString("Directories-%1").arg(profile);
|
|
config->setGroup(group);
|
|
|
|
if ((installDir == config->readEntry("prefixes")) &&
|
|
(newAdmin == oldAdmin) &&
|
|
!deleteProfile)
|
|
return true; // Nothing to do
|
|
|
|
KSimpleConfig *cfg = openKderc();
|
|
if (!cfg)
|
|
return false;
|
|
|
|
cfg->setGroup("Directories");
|
|
cfg->writeEntry("kioskAdmin", newAdmin);
|
|
|
|
if (deleteProfile)
|
|
{
|
|
cfg->deleteGroup(group);
|
|
}
|
|
else
|
|
{
|
|
cfg->setGroup(group);
|
|
// TODO: update prefixes
|
|
cfg->writeEntry("prefixes", installDir);
|
|
}
|
|
cfg->sync();
|
|
|
|
return closeKderc();
|
|
}
|
|
|
|
bool
|
|
KioskRun::deleteProfile(const TQString &profile, bool deleteFiles)
|
|
{
|
|
TQString description;
|
|
TQString installDir;
|
|
TQString installUser;
|
|
getProfileInfo(profile, description, installDir, installUser);
|
|
return setProfileInfo(profile, description, installDir, installUser, true, deleteFiles);
|
|
}
|
|
|
|
// Read profile prefix
|
|
TQString
|
|
KioskRun::getProfilePrefix()
|
|
{
|
|
KConfig *config = kapp->config();
|
|
|
|
config->setGroup("Directories");
|
|
|
|
TQString prefix = config->readEntry("profileDirsPrefix");
|
|
if (!prefix.isEmpty() && !prefix.endsWith("/"))
|
|
prefix.append('/');
|
|
return prefix;
|
|
}
|
|
|
|
// Store profile prefix
|
|
bool
|
|
KioskRun::setProfilePrefix(const TQString &_prefix)
|
|
{
|
|
TQString prefix = _prefix;
|
|
|
|
if (!prefix.isEmpty() && !prefix.endsWith("/"))
|
|
prefix.append('/');
|
|
|
|
if (prefix == getProfilePrefix())
|
|
return true; // Nothing to do
|
|
|
|
KSimpleConfig *cfg = openKderc();
|
|
if (!cfg)
|
|
return false;
|
|
|
|
cfg->setGroup("Directories");
|
|
cfg->writeEntry("profileDirsPrefix", prefix);
|
|
|
|
cfg->sync();
|
|
|
|
return closeKderc();
|
|
}
|
|
|
|
TQString
|
|
KioskRun::newProfile()
|
|
{
|
|
TQString profilePrefix = getProfilePrefix();
|
|
|
|
KConfig *config = kapp->config();
|
|
for(int p = 1; p; p++)
|
|
{
|
|
TQString profile = TQString("profile%1").arg(p);
|
|
TQString group = TQString("Directories-%1").arg(profile);
|
|
if (!config->hasGroup(group))
|
|
{
|
|
if (profilePrefix.isEmpty())
|
|
return profile;
|
|
|
|
TQString profileDir = profilePrefix + profile;
|
|
if (!TQDir(profileDir).exists() && !TQFile::exists(profileDir))
|
|
return profile;
|
|
|
|
// Keep on looking...
|
|
}
|
|
}
|
|
return TQString();
|
|
}
|
|
|
|
TQStringList
|
|
KioskRun::allProfiles()
|
|
{
|
|
KConfig *config = kapp->config();
|
|
TQStringList groups = config->groupList();
|
|
TQStringList profiles;
|
|
TQStringList directories;
|
|
for(TQStringList::ConstIterator it = groups.begin();
|
|
it != groups.end(); ++it)
|
|
{
|
|
if (!(*it).startsWith("Directories-"))
|
|
continue;
|
|
profiles.append((*it).mid(12));
|
|
config->setGroup(*it);
|
|
TQString installDir = config->readEntry("prefixes");
|
|
if (!installDir.endsWith("/"))
|
|
installDir.append("/");
|
|
directories.append(installDir);
|
|
}
|
|
|
|
TQString profilePrefix = getProfilePrefix();
|
|
if (!profilePrefix.isEmpty())
|
|
{
|
|
TQDir dir(profilePrefix, TQString(), TQDir::Unsorted, TQDir::Dirs);
|
|
TQStringList profileDirs = dir.entryList();
|
|
for(TQStringList::ConstIterator it = profileDirs.begin();
|
|
it != profileDirs.end(); ++it)
|
|
{
|
|
if ((*it).startsWith("."))
|
|
continue;
|
|
TQString dir = profilePrefix + *it + "/";
|
|
if (directories.contains(dir))
|
|
{
|
|
kdDebug() << "Skipping " << dir << ", dir already listed" << endl;
|
|
continue;
|
|
}
|
|
if (profiles.contains(*it))
|
|
{
|
|
kdDebug() << "Skipping " << dir << ", profile [" << (*it) << "] already listed" << endl;
|
|
continue;
|
|
}
|
|
|
|
if (!TQFile::exists(dir+".kdeprofile"))
|
|
{
|
|
kdDebug() << "Skipping " << dir << ", no profile info" << endl;
|
|
continue;
|
|
}
|
|
profiles.append(*it);
|
|
directories.append(dir);
|
|
}
|
|
}
|
|
|
|
if (!profiles.contains("default"))
|
|
profiles.append("default");
|
|
|
|
return profiles;
|
|
}
|
|
|
|
void
|
|
KioskRun::getUserProfileMappings( ProfileMapping &groups, ProfileMapping &users, TQStringList &groupOrder)
|
|
{
|
|
groups.clear();
|
|
users.clear();
|
|
|
|
KConfig *config = kapp->config();
|
|
config->setGroup("Directories");
|
|
TQString mapFile = config->readEntry("userProfileMapFile");
|
|
|
|
if (mapFile.isEmpty() || !TQFile::exists(mapFile))
|
|
return;
|
|
|
|
KSimpleConfig mapCfg(mapFile, true);
|
|
|
|
mapCfg.setGroup("General");
|
|
groupOrder = mapCfg.readListEntry("groups");
|
|
|
|
mapCfg.setGroup("Groups");
|
|
for ( TQStringList::ConstIterator it = groupOrder.begin();
|
|
it != groupOrder.end(); ++it )
|
|
{
|
|
TQString group = *it;
|
|
TQStringList profiles = mapCfg.readListEntry(group);
|
|
if (!profiles.isEmpty())
|
|
groups.insert(group, profiles);
|
|
}
|
|
|
|
TQMap<TQString, TQString> cfg_users = mapCfg.entryMap("Users");
|
|
for ( TQMap<TQString, TQString>::Iterator it = cfg_users.begin();
|
|
it != cfg_users.end(); ++it )
|
|
{
|
|
TQString user = it.key();
|
|
TQStringList profiles = TQStringList::split(",", it.data());
|
|
if (!profiles.isEmpty())
|
|
users.insert(user, profiles);
|
|
}
|
|
}
|
|
|
|
bool
|
|
KioskRun::setUserProfileMappings( const ProfileMapping &groups, const ProfileMapping &users, const TQStringList &groupOrder)
|
|
{
|
|
KConfig *config = kapp->config();
|
|
config->setGroup("Directories");
|
|
TQString mapFile = config->readEntry("userProfileMapFile");
|
|
if (mapFile.isEmpty())
|
|
{
|
|
mapFile = "/etc/kde-user-profile";
|
|
|
|
KSimpleConfig *cfg = openKderc();
|
|
if (!cfg)
|
|
return false;
|
|
|
|
cfg->setGroup("Directories");
|
|
cfg->writeEntry("userProfileMapFile", mapFile);
|
|
if (!closeKderc())
|
|
return false;
|
|
}
|
|
|
|
TQString localMapFile = ::locateLocal("tmp", "kde-user-profile_"+kapp->randomString(5));
|
|
::unlink(TQFile::encodeName(localMapFile));
|
|
|
|
KSimpleConfig mapConfig(localMapFile);
|
|
|
|
mapConfig.setGroup("General");
|
|
mapConfig.writeEntry("groups", groupOrder);
|
|
|
|
KioskRun::ProfileMapping::ConstIterator it;
|
|
|
|
mapConfig.setGroup("Groups");
|
|
for ( it = groups.begin(); it != groups.end(); ++it )
|
|
{
|
|
TQString group = it.key();
|
|
mapConfig.writeEntry(group, it.data());
|
|
}
|
|
mapConfig.setGroup("Users");
|
|
for ( it = users.begin(); it != users.end(); ++it )
|
|
{
|
|
TQString user = it.key();
|
|
mapConfig.writeEntry(user, it.data());
|
|
}
|
|
|
|
mapConfig.sync();
|
|
|
|
TQString saveUser = m_user;
|
|
m_user = "root";
|
|
bool result = install(localMapFile, mapFile);
|
|
m_user = saveUser;
|
|
return result;
|
|
}
|
|
|
|
void
|
|
KioskRun::forceSycocaUpdate()
|
|
{
|
|
// Touch $TDEDIR/share/services/update_ksycoca
|
|
KTempFile tempFile;
|
|
tempFile.close();
|
|
TQString sycocaUpdateFile = locateSave("services", "update_ksycoca");
|
|
remove(sycocaUpdateFile);
|
|
install(tempFile.name(), sycocaUpdateFile);
|
|
}
|
|
|
|
void
|
|
KioskRun::scheduleSycocaUpdate()
|
|
{
|
|
m_forceSycocaUpdate = true;
|
|
}
|
|
|
|
void
|
|
KioskRun::setCustomRestrictionFileBrowsing(bool restrict)
|
|
{
|
|
TQString file = "kdeglobals";
|
|
TQString group = "KDE URL Restrictions";
|
|
KConfig *cfg = KioskRun::self()->configFile(file);
|
|
cfg->setGroup(group);
|
|
int count = cfg->readNumEntry("rule_count");
|
|
TQStringList urlRestrictions;
|
|
for(int i = 0; i < count; i++)
|
|
{
|
|
TQString key = TQString("rule_%1").arg(i+1);
|
|
if (cfg->hasKey(key))
|
|
urlRestrictions.append(cfg->readEntry(key));
|
|
}
|
|
|
|
TQStringList newRestrictions;
|
|
newRestrictions << "list,,,,file,,,false";
|
|
newRestrictions << "list,,,,file,,$HOME,true";
|
|
|
|
for(TQStringList::ConstIterator it = newRestrictions.begin();
|
|
it != newRestrictions.end(); ++it)
|
|
{
|
|
urlRestrictions.remove(*it);
|
|
}
|
|
|
|
if (restrict)
|
|
{
|
|
newRestrictions += urlRestrictions;
|
|
urlRestrictions = newRestrictions;
|
|
}
|
|
|
|
count = urlRestrictions.count();
|
|
cfg->writeEntry("rule_count", count);
|
|
|
|
for(int i = 0; i < count; i++)
|
|
{
|
|
TQString key = TQString("rule_%1").arg(i+1);
|
|
cfg->writeEntry(key, urlRestrictions[i]);
|
|
}
|
|
KioskRun::self()->setConfigImmutable(file, group, true);
|
|
}
|
|
|
|
KioskRunProgressDialog::KioskRunProgressDialog(TQWidget *parent, const char *name,
|
|
const TQString &caption, const TQString &text)
|
|
: KProgressDialog(parent, name, caption, text, true)
|
|
{
|
|
connect(&m_timer, TQT_SIGNAL(timeout()), this, TQT_SLOT(slotProgress()));
|
|
progressBar()->setTotalSteps(20);
|
|
m_timeStep = 700;
|
|
m_timer.start(m_timeStep);
|
|
setAutoClose(false);
|
|
}
|
|
|
|
void
|
|
KioskRunProgressDialog::slotProgress()
|
|
{
|
|
int p = progressBar()->progress();
|
|
if (p == 18)
|
|
{
|
|
progressBar()->reset();
|
|
progressBar()->setProgress(1);
|
|
m_timeStep = m_timeStep * 2;
|
|
m_timer.start(m_timeStep);
|
|
}
|
|
else
|
|
{
|
|
progressBar()->setProgress(p+1);
|
|
}
|
|
}
|
|
|
|
void
|
|
KioskRunProgressDialog::slotFinished()
|
|
{
|
|
progressBar()->setProgress(20);
|
|
m_timer.stop();
|
|
TQTimer::singleShot(1000, this, TQT_SLOT(close()));
|
|
}
|
|
|
|
|
|
#include "kioskrun.moc"
|
|
|