• Skip to content
  • Skip to link menu
KDE 4.1 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.begin();
00151        it != updateFiles.end();
00152        ++it)
00153    {
00154       QString file = *it;
00155       updateFile(file);
00156    }
00157 
00158    if (updateAll && !cg.readEntry("updateInfoAdded", false))
00159    {
00160        cg.writeEntry("updateInfoAdded", true);
00161        updateFiles = findUpdateFiles(false);
00162 
00163        for(QStringList::ConstIterator it = updateFiles.begin();
00164            it != updateFiles.end();
00165            ++it)
00166        {
00167            QString file = *it;
00168            checkFile(file);
00169        }
00170        updateFiles.clear();
00171    }
00172 }
00173 
00174 KonfUpdate::~KonfUpdate()
00175 {
00176    delete config;
00177    delete m_file;
00178    delete m_textStream;
00179 }
00180 
00181 QTextStream &
00182 KonfUpdate::log()
00183 {
00184    if (!m_textStream)
00185    {
00186       QString file = KStandardDirs::locateLocal("data", "kconf_update/log/update.log");
00187       m_file = new QFile(file);
00188       if (m_file->open(QIODevice::WriteOnly | QIODevice::Append))
00189       {
00190         m_textStream = new QTextStream(m_file);
00191       }
00192       else
00193       {
00194         // Error
00195         m_textStream = new QTextStream(stderr, QIODevice::WriteOnly);
00196       }
00197    }
00198 
00199    (*m_textStream) << QDateTime::currentDateTime().toString( Qt::ISODate ) << " ";
00200 
00201    return *m_textStream;
00202 }
00203 
00204 QStringList KonfUpdate::findUpdateFiles(bool dirtyOnly)
00205 {
00206    QStringList result;
00207    QStringList list = KGlobal::dirs()->findAllResources("data", "kconf_update/*.upd",
00208                                                         KStandardDirs::NoDuplicates);
00209    for(QStringList::ConstIterator it = list.begin();
00210        it != list.end();
00211        ++it)
00212    {
00213       QString file = *it;
00214       KDE_struct_stat buff;
00215       if (KDE_stat( QFile::encodeName(file), &buff) == 0)
00216       {
00217          int i = file.lastIndexOf('/');
00218          if (i != -1)
00219             file = file.mid(i+1);
00220          KConfigGroup cg(config, file);
00221          time_t ctime = cg.readEntry("ctime", 0);
00222          time_t mtime = cg.readEntry("mtime", 0);
00223          if (!dirtyOnly ||
00224              (ctime != buff.st_ctime) || (mtime != buff.st_mtime))
00225          {
00226             result.append(*it);
00227          }
00228       }
00229    }
00230    return result;
00231 }
00232 
00233 bool KonfUpdate::checkFile(const QString &filename)
00234 {
00235    currentFilename = filename;
00236    int i = currentFilename.lastIndexOf('/');
00237    if (i != -1)
00238       currentFilename = currentFilename.mid(i+1);
00239    skip = true;
00240    QFile file(filename);
00241    if (!file.open(QIODevice::ReadOnly))
00242       return false;
00243 
00244    QTextStream ts(&file);
00245    ts.setCodec(QTextCodec::codecForName("ISO-8859-1"));
00246    int lineCount = 0;
00247    resetOptions();
00248    QString id;
00249    while(!ts.atEnd())
00250    {
00251       QString line = ts.readLine().trimmed();
00252       lineCount++;
00253       if (line.isEmpty() || (line[0] == '#'))
00254          continue;
00255       if (line.startsWith("Id="))
00256          id = currentFilename+':'+line.mid(3);
00257       else if (line.startsWith("File="))
00258          checkGotFile(line.mid(5), id);
00259    }
00260 
00261    return true;
00262 }
00263 
00264 void KonfUpdate::checkGotFile(const QString &_file, const QString &id)
00265 {
00266    QString file;
00267    int i = _file.indexOf(',');
00268    if (i == -1)
00269    {
00270       file = _file.trimmed();
00271    }
00272    else
00273    {
00274       file = _file.mid(i+1).trimmed();
00275    }
00276 
00277 //   qDebug("File %s, id %s", file.toLatin1().constData(), id.toLatin1().constData());
00278 
00279    KConfig cfg(file, KConfig::SimpleConfig);
00280    KConfigGroup cg(&cfg, "$Version");
00281    QStringList ids = cg.readEntry("update_info", QStringList());
00282    if (ids.contains(id))
00283        return;
00284    ids.append(id);
00285    cg.writeEntry("update_info", ids);
00286 }
00287 
00307 bool KonfUpdate::updateFile(const QString &filename)
00308 {
00309    currentFilename = filename;
00310    int i = currentFilename.lastIndexOf('/');
00311    if (i != -1)
00312        currentFilename = currentFilename.mid(i+1);
00313    skip = true;
00314    QFile file(filename);
00315    if (!file.open(QIODevice::ReadOnly))
00316       return false;
00317 
00318    log() << "Checking update-file '" << filename << "' for new updates" << endl;
00319 
00320    QTextStream ts(&file);
00321    ts.setCodec(QTextCodec::codecForName("ISO-8859-1"));
00322    m_lineCount = 0;
00323    resetOptions();
00324    while(!ts.atEnd())
00325    {
00326       m_line = ts.readLine().trimmed();
00327       m_lineCount++;
00328       if (m_line.isEmpty() || (m_line[0] == '#'))
00329          continue;
00330       if (m_line.startsWith("Id="))
00331          gotId(m_line.mid(3));
00332       else if (skip)
00333          continue;
00334       else if (m_line.startsWith("Options="))
00335          gotOptions(m_line.mid(8));
00336       else if (m_line.startsWith("File="))
00337          gotFile(m_line.mid(5));
00338       else if(skipFile)
00339          continue;
00340       else if (m_line.startsWith("Group="))
00341          gotGroup(m_line.mid(6));
00342       else if (m_line.startsWith("RemoveGroup="))
00343       {
00344          gotRemoveGroup(m_line.mid(12));
00345          resetOptions();
00346       }
00347       else if (m_line.startsWith("Script="))
00348       {
00349          gotScript(m_line.mid(7));
00350          resetOptions();
00351       }
00352       else if (m_line.startsWith("ScriptArguments="))
00353          gotScriptArguments(m_line.mid(16));
00354       else if (m_line.startsWith("Key="))
00355       {
00356          gotKey(m_line.mid(4));
00357          resetOptions();
00358       }
00359       else if (m_line.startsWith("RemoveKey="))
00360       {
00361          gotRemoveKey(m_line.mid(10));
00362          resetOptions();
00363       }
00364       else if (m_line == "AllKeys")
00365       {
00366          gotAllKeys();
00367          resetOptions();
00368       }
00369       else if (m_line == "AllGroups")
00370       {
00371          gotAllGroups();
00372          resetOptions();
00373       }
00374       else
00375       {
00376          log() << currentFilename << ": parse error in line " << m_lineCount << " : '" << m_line << "'" << endl;
00377       }
00378    }
00379    // Flush.
00380    gotId(QString());
00381 
00382    KDE_struct_stat buff;
00383    KDE_stat( QFile::encodeName(filename), &buff);
00384    KConfigGroup cg(config, currentFilename);
00385    cg.writeEntry("ctime", int(buff.st_ctime));
00386    cg.writeEntry("mtime", int(buff.st_mtime));
00387    cg.sync();
00388    return true;
00389 }
00390 
00391 
00392 
00393 void KonfUpdate::gotId(const QString &_id)
00394 {
00395    if (!id.isEmpty() && !skip)
00396    {
00397        KConfigGroup cg(config, currentFilename);
00398 
00399        QStringList ids = cg.readEntry("done", QStringList());
00400        if (!ids.contains(id))
00401        {
00402           ids.append(id);
00403           cg.writeEntry("done", ids);
00404           cg.sync();
00405        }
00406    }
00407 
00408    // Flush pending changes
00409    gotFile(QString());
00410    KConfigGroup cg(config, currentFilename);
00411 
00412    QStringList ids = cg.readEntry("done", QStringList());
00413    if (!_id.isEmpty())
00414    {
00415        if (ids.contains(_id))
00416        {
00417           //qDebug("Id '%s' was already in done-list", _id.toLatin1().constData());
00418           if (!m_bUseConfigInfo)
00419           {
00420              skip = true;
00421              return;
00422           }
00423        }
00424        skip = false;
00425        skipFile = 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());
00438 
00439    if (!oldFile.isEmpty())
00440    {
00441       // Close old file.
00442       delete oldConfig1;
00443       oldConfig1 = 0;
00444 
00445       KConfigGroup cg(oldConfig2, "$Version");
00446       QStringList ids = cg.readEntry("update_info", QStringList());
00447       QString cfg_id = currentFilename + ':' + id;
00448       if (!ids.contains(cfg_id) && !skip)
00449       {
00450          ids.append(cfg_id);
00451          cg.writeEntry("update_info", ids);
00452       }
00453       cg.sync();
00454       delete oldConfig2;
00455       oldConfig2 = 0;
00456 
00457       QString file = KStandardDirs::locateLocal("config", oldFile);
00458       KDE_struct_stat s_buf;
00459       if (KDE_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.clear();
00469    }
00470    if (!newFile.isEmpty())
00471    {
00472       // Close new file.
00473       KConfigGroup cg(newConfig, "$Version");
00474       QStringList ids = cg.readEntry("update_info", QStringList());
00475       QString cfg_id = currentFilename + ':' + id;
00476       if (!ids.contains(cfg_id) && !skip)
00477       {
00478          ids.append(cfg_id);
00479          cg.writeEntry("update_info", ids);
00480       }
00481       newConfig->sync();
00482       delete newConfig;
00483       newConfig = 0;
00484 
00485       newFile.clear();
00486    }
00487    newConfig = 0;
00488 
00489    int i = _file.indexOf(',');
00490    if (i == -1)
00491    {
00492       oldFile = _file.trimmed();
00493    }
00494    else
00495    {
00496       oldFile = _file.left(i).trimmed();
00497       newFile = _file.mid(i+1).trimmed();
00498       if (oldFile == newFile)
00499          newFile.clear();
00500    }
00501 
00502    if (!oldFile.isEmpty())
00503    {
00504       oldConfig2 = new KConfig(oldFile, KConfig::NoGlobals);
00505       QString cfg_id = currentFilename + ':' + id;
00506       KConfigGroup cg(oldConfig2, "$Version");
00507       QStringList ids = cg.readEntry("update_info", QStringList());
00508       if (ids.contains(cfg_id))
00509       {
00510          skip = true;
00511          newFile.clear();
00512          log() << currentFilename << ": Skipping update '" << id << "'" << endl;
00513       }
00514 
00515       if (!newFile.isEmpty())
00516       {
00517          newConfig = new KConfig(newFile, KConfig::NoGlobals);
00518          KConfigGroup cg(newConfig, "$Version");
00519          ids = cg.readEntry("update_info", QStringList());
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, KConfig::NoGlobals);
00532    }
00533    else
00534    {
00535       newFile.clear();
00536    }
00537    newFileName = newFile;
00538    if (newFileName.isEmpty())
00539       newFileName = oldFile;
00540 
00541    skipFile = false;
00542    if( !oldFile.isEmpty())
00543    { // if File= is specified, it doesn't exist, is empty or contains only kconf_update's [$Version] group, skip
00544       if( oldConfig1 != NULL
00545           && ( oldConfig1->groupList().isEmpty()
00546               || ( oldConfig1->groupList().count() == 1 && oldConfig1->groupList().first() == "$Version" )))
00547       {
00548          log() << currentFilename << ": File '" << oldFile << "' does not exist or empty, skipping" << endl;
00549          skipFile = true;
00550       }
00551    }
00552 }
00553 
00554 void KonfUpdate::gotGroup(const QString &_group)
00555 {
00556    int i = _group.indexOf(',');
00557    if (i == -1)
00558    {
00559       oldGroup = _group.trimmed();
00560       newGroup = oldGroup;
00561    }
00562    else
00563    {
00564       oldGroup = _group.left(i).trimmed();
00565       newGroup = _group.mid(i+1).trimmed();
00566    }
00567 }
00568 
00569 void KonfUpdate::gotRemoveGroup(const QString &_group)
00570 {
00571    oldGroup = _group.trimmed();
00572 
00573    if (!oldConfig1)
00574    {
00575       log() << currentFilename << ": !! RemoveGroup without previous File specification in line " << m_lineCount << " : '" << m_line << "'" << endl;
00576       return;
00577    }
00578 
00579    if (!oldConfig1->hasGroup(oldGroup))
00580       return;
00581    // Delete group.
00582    oldConfig2->deleteGroup(oldGroup);
00583    log() << currentFilename << ": RemoveGroup removes group " << oldFile << ":" << oldGroup << endl;
00584 }
00585 
00586 
00587 void KonfUpdate::gotKey(const QString &_key)
00588 {
00589    int i = _key.indexOf(',');
00590    if (i == -1)
00591    {
00592       oldKey = _key.trimmed();
00593       newKey = oldKey;
00594    }
00595    else
00596    {
00597       oldKey = _key.left(i).trimmed();
00598       newKey = _key.mid(i+1).trimmed();
00599    }
00600 
00601    if (oldKey.isEmpty() || newKey.isEmpty())
00602    {
00603       log() << currentFilename << ": !! Key specifies invalid key in line " << m_lineCount << " : '" << m_line << "'" << endl;
00604       return;
00605    }
00606    if (!oldConfig1)
00607    {
00608       log() << currentFilename << ": !! Key without previous File specification in line " << m_lineCount << " : '" << m_line << "'" << endl;
00609       return;
00610    }
00611    KConfigGroup cg1( oldConfig1, oldGroup);
00612    if (!cg1.hasKey(oldKey))
00613       return;
00614    QString value = cg1.readEntry(oldKey, QString());
00615    KConfigGroup newFGroup( newConfig, newGroup);
00616    if (!m_bOverwrite && newFGroup.hasKey(newKey))
00617    {
00618       log() << currentFilename << ": Skipping " << newFileName << ":" << newGroup << ":" << newKey << ", already exists."<< endl;
00619       return;
00620    }
00621    log() << currentFilename << ": Updating " << newFileName << ":" << newGroup << ":" << newKey << " to '" << value << "'" << endl;
00622    newFGroup.writeEntry(newKey, value);
00623 
00624    if (m_bCopy)
00625       return; // Done.
00626 
00627    // Delete old entry
00628    if ((oldConfig2 == newConfig) &&
00629        (oldGroup == newGroup) &&
00630        (oldKey == newKey))
00631       return; // Don't delete!
00632    KConfigGroup oldGroup2( oldConfig2, oldGroup);
00633    oldGroup2.deleteEntry(oldKey);
00634    log() << currentFilename << ": Removing " << oldFile << ":" << oldGroup << ":" << oldKey << ", moved." << endl;
00635    /*if (oldConfig2->deleteGroup(oldGroup, KConfig::Normal)) { // Delete group if empty.
00636       log() << currentFilename << ": Removing empty group " << oldFile << ":" << oldGroup << endl;
00637    }  (this should be automatic)  */
00638 }
00639 
00640 void KonfUpdate::gotRemoveKey(const QString &_key)
00641 {
00642    oldKey = _key.trimmed();
00643 
00644    if (oldKey.isEmpty())
00645    {
00646       log() << currentFilename << ": !! RemoveKey specifies invalid key in line " << m_lineCount << " : '" << m_line << "'" << endl;
00647       return;
00648    }
00649 
00650    if (!oldConfig1)
00651    {
00652       log() << currentFilename << ": !! Key without previous File specification in line " << m_lineCount << " : '" << m_line << "'" << endl;
00653       return;
00654    }
00655 
00656    KConfigGroup cg1(oldConfig1, oldGroup);
00657    if (!cg1.hasKey(oldKey))
00658       return;
00659    log() << currentFilename << ": RemoveKey removes " << oldFile << ":" << oldGroup << ":" << oldKey << endl;
00660 
00661    // Delete old entry
00662    KConfigGroup cg2( oldConfig2, oldGroup);
00663    cg2.deleteEntry(oldKey);
00664    /*if (oldConfig2->deleteGroup(oldGroup, KConfig::Normal)) { // Delete group if empty.
00665       log() << currentFilename << ": Removing empty group " << oldFile << ":" << oldGroup << endl;
00666    }   (this should be automatic)*/
00667 }
00668 
00669 void KonfUpdate::gotAllKeys()
00670 {
00671    if (!oldConfig1)
00672    {
00673       log() << currentFilename << ": !! AllKeys without previous File specification in line " << m_lineCount << " : '" << m_line << "'" << endl;
00674       return;
00675    }
00676 
00677    QMap<QString, QString> list = oldConfig1->entryMap(oldGroup);
00678    for(QMap<QString, QString>::Iterator it = list.begin();
00679        it != list.end(); ++it)
00680    {
00681       gotKey(it.key());
00682    }
00683 }
00684 
00685 void KonfUpdate::gotAllGroups()
00686 {
00687    if (!oldConfig1)
00688    {
00689       log() << currentFilename << ": !! AllGroups without previous File specification in line " << m_lineCount << " : '" << m_line << "'" << endl;
00690       return;
00691    }
00692 
00693    QStringList allGroups = oldConfig1->groupList();
00694    for(QStringList::ConstIterator it = allGroups.begin();
00695        it != allGroups.end(); ++it)
00696    {
00697      oldGroup = *it;
00698      newGroup = oldGroup;
00699      gotAllKeys();
00700    }
00701 }
00702 
00703 void KonfUpdate::gotOptions(const QString &_options)
00704 {
00705    QStringList options = _options.split(',');
00706    for(QStringList::ConstIterator it = options.begin();
00707        it != options.end();
00708        ++it)
00709    {
00710        if ( (*it).toLower().trimmed() == "copy")
00711           m_bCopy = true;
00712 
00713        if ( (*it).toLower().trimmed() == "overwrite")
00714           m_bOverwrite = true;
00715    }
00716 }
00717 
00718 void KonfUpdate::copyGroup(KConfig *cfg1, const QString &group1,
00719                            KConfig *cfg2, const QString &group2)
00720 {
00721    KConfigGroup cg1(cfg1, group1);
00722    KConfigGroup cg2(cfg2, group2);
00723    QMap<QString, QString> list = cg1.entryMap();
00724    for(QMap<QString, QString>::Iterator it = list.begin();
00725        it != list.end(); ++it)
00726    {
00727       cg2.writeEntry(it.key(), cg1.readEntry(it.key(), QString()));
00728    }
00729 }
00730 
00731 void KonfUpdate::gotScriptArguments(const QString &_arguments)
00732 {
00733    m_arguments = _arguments;
00734 }
00735 
00736 void KonfUpdate::gotScript(const QString &_script)
00737 {
00738    QString script, interpreter;
00739    int i = _script.indexOf(',');
00740    if (i == -1)
00741    {
00742       script = _script.trimmed();
00743    }
00744    else
00745    {
00746       script = _script.left(i).trimmed();
00747       interpreter = _script.mid(i+1).trimmed();
00748    }
00749 
00750 
00751    if (script.isEmpty())
00752    {
00753       log() << currentFilename << ": !! Script fails to specify filename in line " << m_lineCount << " : '" << m_line << "'" << endl;
00754       skip = true;
00755       return;
00756    }
00757 
00758 
00759 
00760    QString path = KStandardDirs::locate("data","kconf_update/"+script);
00761    if (path.isEmpty())
00762    {
00763       if (interpreter.isEmpty())
00764          path = KStandardDirs::locate("lib", "kconf_update_bin/"+script);
00765 
00766       if (path.isEmpty())
00767       {
00768         log() << currentFilename << ": !! Script '" << script << "' not found in line " << m_lineCount << " : '" << m_line << "'" << endl;
00769         skip = true;
00770         return;
00771       }
00772    }
00773 
00774    if( !m_arguments.isNull())
00775       log() << currentFilename << ": Running script '" << script << "' with arguments '" << m_arguments << "'" << endl;
00776    else
00777       log() << currentFilename << ": Running script '" << script << "'" << endl;
00778 
00779    QString cmd;
00780    if (interpreter.isEmpty())
00781       cmd = path;
00782    else
00783       cmd = interpreter + ' ' + path;
00784 
00785    if( !m_arguments.isNull())
00786    {
00787       cmd += ' ';
00788       cmd += m_arguments;
00789    }
00790 
00791    KTemporaryFile tmp1;
00792    tmp1.open();
00793    KTemporaryFile tmp2;
00794    tmp2.open();
00795    KTemporaryFile tmp3;
00796    tmp3.open();
00797 
00798    int result;
00799    if (oldConfig1)
00800    {
00801        if (debug)
00802        {
00803            tmp1.setAutoRemove(false);
00804            log() << "Script input stored in " << tmp1.fileName() << endl;
00805        }
00806        KConfig cfg(tmp1.fileName(), KConfig::SimpleConfig);
00807 
00808        if (oldGroup.isEmpty())
00809        {
00810            // Write all entries to tmpFile;
00811            QStringList grpList = oldConfig1->groupList();
00812            for(QStringList::ConstIterator it = grpList.begin();
00813                it != grpList.end();
00814                ++it)
00815            {
00816                copyGroup(oldConfig1, *it, &cfg, *it);
00817            }
00818        }
00819        else
00820        {
00821            copyGroup(oldConfig1, oldGroup, &cfg, QString());
00822        }
00823        cfg.sync();
00824        result = system(QFile::encodeName(QString("%1 < %2 > %3 2> %4").arg(cmd, tmp1.fileName(), tmp2.fileName(), tmp3.fileName())));
00825    }
00826    else
00827    {
00828        // No config file
00829        result = system(QFile::encodeName(QString("%1 2> %2").arg(cmd, tmp3.fileName())));
00830    }
00831 
00832    // Copy script stderr to log file
00833    {
00834      QFile output(tmp3.fileName());
00835      if (output.open(QIODevice::ReadOnly))
00836      {
00837        QTextStream ts( &output );
00838        ts.setCodec(QTextCodec::codecForName("UTF-8"));
00839        while(!ts.atEnd())
00840        {
00841          QString line = ts.readLine();
00842          log() << "[Script] " << line << endl;
00843        }
00844      }
00845    }
00846 
00847    if (result)
00848    {
00849       log() << currentFilename << ": !! An error occurred while running '" << cmd << "'" << endl;
00850       return;
00851    }
00852 
00853    if (!oldConfig1)
00854       return; // Nothing to merge
00855 
00856    if (debug)
00857    {
00858       tmp2.setAutoRemove(false);
00859       log() << "Script output stored in " << tmp2.fileName() << endl;
00860    }
00861 
00862    // Deleting old entries
00863    {
00864      QString group = oldGroup;
00865      QFile output(tmp2.fileName());
00866      if (output.open(QIODevice::ReadOnly))
00867      {
00868        QTextStream ts( &output );
00869        ts.setCodec(QTextCodec::codecForName("UTF-8"));
00870        while(!ts.atEnd())
00871        {
00872          QString line = ts.readLine();
00873          if (line.startsWith('['))
00874          {
00875             int j = line.indexOf(']')+1;
00876             if (j > 0)
00877                group = line.mid(1, j-2);
00878          }
00879          else if (line.startsWith("# DELETE "))
00880          {
00881             QString key = line.mid(9);
00882             if (key[0] == '[')
00883             {
00884                int j = key.indexOf(']')+1;
00885                if (j > 0)
00886                {
00887                   group = key.mid(1,j-2);
00888                   key = key.mid(j);
00889                }
00890             }
00891             KConfigGroup cg(oldConfig2, group);
00892             cg.deleteEntry(key);
00893             log() << currentFilename << ": Script removes " << oldFile << ":" << group << ":" << key << endl;
00894             /*if (oldConfig2->deleteGroup(group, KConfig::Normal)) { // Delete group if empty.
00895                log() << currentFilename << ": Removing empty group " << oldFile << ":" << group << endl;
00896         } (this should be automatic)*/
00897          }
00898          else if (line.startsWith("# DELETEGROUP"))
00899          {
00900             QString key = line.mid(13).trimmed();
00901             if (key[0] == '[')
00902             {
00903                int j = key.indexOf(']')+1;
00904                if (j > 0)
00905                {
00906                   group = key.mid(1,j-2);
00907                }
00908             }
00909             oldConfig2->deleteGroup(group);
00910             log() << currentFilename << ": Script removes group " << oldFile << ":" << group << endl;
00911           }
00912        }
00913      }
00914    }
00915 
00916    // Merging in new entries.
00917    m_bCopy = true;
00918    {
00919      KConfig *saveOldConfig1 = oldConfig1;
00920      QString saveOldGroup = oldGroup;
00921      QString saveNewGroup = newGroup;
00922      oldConfig1 = new KConfig(tmp2.fileName(), KConfig::NoGlobals);
00923 
00924      // For all groups...
00925      QStringList grpList = oldConfig1->groupList();
00926      for(QStringList::ConstIterator it = grpList.begin();
00927          it != grpList.end();
00928          ++it)
00929      {
00930         oldGroup = *it;
00931         if (oldGroup != "<default>")
00932         {
00933            newGroup = oldGroup;
00934         }
00935         gotAllKeys(); // Copy all keys
00936      }
00937      delete oldConfig1;
00938      oldConfig1 = saveOldConfig1;
00939      oldGroup = saveOldGroup;
00940      newGroup = saveNewGroup;
00941    }
00942 }
00943 
00944 void KonfUpdate::resetOptions()
00945 {
00946    m_bCopy = false;
00947    m_bOverwrite = false;
00948    m_arguments.clear();
00949 }
00950 
00951 
00952 extern "C" KDE_EXPORT int kdemain(int argc, char **argv)
00953 {
00954    KCmdLineOptions options;
00955    options.add("debug", ki18n("Keep output results from scripts"));
00956    options.add("check <update-file>", ki18n("Check whether config file itself requires updating"));
00957    options.add("+[file]", ki18n("File to read update instructions from"));
00958 
00959    KAboutData aboutData("kconf_update", 0, ki18n("KConf Update"),
00960                         "1.0.2",
00961                         ki18n("KDE Tool for updating user configuration files"),
00962                         KAboutData::License_GPL,
00963                         ki18n("(c) 2001, Waldo Bastian"));
00964 
00965    aboutData.addAuthor(ki18n("Waldo Bastian"), KLocalizedString(), "bastian@kde.org");
00966 
00967    KCmdLineArgs::init(argc, argv, &aboutData);
00968    KCmdLineArgs::addCmdLineOptions(options);
00969 
00970    KComponentData componentData(&aboutData);
00971 
00972    KonfUpdate konfUpdate;
00973 
00974    return 0;
00975 }

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
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
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