• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kconf_update

kconf_update.cpp

Go to the documentation of this file.
00001 /*
00002  *
00003  *  This file is part of the KDE libraries
00004  *  Copyright (c) 2001 Waldo Bastian <bastian@kde.org>
00005  *
00006  * $Id: kconf_update.cpp 465272 2005-09-29 09:47:40Z mueller $
00007  *
00008  *  This library is free software; you can redistribute it and/or
00009  *  modify it under the terms of the GNU Library General Public
00010  *  License version 2 as published by the Free Software Foundation.
00011  *
00012  *  This library is distributed in the hope that it will be useful,
00013  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  *  Library General Public License for more details.
00016  *
00017  *  You should have received a copy of the GNU Library General Public License
00018  *  along with this library; see the file COPYING.LIB.  If not, write to
00019  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00020  *  Boston, MA 02110-1301, USA.
00021  **/
00022 
00023 #include <sys/types.h>
00024 #include <sys/stat.h>
00025 #include <unistd.h>
00026 #include <stdlib.h>
00027 
00028 #include <qfile.h>
00029 #include <qtextstream.h>
00030 
00031 #include <kconfig.h>
00032 #include <ksimpleconfig.h>
00033 #include <klocale.h>
00034 #include <kcmdlineargs.h>
00035 #include <kglobal.h>
00036 #include <kstandarddirs.h>
00037 #include <kaboutdata.h>
00038 #include <kinstance.h>
00039 #include <ktempfile.h>
00040 
00041 static KCmdLineOptions options[] =
00042 {
00043         { "debug", I18N_NOOP("Keep output results from scripts"), 0 },
00044     { "check <update-file>", I18N_NOOP("Check whether config file itself requires updating"), 0 },
00045     { "+[file]", I18N_NOOP("File to read update instructions from"), 0 },
00046         KCmdLineLastOption
00047 };
00048 
00049 class KonfUpdate
00050 {
00051 public:
00052    KonfUpdate();
00053    ~KonfUpdate();
00054    QStringList findUpdateFiles(bool dirtyOnly);
00055 
00056    QTextStream &log();
00057 
00058    bool checkFile(const QString &filename);
00059    void checkGotFile(const QString &_file, const QString &id);
00060 
00061    bool updateFile(const QString &filename);
00062 
00063    void gotId(const QString &_id);
00064    void gotFile(const QString &_file);
00065    void gotGroup(const QString &_group);
00066    void gotRemoveGroup(const QString &_group);
00067    void gotKey(const QString &_key);
00068    void gotRemoveKey(const QString &_key);
00069    void gotAllKeys();
00070    void gotAllGroups();
00071    void gotOptions(const QString &_options);
00072    void gotScript(const QString &_script);
00073    void gotScriptArguments(const QString &_arguments);
00074    void resetOptions();
00075 
00076    void copyGroup(KConfigBase *cfg1, const QString &grp1, 
00077                   KConfigBase *cfg2, const QString &grp2);
00078 
00079 protected:
00080    KConfig *config;
00081    QString currentFilename;
00082    bool skip;
00083    bool debug;
00084    QString id;
00085 
00086    QString oldFile;
00087    QString newFile;
00088    QString newFileName;
00089    KConfig *oldConfig1; // Config to read keys from.
00090    KConfig *oldConfig2; // Config to delete keys from.
00091    KConfig *newConfig;
00092 
00093    QString oldGroup;
00094    QString newGroup;
00095    QString oldKey;
00096    QString newKey;
00097 
00098    bool m_bCopy;
00099    bool m_bOverwrite;
00100    bool m_bUseConfigInfo;
00101    QString m_arguments;
00102    QTextStream *m_textStream;
00103    QFile *m_file;
00104    QString m_line;
00105    int m_lineCount;
00106 };
00107 
00108 KonfUpdate::KonfUpdate()
00109  : m_textStream(0), m_file(0)
00110 {
00111    bool updateAll = false;
00112    oldConfig1 = 0;
00113    oldConfig2 = 0;
00114    newConfig = 0;
00115 
00116    config = new KConfig("kconf_updaterc");
00117 
00118    QStringList updateFiles;
00119    KCmdLineArgs *args=KCmdLineArgs::parsedArgs();
00120    
00121    debug = args->isSet("debug");
00122 
00123    m_bUseConfigInfo = false;
00124    if (args->isSet("check"))
00125    {
00126       m_bUseConfigInfo = true;
00127       QString file = locate("data", "kconf_update/"+QFile::decodeName(args->getOption("check")));
00128       if (file.isEmpty())
00129       {
00130          qWarning("File '%s' not found.", args->getOption("check").data());
00131          log() << "File '" << QFile::decodeName(args->getOption("check")) << "' passed on command line not found" << endl;
00132          return;
00133       }
00134       updateFiles.append(file);
00135    }
00136    else if (args->count())
00137    {
00138       for(int i = 0; i < args->count(); i++)
00139       {
00140          KURL url = args->url(i);
00141          if (!url.isLocalFile())
00142             KCmdLineArgs::usage(i18n("Only local files are supported."));
00143          updateFiles.append(url.path());
00144       }
00145    }
00146    else
00147    {
00148       if (config->readBoolEntry("autoUpdateDisabled", false))
00149          return;
00150       updateFiles = findUpdateFiles(true);
00151       updateAll = true;
00152    }
00153 
00154    for(QStringList::ConstIterator it = updateFiles.begin();
00155        it != updateFiles.end();
00156        ++it)
00157    {
00158       QString file = *it;
00159       updateFile(file);
00160    }
00161 
00162    config->setGroup(QString::null);
00163    if (updateAll && !config->readBoolEntry("updateInfoAdded", false))
00164    {
00165        config->writeEntry("updateInfoAdded", true);
00166        updateFiles = findUpdateFiles(false);
00167 
00168        for(QStringList::ConstIterator it = updateFiles.begin();
00169            it != updateFiles.end();
00170            ++it)
00171        {
00172            QString file = *it;
00173            checkFile(file);
00174        }
00175        updateFiles.clear();
00176    }
00177 }
00178 
00179 KonfUpdate::~KonfUpdate()
00180 {
00181    delete config;
00182    delete m_file;
00183    delete m_textStream;
00184 }
00185 
00186 QTextStream &
00187 KonfUpdate::log()
00188 {
00189    if (!m_textStream)
00190    {
00191       QString file = locateLocal("data", "kconf_update/log/update.log");
00192       m_file = new QFile(file);
00193       if (m_file->open(IO_WriteOnly | IO_Append))
00194       {
00195         m_textStream = new QTextStream(m_file);
00196       }
00197       else
00198       {
00199         // Error
00200         m_textStream = new QTextStream(stderr, IO_WriteOnly);
00201       }
00202    }
00203    
00204    (*m_textStream) << QDateTime::currentDateTime().toString( Qt::ISODate ) << " ";
00205    
00206    return *m_textStream;
00207 }
00208 
00209 QStringList KonfUpdate::findUpdateFiles(bool dirtyOnly)
00210 {
00211    QStringList result;
00212    QStringList list = KGlobal::dirs()->findAllResources("data", "kconf_update/*.upd", false, true);
00213    for(QStringList::ConstIterator it = list.begin();
00214        it != list.end();
00215        ++it)
00216    {
00217       QString file = *it;
00218       struct stat buff;
00219       if (stat( QFile::encodeName(file), &buff) == 0)
00220       {
00221          int i = file.findRev('/');
00222          if (i != -1) 
00223             file = file.mid(i+1);
00224          config->setGroup(file);
00225          time_t ctime = config->readUnsignedLongNumEntry("ctime");
00226          time_t mtime = config->readUnsignedLongNumEntry("mtime");
00227          if (!dirtyOnly ||
00228              (ctime != buff.st_ctime) || (mtime != buff.st_mtime))
00229          {
00230             result.append(*it);
00231          }
00232       }
00233    }
00234    return result;
00235 }
00236 
00237 bool KonfUpdate::checkFile(const QString &filename)
00238 {
00239    currentFilename = filename;
00240    int i = currentFilename.findRev('/');
00241    if (i != -1) 
00242       currentFilename = currentFilename.mid(i+1);
00243    skip = true;
00244    QFile file(filename);
00245    if (!file.open(IO_ReadOnly))
00246       return false;
00247 
00248    QTextStream ts(&file);
00249    ts.setEncoding(QTextStream::Latin1);
00250    int lineCount = 0;
00251    resetOptions();
00252    QString id;
00253    while(!ts.atEnd())
00254    {
00255       QString line = ts.readLine().stripWhiteSpace();
00256       lineCount++;
00257       if (line.isEmpty() || (line[0] == '#'))
00258          continue;
00259       if (line.startsWith("Id="))
00260          id = currentFilename+":"+line.mid(3);
00261       else if (line.startsWith("File="))
00262          checkGotFile(line.mid(5), id);
00263    }
00264   
00265    return true;
00266 }
00267 
00268 void KonfUpdate::checkGotFile(const QString &_file, const QString &id)
00269 {
00270    QString file;
00271    int i = _file.find(',');
00272    if (i == -1)
00273    {
00274       file = _file.stripWhiteSpace();
00275    }
00276    else
00277    {
00278       file = _file.mid(i+1).stripWhiteSpace();
00279    }
00280 
00281 //   qDebug("File %s, id %s", file.latin1(), id.latin1());
00282 
00283    KSimpleConfig cfg(file);
00284    cfg.setGroup("$Version");
00285    QStringList ids = cfg.readListEntry("update_info");
00286    if (ids.contains(id))
00287        return;
00288    ids.append(id);
00289    cfg.writeEntry("update_info", ids);
00290 }
00291 
00311 bool KonfUpdate::updateFile(const QString &filename)
00312 {
00313    currentFilename = filename;
00314    int i = currentFilename.findRev('/');
00315    if (i != -1) 
00316        currentFilename = currentFilename.mid(i+1);
00317    skip = true;
00318    QFile file(filename);
00319    if (!file.open(IO_ReadOnly))
00320       return false;
00321 
00322    log() << "Checking update-file '" << filename << "' for new updates" << endl; 
00323 
00324    QTextStream ts(&file);
00325    ts.setEncoding(QTextStream::Latin1);
00326    m_lineCount = 0;
00327    resetOptions();
00328    while(!ts.atEnd())
00329    {
00330       m_line = ts.readLine().stripWhiteSpace();
00331       m_lineCount++;
00332       if (m_line.isEmpty() || (m_line[0] == '#'))
00333          continue;
00334       if (m_line.startsWith("Id="))
00335          gotId(m_line.mid(3));
00336       else if (skip)
00337          continue;
00338       else if (m_line.startsWith("Options="))
00339          gotOptions(m_line.mid(8));
00340       else if (m_line.startsWith("File="))
00341          gotFile(m_line.mid(5));
00342       else if (m_line.startsWith("Group="))
00343          gotGroup(m_line.mid(6));
00344       else if (m_line.startsWith("RemoveGroup="))
00345       {
00346          gotRemoveGroup(m_line.mid(12));
00347          resetOptions();
00348       }
00349       else if (m_line.startsWith("Script="))
00350       {
00351          gotScript(m_line.mid(7));
00352          resetOptions();
00353       }
00354       else if (m_line.startsWith("ScriptArguments="))
00355          gotScriptArguments(m_line.mid(16));
00356       else if (m_line.startsWith("Key="))
00357       {
00358          gotKey(m_line.mid(4));
00359          resetOptions();
00360       }
00361       else if (m_line.startsWith("RemoveKey="))
00362       {
00363          gotRemoveKey(m_line.mid(10));
00364          resetOptions();
00365       }
00366       else if (m_line == "AllKeys")
00367       {
00368          gotAllKeys();
00369          resetOptions();
00370       }
00371       else if (m_line == "AllGroups")
00372       {
00373          gotAllGroups();
00374          resetOptions();
00375       }
00376       else
00377       {
00378          log() << currentFilename << ": parse error in line " << m_lineCount << " : '" << m_line << "'" << endl;
00379       }
00380    }
00381    // Flush.
00382    gotId(QString::null);
00383   
00384    struct stat buff;
00385    stat( QFile::encodeName(filename), &buff);
00386    config->setGroup(currentFilename);
00387    config->writeEntry("ctime", buff.st_ctime);
00388    config->writeEntry("mtime", buff.st_mtime);
00389    config->sync();
00390    return true;
00391 }
00392 
00393 
00394 
00395 void KonfUpdate::gotId(const QString &_id)
00396 {
00397    if (!id.isEmpty() && !skip)
00398    {
00399        config->setGroup(currentFilename);
00400        QStringList ids = config->readListEntry("done");
00401        if (!ids.contains(id))
00402        {
00403           ids.append(id);
00404           config->writeEntry("done", ids);
00405           config->sync();
00406        }
00407    }
00408 
00409    // Flush pending changes
00410    gotFile(QString::null);
00411 
00412    config->setGroup(currentFilename);
00413    QStringList ids = config->readListEntry("done");
00414    if (!_id.isEmpty())
00415    {
00416        if (ids.contains(_id))
00417        {
00418           //qDebug("Id '%s' was already in done-list", _id.latin1());
00419           if (!m_bUseConfigInfo)
00420           {
00421              skip = true;
00422              return;
00423           }
00424        }
00425        skip = false;
00426        id = _id;
00427        if (m_bUseConfigInfo)
00428           log() << currentFilename << ": Checking update '" << _id << "'" << endl;
00429        else
00430           log() << currentFilename << ": Found new update '" << _id << "'" << endl;
00431    }
00432 }
00433 
00434 void KonfUpdate::gotFile(const QString &_file)
00435 {
00436    // Reset group
00437    gotGroup(QString::null);
00438  
00439    if (!oldFile.isEmpty())
00440    {
00441       // Close old file.
00442       delete oldConfig1;
00443       oldConfig1 = 0;
00444 
00445       oldConfig2->setGroup("$Version");
00446       QStringList ids = oldConfig2->readListEntry("update_info");
00447       QString cfg_id = currentFilename + ":" + id;
00448       if (!ids.contains(cfg_id) && !skip)
00449       {
00450          ids.append(cfg_id);
00451          oldConfig2->writeEntry("update_info", ids);
00452       }
00453       oldConfig2->sync();
00454       delete oldConfig2;
00455       oldConfig2 = 0;
00456       
00457       QString file = locateLocal("config", oldFile);
00458       struct stat s_buf;
00459       if (stat(QFile::encodeName(file), &s_buf) == 0)
00460       {
00461          if (s_buf.st_size == 0)
00462          {
00463             // Delete empty file.
00464             unlink(QFile::encodeName(file));
00465          }   
00466       }
00467 
00468       oldFile = QString::null;
00469    }
00470    if (!newFile.isEmpty())
00471    {
00472       // Close new file.
00473       newConfig->setGroup("$Version");
00474       QStringList ids = newConfig->readListEntry("update_info");
00475       QString cfg_id = currentFilename + ":" + id;
00476       if (!ids.contains(cfg_id) && !skip)
00477       {
00478          ids.append(cfg_id);
00479          newConfig->writeEntry("update_info", ids);
00480       }
00481       newConfig->sync();
00482       delete newConfig;
00483       newConfig = 0;
00484 
00485       newFile = QString::null;
00486    }
00487    newConfig = 0; 
00488 
00489    int i = _file.find(',');
00490    if (i == -1)
00491    {
00492       oldFile = _file.stripWhiteSpace();
00493    }
00494    else
00495    {
00496       oldFile = _file.left(i).stripWhiteSpace();
00497       newFile = _file.mid(i+1).stripWhiteSpace();
00498       if (oldFile == newFile)
00499          newFile = QString::null;
00500    }
00501    
00502    if (!oldFile.isEmpty())
00503    {
00504       oldConfig2 = new KConfig(oldFile, false, false);
00505       QString cfg_id = currentFilename + ":" + id;
00506       oldConfig2->setGroup("$Version");
00507       QStringList ids = oldConfig2->readListEntry("update_info");
00508       if (ids.contains(cfg_id))
00509       {
00510          skip = true;
00511          newFile = QString::null;
00512          log() << currentFilename << ": Skipping update '" << id << "'" << endl;
00513       }
00514 
00515       if (!newFile.isEmpty())
00516       {
00517          newConfig = new KConfig(newFile, false, false);
00518          newConfig->setGroup("$Version");
00519          ids = newConfig->readListEntry("update_info");
00520          if (ids.contains(cfg_id))
00521          {
00522             skip = true;
00523             log() << currentFilename << ": Skipping update '" << id << "'" << endl;
00524          }
00525       }
00526       else
00527       {
00528          newConfig = oldConfig2;
00529       }
00530 
00531       oldConfig1 = new KConfig(oldFile, true, false);
00532    }
00533    else
00534    {
00535       newFile = QString::null;
00536    }
00537    newFileName = newFile;
00538    if (newFileName.isEmpty())
00539       newFileName = oldFile;
00540 }
00541 
00542 void KonfUpdate::gotGroup(const QString &_group)
00543 {
00544    int i = _group.find(',');
00545    if (i == -1)
00546    {
00547       oldGroup = _group.stripWhiteSpace();
00548       newGroup = oldGroup;
00549    }
00550    else
00551    {
00552       oldGroup = _group.left(i).stripWhiteSpace();
00553       newGroup = _group.mid(i+1).stripWhiteSpace();
00554    }
00555 }
00556 
00557 void KonfUpdate::gotRemoveGroup(const QString &_group)
00558 {
00559    oldGroup = _group.stripWhiteSpace();
00560 
00561    if (!oldConfig1)
00562    {
00563       log() << currentFilename << ": !! RemoveGroup without previous File specification in line " << m_lineCount << " : '" << m_line << "'" << endl;
00564       return;
00565    }
00566 
00567    if (!oldConfig1->hasGroup(oldGroup))
00568       return;
00569    // Delete group.
00570    oldConfig2->deleteGroup(oldGroup, true);
00571    log() << currentFilename << ": RemoveGroup removes group " << oldFile << ":" << oldGroup << endl;
00572 }
00573 
00574 
00575 void KonfUpdate::gotKey(const QString &_key)
00576 {
00577    int i = _key.find(',');
00578    if (i == -1)
00579    {
00580       oldKey = _key.stripWhiteSpace();
00581       newKey = oldKey;
00582    }
00583    else
00584    {
00585       oldKey = _key.left(i).stripWhiteSpace();
00586       newKey = _key.mid(i+1).stripWhiteSpace();
00587    }
00588 
00589    if (oldKey.isEmpty() || newKey.isEmpty())
00590    {
00591       log() << currentFilename << ": !! Key specifies invalid key in line " << m_lineCount << " : '" << m_line << "'" << endl;
00592       return;
00593    }
00594    if (!oldConfig1)
00595    {
00596       log() << currentFilename << ": !! Key without previous File specification in line " << m_lineCount << " : '" << m_line << "'" << endl;
00597       return;
00598    }
00599    oldConfig1->setGroup(oldGroup);
00600    if (!oldConfig1->hasKey(oldKey))
00601       return;
00602    QString value = oldConfig1->readEntry(oldKey);
00603    newConfig->setGroup(newGroup);
00604    if (!m_bOverwrite && newConfig->hasKey(newKey))
00605    {
00606       log() << currentFilename << ": Skipping " << newFileName << ":" << newGroup << ":" << newKey << ", already exists."<< endl;
00607       return;
00608    }
00609    log() << currentFilename << ": Updating " << newFileName << ":" << newGroup << ":" << newKey << " to '" << value << "'" << endl;
00610    newConfig->writeEntry(newKey, value);
00611 
00612    if (m_bCopy)
00613       return; // Done.
00614 
00615    // Delete old entry
00616    if ((oldConfig2 == newConfig) && 
00617        (oldGroup == newGroup) &&
00618        (oldKey == newKey))
00619       return; // Don't delete!
00620    oldConfig2->setGroup(oldGroup);
00621    oldConfig2->deleteEntry(oldKey, false);
00622    log() << currentFilename << ": Removing " << oldFile << ":" << oldGroup << ":" << oldKey << ", moved." << endl;
00623    if (oldConfig2->deleteGroup(oldGroup, false)) { // Delete group if empty.
00624       log() << currentFilename << ": Removing empty group " << oldFile << ":" << oldGroup << endl;
00625    }
00626 }
00627 
00628 void KonfUpdate::gotRemoveKey(const QString &_key)
00629 {
00630    oldKey = _key.stripWhiteSpace();
00631 
00632    if (oldKey.isEmpty())
00633    {
00634       log() << currentFilename << ": !! RemoveKey specifies invalid key in line " << m_lineCount << " : '" << m_line << "'" << endl;
00635       return;
00636    }
00637 
00638    if (!oldConfig1)
00639    {
00640       log() << currentFilename << ": !! Key without previous File specification in line " << m_lineCount << " : '" << m_line << "'" << endl;
00641       return;
00642    }
00643 
00644    oldConfig1->setGroup(oldGroup);
00645    if (!oldConfig1->hasKey(oldKey))
00646       return;
00647    log() << currentFilename << ": RemoveKey removes " << oldFile << ":" << oldGroup << ":" << oldKey << endl;
00648 
00649    // Delete old entry
00650    oldConfig2->setGroup(oldGroup);
00651    oldConfig2->deleteEntry(oldKey, false);
00652    if (oldConfig2->deleteGroup(oldGroup, false)) { // Delete group if empty.
00653       log() << currentFilename << ": Removing empty group " << oldFile << ":" << oldGroup << endl;
00654    }
00655 }
00656 
00657 void KonfUpdate::gotAllKeys()
00658 {
00659    if (!oldConfig1)
00660    {
00661       log() << currentFilename << ": !! AllKeys without previous File specification in line " << m_lineCount << " : '" << m_line << "'" << endl;
00662       return;
00663    }
00664 
00665    QMap<QString, QString> list = oldConfig1->entryMap(oldGroup);
00666    for(QMap<QString, QString>::Iterator it = list.begin();
00667        it != list.end(); ++it)
00668    {
00669       gotKey(it.key());
00670    }
00671 }
00672 
00673 void KonfUpdate::gotAllGroups()
00674 {
00675    if (!oldConfig1)
00676    {
00677       log() << currentFilename << ": !! AllGroups without previous File specification in line " << m_lineCount << " : '" << m_line << "'" << endl;
00678       return;
00679    }
00680 
00681    QStringList allGroups = oldConfig1->groupList();
00682    for(QStringList::ConstIterator it = allGroups.begin();
00683        it != allGroups.end(); ++it)
00684    {
00685      oldGroup = *it;
00686      newGroup = oldGroup;
00687      gotAllKeys();
00688    }
00689 }
00690 
00691 void KonfUpdate::gotOptions(const QString &_options)
00692 {
00693    QStringList options = QStringList::split(',', _options);
00694    for(QStringList::ConstIterator it = options.begin();
00695        it != options.end();
00696        ++it)
00697    {
00698        if ( (*it).lower().stripWhiteSpace() == "copy")
00699           m_bCopy = true;
00700 
00701        if ( (*it).lower().stripWhiteSpace() == "overwrite")
00702           m_bOverwrite = true;
00703    }
00704 }
00705 
00706 void KonfUpdate::copyGroup(KConfigBase *cfg1, const QString &grp1, 
00707                            KConfigBase *cfg2, const QString &grp2)
00708 {
00709    cfg1->setGroup(grp1);
00710    cfg2->setGroup(grp2);
00711    QMap<QString, QString> list = cfg1->entryMap(grp1);
00712    for(QMap<QString, QString>::Iterator it = list.begin();
00713        it != list.end(); ++it)
00714    {
00715       cfg2->writeEntry(it.key(), cfg1->readEntry(it.key()));
00716    }
00717 }
00718 
00719 void KonfUpdate::gotScriptArguments(const QString &_arguments)
00720 {
00721    m_arguments = _arguments;
00722 }
00723 
00724 void KonfUpdate::gotScript(const QString &_script)
00725 {
00726    QString script, interpreter;
00727    int i = _script.find(',');
00728    if (i == -1)
00729    {
00730       script = _script.stripWhiteSpace();
00731    }
00732    else
00733    {
00734       script = _script.left(i).stripWhiteSpace();
00735       interpreter = _script.mid(i+1).stripWhiteSpace();
00736    }
00737 
00738 
00739    if (script.isEmpty())
00740    {
00741       log() << currentFilename << ": !! Script fails to specifiy filename in line " << m_lineCount << " : '" << m_line << "'" << endl;
00742       skip = true;
00743       return;
00744    } 
00745 
00746 
00747 
00748    QString path = locate("data","kconf_update/"+script);
00749    if (path.isEmpty())
00750    {
00751       if (interpreter.isEmpty())
00752          path = locate("lib", "kconf_update_bin/"+script);
00753 
00754       if (path.isEmpty())
00755       {
00756         log() << currentFilename << ": !! Script '" << script << "' not found in line " << m_lineCount << " : '" << m_line << "'" << endl;
00757         skip = true;
00758         return;
00759       }
00760    }
00761 
00762    if( !m_arguments.isNull())
00763       log() << currentFilename << ": Running script '" << script << "' with arguments '" << m_arguments << "'" << endl;
00764    else
00765       log() << currentFilename << ": Running script '" << script << "'" << endl;
00766 
00767    QString cmd;
00768    if (interpreter.isEmpty())
00769       cmd = path;
00770    else
00771       cmd = interpreter + " " + path;
00772 
00773    if( !m_arguments.isNull())
00774    {
00775       cmd += ' ';
00776       cmd += m_arguments;
00777    }
00778 
00779    KTempFile tmp1;
00780    tmp1.setAutoDelete(true);
00781    KTempFile tmp2;
00782    tmp2.setAutoDelete(true);
00783    KTempFile tmp3;
00784    tmp3.setAutoDelete(true);
00785 
00786    int result;
00787    if (oldConfig1)
00788    {
00789        if (debug)
00790        {
00791            tmp1.setAutoDelete(false);
00792            log() << "Script input stored in " << tmp1.name() << endl;
00793        }
00794        KSimpleConfig cfg(tmp1.name());
00795 
00796        if (oldGroup.isEmpty())
00797        {
00798            // Write all entries to tmpFile;
00799            QStringList grpList = oldConfig1->groupList();
00800            for(QStringList::ConstIterator it = grpList.begin();
00801                it != grpList.end();
00802                ++it)
00803            {
00804                copyGroup(oldConfig1, *it, &cfg, *it);
00805            }
00806        }
00807        else 
00808        {
00809            copyGroup(oldConfig1, oldGroup, &cfg, QString::null);
00810        }
00811        cfg.sync();
00812        result = system(QFile::encodeName(QString("%1 < %2 > %3 2> %4").arg(cmd, tmp1.name(), tmp2.name(), tmp3.name())));
00813    }
00814    else
00815    {
00816        // No config file
00817        result = system(QFile::encodeName(QString("%1 2> %2").arg(cmd, tmp3.name())));
00818    }
00819 
00820    // Copy script stderr to log file
00821    {
00822      QFile output(tmp3.name());
00823      if (output.open(IO_ReadOnly))
00824      { 
00825        QTextStream ts( &output );
00826        ts.setEncoding(QTextStream::UnicodeUTF8);
00827        while(!ts.atEnd())
00828        {
00829          QString line = ts.readLine();
00830          log() << "[Script] " << line << endl;
00831        }
00832      }
00833    }
00834 
00835    if (result)
00836    {
00837       log() << currentFilename << ": !! An error occured while running '" << cmd << "'" << endl;
00838       return;
00839    }
00840 
00841    if (!oldConfig1)
00842       return; // Nothing to merge
00843 
00844    if (debug)
00845    {
00846       tmp2.setAutoDelete(false);
00847       log() << "Script output stored in " << tmp2.name() << endl;
00848    }
00849 
00850    // Deleting old entries
00851    {
00852      QString group = oldGroup;
00853      QFile output(tmp2.name());
00854      if (output.open(IO_ReadOnly))
00855      { 
00856        QTextStream ts( &output );
00857        ts.setEncoding(QTextStream::UnicodeUTF8);
00858        while(!ts.atEnd())
00859        {
00860          QString line = ts.readLine();
00861          if (line.startsWith("["))
00862          {
00863             int j = line.find(']')+1;
00864             if (j > 0)
00865                group = line.mid(1, j-2);
00866          }
00867          else if (line.startsWith("# DELETE "))
00868          {  
00869             QString key = line.mid(9);
00870             if (key[0] == '[')
00871             {
00872                int j = key.find(']')+1;
00873                if (j > 0)
00874                {
00875                   group = key.mid(1,j-2);
00876                   key = key.mid(j);
00877                }
00878             }
00879             oldConfig2->setGroup(group);
00880             oldConfig2->deleteEntry(key, false);
00881             log() << currentFilename << ": Script removes " << oldFile << ":" << group << ":" << key << endl;
00882             if (oldConfig2->deleteGroup(group, false)) { // Delete group if empty.
00883                log() << currentFilename << ": Removing empty group " << oldFile << ":" << group << endl;
00884         }
00885          }
00886          else if (line.startsWith("# DELETEGROUP"))
00887          {
00888             QString key = line.mid(13).stripWhiteSpace();
00889             if (key[0] == '[')
00890             {
00891                int j = key.find(']')+1;
00892                if (j > 0)
00893                {
00894                   group = key.mid(1,j-2);
00895                }
00896             }
00897             if (oldConfig2->deleteGroup(group, true)) { // Delete group
00898                log() << currentFilename << ": Script removes group " << oldFile << ":" << group << endl;
00899         }
00900           }
00901        }
00902      }
00903    }
00904 
00905    // Merging in new entries.
00906    m_bCopy = true;
00907    {
00908      KConfig *saveOldConfig1 = oldConfig1;
00909      QString saveOldGroup = oldGroup;
00910      QString saveNewGroup = newGroup;
00911      oldConfig1 = new KConfig(tmp2.name(), true, false);
00912 
00913      // For all groups...
00914      QStringList grpList = oldConfig1->groupList();
00915      for(QStringList::ConstIterator it = grpList.begin();
00916          it != grpList.end();
00917          ++it)
00918      {
00919         oldGroup = *it;
00920         if (oldGroup != "<default>")
00921         {
00922            newGroup = oldGroup;
00923         }
00924         gotAllKeys(); // Copy all keys
00925      }
00926      delete oldConfig1;
00927      oldConfig1 = saveOldConfig1;
00928      oldGroup = saveOldGroup;
00929      newGroup = saveNewGroup;
00930    }
00931 }
00932 
00933 void KonfUpdate::resetOptions()
00934 {
00935    m_bCopy = false;
00936    m_bOverwrite = false;
00937    m_arguments = QString::null;
00938 }
00939 
00940 
00941 extern "C" KDE_EXPORT int kdemain(int argc, char **argv)
00942 {
00943    KAboutData aboutData("kconf_update", I18N_NOOP("KConf Update"),
00944                         "1.0.2",
00945                         I18N_NOOP("KDE Tool for updating user configuration files"),
00946                         KAboutData::License_GPL,
00947                         "(c) 2001, Waldo Bastian");
00948 
00949    aboutData.addAuthor("Waldo Bastian", 0, "bastian@kde.org");
00950 
00951    KCmdLineArgs::init(argc, argv, &aboutData);
00952    KCmdLineArgs::addCmdLineOptions(options);
00953 
00954    KInstance instance(&aboutData);
00955 
00956    KonfUpdate konfUpdate;
00957 
00958    return 0;
00959 }

kconf_update

Skip menu "kconf_update"
  • Main Page
  • File List
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal