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;
}