Source Code (Use browser search to find items of interest.)
Class Index
kdelibs'KConfigINIBackEnd (./kdelibs/kdecore/kconfigbackend.h:145)
class KConfigINIBackEnd : public KConfigBackEnd
{
public:
/**
* Construct a configuration back end.
*
* @param _config Specifies the configuration object which values
* will be passed to as they are read, or from where values
* to be written to will be obtained from.
* @param _fileName The name of the file in which config
* data is stored. All registered configuration directories
* will be looked in in order of decreasing relevance.
* @param _resType the resource type of the fileName specified, _if_
* it is not an absolute path (otherwise this parameter is ignored).
* @param _useKDEGlobals If true, the user's system-wide kdeglobals file
* will be imported into the config object. If false, only
* the filename specified will be dealt with.
*/
KConfigINIBackEnd(KConfigBase *_config, const QString &_fileName,
const QString &_resType, bool _useKDEGlobals = true)
: KConfigBackEnd(_config, _fileName, _resType, _useKDEGlobals) {}
/**
* Destructor.
*/
virtual ~KConfigINIBackEnd() {};
/**
* Parse all INI-style configuration files for a config object.
*
* @returns Whether or not parsing was successful.
*/
bool parseConfigFiles();
/**
* write configuration data to file(s).
*/
virtual void sync(bool bMerge = true);
protected:
/**
* Parse one configuration file.
*
* @param rFile The configuration file to parse
* @param pWriteBackMap If specified, points to a KEntryMap where
* the data read from the file should be stored, instead of
* inserting them directly into the configuration object.
* Use this area as a "scratchpad" when you need to know what is
* on disk but don't want to effect the configuration object.
* @param bGlobal Specifies whether entries should be marked as
* belonging to the global KDE configuration file rather
* than the application-specific KDE configuration file(s).
*/
void parseSingleConfigFile(QFile& rFile, KEntryMap *pWriteBackMap = 0L,
bool bGlobal = false);
/**
* Write configuration file back.
*
* @param filename The name of the file to write.
* @param bGlobal Specifies whether to write only entries which
* are marked as belonging to the global KDE config file.
* If this is false, it skips those entries.
* @param bMerge Specifies whether the old config file already
* on disk should be merged in with the data in memory. If true,
* data is read off the disk and merged. If false, the on-disk
* file is removed and only in-memory data is written out.
* @return Whether some entries are left to be written to other
* files.
*/
bool writeConfigFile(QString filename, bool bGlobal = false, bool bMerge = true);
/**
* Retrieve the state of the app-config object.
*
* @see KConfig::getConfigState
*/
virtual KConfigBase::ConfigState getConfigState() const;
private:
KConfigINIBackEndPrivate *d;
};
kdelibs'KConfigINIBackEnd::parseConfigFiles() (./kdelibs/kdecore/kconfigbackend.cpp:101)
bool KConfigINIBackEnd::parseConfigFiles()
{
// Parse all desired files from the least to the most specific.
// Parse the general config files
if (useKDEGlobals) {
QStringList kdercs = KGlobal::dirs()->
findAllResources("config", QString::fromLatin1("kdeglobals"));
if (checkAccess(QString::fromLatin1("/etc/kderc"), R_OK))
kdercs += QString::fromLatin1("/etc/kderc");
kdercs += KGlobal::dirs()->
findAllResources("config", QString::fromLatin1("system.kdeglobals"));
QStringList::ConstIterator it;
for (it = kdercs.fromLast(); it != kdercs.end(); it--) {
QFile aConfigFile( *it );
aConfigFile.open( IO_ReadOnly );
parseSingleConfigFile( aConfigFile, 0L, true );
aConfigFile.close();
}
}
if (!fileName.isEmpty()) {
// WABA: Why recursive?
// QStringList list = KGlobal::dirs()->
// findAllResources(resType, fileName, true);
QStringList list = KGlobal::dirs()->
findAllResources(resType.latin1(), fileName);
QStringList::ConstIterator it;
for (it = list.fromLast(); it != list.end(); it--) {
QFile aConfigFile( *it );
// we can already be sure that this file exists
aConfigFile.open( IO_ReadOnly );
parseSingleConfigFile( aConfigFile, 0L, false );
aConfigFile.close();
}
}
return true;
}
KConfigBase::ConfigState KConfigINIBackEnd::getConfigState() const
{
if (fileName.isEmpty())
return KConfigBase::NoAccess;
QString aLocalFileName = KGlobal::dirs()->saveLocation("config") +
fileName;
// Can we allow the write? We can, if the program
// doesn't run SUID. But if it runs SUID, we must
// check if the user would be allowed to write if
// it wasn't SUID.
if (checkAccess(aLocalFileName, W_OK|R_OK))
return KConfigBase::ReadWrite;
else
if (checkAccess(aLocalFileName, R_OK))
return KConfigBase::ReadOnly;
return KConfigBase::NoAccess;
}
kdelibs'KConfigINIBackEnd::parseSingleConfigFile() (./kdelibs/kdecore/kconfigbackend.cpp:171)
void KConfigINIBackEnd::parseSingleConfigFile(QFile &rFile,
KEntryMap *pWriteBackMap,
bool bGlobal)
{
if (!rFile.isOpen()) // come back, if you have real work for us ;->
return;
QString aCurrentLine;
QString aCurrentGroup(QString::fromLatin1("<default>"));
// reset the stream's device
rFile.at(0);
QTextStream aStream( &rFile );
aStream.setCodec(QTextCodec::codecForName("utf-8"));
while (!aStream.atEnd()) {
aCurrentLine = aStream.readLine();
// check for a group
int nLeftBracket = aCurrentLine.find( '[' );
int nRightBracket = aCurrentLine.find( ']', 1 );
if( nLeftBracket == 0 && nRightBracket != -1 ) {
// group found; get the group name by taking everything in
// between the brackets
aCurrentGroup =
aCurrentLine.mid( 1, nRightBracket-1 );
if (pWriteBackMap) {
// add the special group key indicator
KEntryKey groupKey(aCurrentGroup, QString::fromLatin1(""));
pWriteBackMap->insert(groupKey, KEntry());
}
continue;
};
if( aCurrentLine[0] == '#' )
// comment character in the first column, skip the line
continue;
int nEqualsPos = aCurrentLine.find( '=' );
if( nEqualsPos == -1 )
// no equals sign: incorrect or empty line, skip it
continue;
// insert the key/value line
QString key = aCurrentLine.left(nEqualsPos).stripWhiteSpace();
QString val = printableToString(aCurrentLine.right(aCurrentLine.length() - nEqualsPos - 1)).stripWhiteSpace();
KEntryKey aEntryKey(aCurrentGroup, key);
KEntry aEntry;
aEntry.aValue = val;
aEntry.bGlobal = bGlobal;
if (pWriteBackMap) {
// don't insert into the config object but into the temporary
// scratchpad map
pWriteBackMap->insert(aEntryKey, aEntry);
} else {
// directly insert value into config object
// no need to specify localization; if the key we just
// retrieved was localized already, no need to localize it again.
pConfig->putData(aEntryKey, aEntry);
}
}
}
kdelibs'KConfigINIBackEnd::sync() (./kdelibs/kdecore/kconfigbackend.cpp:236)
void KConfigINIBackEnd::sync(bool bMerge)
{
// write-sync is only necessary if there are dirty entries
if (!pConfig->isDirty())
return;
bool bEntriesLeft = true;
bool bLocalGood = false;
// find out the file to write to (most specific writable file)
// try local app-specific file first
if (!fileName.isEmpty()) {
QString aLocalFileName;
if (fileName[0] == '/') {
aLocalFileName = fileName;
} else {
aLocalFileName = KGlobal::dirs()->saveLocation("config") + fileName;
}
// Can we allow the write? We can, if the program
// doesn't run SUID. But if it runs SUID, we must
// check if the user would be allowed to write if
// it wasn't SUID.
if (checkAccess(aLocalFileName, W_OK)) {
// is it writable?
bEntriesLeft = writeConfigFile( aLocalFileName, false, bMerge );
bLocalGood = true;
}
}
// only write out entries to the kdeglobals file if there are any
// entries marked global (indicated by bEntriesLeft) and
// the useKDEGlobals flag is set.
if (bEntriesLeft && useKDEGlobals) {
QString aFileName = KGlobal::dirs()->saveLocation("config") +
QString::fromLatin1("kdeglobals");
// can we allow the write? (see above)
if (checkAccess ( aFileName, W_OK )) {
writeConfigFile( aFileName, true, bMerge );
}
}
}
kdelibs'KConfigINIBackEnd::writeConfigFile() (./kdelibs/kdecore/kconfigbackend.cpp:284)
bool KConfigINIBackEnd::writeConfigFile(QString filename, bool bGlobal,
bool bMerge)
{
KEntryMap aTempMap;
bool bEntriesLeft = false;
// is the config object read-only?
if (pConfig->isReadOnly())
return true; // pretend we wrote it
if (bMerge)
{
// Read entries from disk
QFile rConfigFile( filename );
if (rConfigFile.open(IO_ReadOnly))
{
// fill the temporary structure with entries from the file
parseSingleConfigFile( rConfigFile, &aTempMap, bGlobal );
rConfigFile.close();
}
KEntryMap aMap = pConfig->internalEntryMap();
// augment this structure with the dirty entries from the config object
for (KEntryMapIterator aInnerIt = aMap.begin();
aInnerIt != aMap.end(); ++aInnerIt)
{
KEntry currentEntry = *aInnerIt;
if (!currentEntry.bDirty)
continue;
// only write back entries that have the same
// "globality" as the file
if (currentEntry.bGlobal == bGlobal)
{
KEntryKey entryKey = aInnerIt.key();
// put this entry from the config object into the
// temporary map, possibly replacing an existing entry
if (aTempMap.contains(entryKey))
{
aTempMap.replace(entryKey, currentEntry);
}
else
{
// add special group key and then the entry
KEntryKey groupKey(entryKey.group, QString::fromLatin1(""));
if (!aTempMap.contains(groupKey))
aTempMap.insert(groupKey, KEntry());
aTempMap.insert(entryKey, currentEntry);
}
}
else
{
// wrong "globality" - might have to be saved later
bEntriesLeft = true;
}
} // loop
}
else
{
// don't merge, just get the regular entry map and use that.
aTempMap = pConfig->internalEntryMap();
bEntriesLeft = true; // maybe not true, but we aren't sure
}
// OK now the temporary map should be full of ALL entries.
// write it out to disk.
KSaveFile rConfigFile( filename, 0600 );
if (rConfigFile.status() != 0)
return bEntriesLeft;
QTextStream *pStream = rConfigFile.textStream();
pStream->setCodec(QTextCodec::codecForName("utf-8"));
// write back -- start with the default group
KEntryMapConstIterator aWriteIt;
for (aWriteIt = aTempMap.begin(); aWriteIt != aTempMap.end(); ++aWriteIt) {
if ( aWriteIt.key().group == QString::fromLatin1("<default>") && !aWriteIt.key().key.isEmpty() ) {
if ( (*aWriteIt).bNLS &&
aWriteIt.key().key.right(1) != QString::fromLatin1("]"))
// not yet localized, but should be
(*pStream) << aWriteIt.key().key << '['
<< pConfig->locale() << ']' << "="
<< stringToPrintable( (*aWriteIt).aValue) << '\n';
else
// need not be localized or already is
(*pStream) << aWriteIt.key().key << "="
<< stringToPrintable( (*aWriteIt).aValue) << '\n';
}
} // for loop
// now write out all other groups.
QString currentGroup;
for (aWriteIt = aTempMap.begin(); aWriteIt != aTempMap.end(); ++aWriteIt) {
// check if it's not the default group (which has already been written)
if (aWriteIt.key().group == QString::fromLatin1("<default>"))
continue;
if ( currentGroup != aWriteIt.key().group ) {
currentGroup = aWriteIt.key().group;
(*pStream) << '[' << aWriteIt.key().group << ']' << '\n';
}
if (aWriteIt.key().key.isEmpty()) {
// we found a special group key, ignore it
} else {
// it is data for a group
if ( (*aWriteIt).bNLS &&
aWriteIt.key().key.right(1) != QString::fromLatin1("]"))
// not yet localized, but should be
(*pStream) << aWriteIt.key().key << '['
<< pConfig->locale() << ']' << "="
<< stringToPrintable( (*aWriteIt).aValue) << '\n';
else
// need not be localized or already is
(*pStream) << aWriteIt.key().key << "="
<< stringToPrintable( (*aWriteIt).aValue) << '\n';
}
} // for loop
rConfigFile.close();
return bEntriesLeft;
}