00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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;
00090 KConfig *oldConfig2;
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
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
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
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
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
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
00437 gotGroup(QString::null);
00438
00439 if (!oldFile.isEmpty())
00440 {
00441
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
00464 unlink(QFile::encodeName(file));
00465 }
00466 }
00467
00468 oldFile = QString::null;
00469 }
00470 if (!newFile.isEmpty())
00471 {
00472
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
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;
00614
00615
00616 if ((oldConfig2 == newConfig) &&
00617 (oldGroup == newGroup) &&
00618 (oldKey == newKey))
00619 return;
00620 oldConfig2->setGroup(oldGroup);
00621 oldConfig2->deleteEntry(oldKey, false);
00622 log() << currentFilename << ": Removing " << oldFile << ":" << oldGroup << ":" << oldKey << ", moved." << endl;
00623 if (oldConfig2->deleteGroup(oldGroup, false)) {
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
00650 oldConfig2->setGroup(oldGroup);
00651 oldConfig2->deleteEntry(oldKey, false);
00652 if (oldConfig2->deleteGroup(oldGroup, false)) {
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
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
00817 result = system(QFile::encodeName(QString("%1 2> %2").arg(cmd, tmp3.name())));
00818 }
00819
00820
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;
00843
00844 if (debug)
00845 {
00846 tmp2.setAutoDelete(false);
00847 log() << "Script output stored in " << tmp2.name() << endl;
00848 }
00849
00850
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)) {
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)) {
00898 log() << currentFilename << ": Script removes group " << oldFile << ":" << group << endl;
00899 }
00900 }
00901 }
00902 }
00903 }
00904
00905
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
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();
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 }