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

kconf_update

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
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