00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <stdlib.h>
00025
00026 #include <QFile>
00027 #include <QDir>
00028 #include <QLibraryInfo>
00029 #include <QUrl>
00030 #include <QUrlQuery>
00031 #include <QMessageBox>
00032 #include <QPushButton>
00033 #include <QApplication>
00034 #include <QDesktopWidget>
00035 #include <QProcess>
00036
00037 #include "klfutil.h"
00038 #include "klfsysinfo.h"
00039
00040
00041 KLF_EXPORT bool klfEnsureDir(const QString& dir)
00042 {
00043 if ( ! QDir(dir).exists() ) {
00044 bool r = QDir("/").mkpath(dir);
00045 if ( ! r ) {
00046 qWarning("Can't create local directory %s!", qPrintable(dir));
00047 return false;
00048 }
00049
00050 r = QFile::setPermissions(dir, QFile::ReadOwner|QFile::WriteOwner|QFile::ExeOwner|
00051 QFile::ReadUser|QFile::WriteUser|QFile::ExeUser);
00052 if ( ! r ) {
00053 qWarning("Can't set permissions to local config directory `%s' !", qPrintable(dir));
00054 return false;
00055 }
00056 }
00057 return true;
00058 }
00059
00060
00061
00062 static QMap<QString,QString> klf_url_query_items_map(const QUrl& url,
00063 const QStringList& interestQueryItems)
00064 {
00065 QList<QPair<QString,QString> > qitems = QUrlQuery(url).queryItems();
00066 QMap<QString,QString> map;
00067 int k;
00068 for (k = 0; k < qitems.size(); ++k) {
00069 const QPair<QString,QString>& p = qitems[k];
00070 if (interestQueryItems.isEmpty() || interestQueryItems.contains(p.first))
00071 map[p.first] = p.second;
00072 }
00073 return map;
00074 }
00075
00076
00077
00078 KLF_EXPORT uint klfUrlCompare(const QUrl& url1, const QUrl& url2, uint interestFlags,
00079 const QStringList& interestQueryItems)
00080 {
00081 KLF_DEBUG_BLOCK(KLF_FUNC_NAME);
00082 klfDbg( ": 1="<<url1<<"; 2="<<url2<<"; interestflags="<<interestFlags<<"; int.q.i="
00083 <<interestQueryItems ) ;
00084 uint compareflags = 0x00;
00085
00086 Qt::CaseSensitivity queryItemValsCS = Qt::CaseSensitive;
00087 if (interestFlags & klfUrlCompareFlagIgnoreQueryItemValueCase)
00088 queryItemValsCS = Qt::CaseInsensitive;
00089
00090 QMap<QString,QString> qitems_map1;
00091 QMap<QString,QString> qitems_map2;
00092
00093 QUrl u1 = url1;
00094 QUrl u2 = url2;
00095 u1.setQuery("");
00096 u2.setQuery("");
00097
00098 klfDbg( " after q-i-stripping: u1="<<u1<<"; u2="<<u2 ) ;
00099
00100 if (interestFlags &
00101 (KlfUrlCompareEqual|KlfUrlCompareLessSpecific|KlfUrlCompareMoreSpecific)) {
00102
00103 qitems_map1 = klf_url_query_items_map(url1, interestQueryItems);
00104 qitems_map2 = klf_url_query_items_map(url2, interestQueryItems);
00105 }
00106
00107 if (interestFlags & KlfUrlCompareEqual) {
00108
00109 if (u1 == u2 && qitems_map1 == qitems_map2)
00110 compareflags |= KlfUrlCompareEqual;
00111 }
00112
00113 if (interestFlags & KlfUrlCompareLessSpecific) {
00114
00115 if (u1 == u2) {
00116 bool ok = klfMapIsIncludedIn(qitems_map1, qitems_map2, queryItemValsCS);
00117 if (ok)
00118 compareflags |= KlfUrlCompareLessSpecific;
00119 }
00120 }
00121 if (interestFlags & KlfUrlCompareMoreSpecific) {
00122
00123 if (u1 == u2) {
00124 bool ok = klfMapIsIncludedIn(qitems_map2, qitems_map1, queryItemValsCS);
00125 if (ok)
00126 compareflags |= KlfUrlCompareMoreSpecific;
00127 }
00128 }
00129
00130 if (interestFlags & KlfUrlCompareBaseEqual) {
00131 if (u1 == u2)
00132 compareflags |= KlfUrlCompareBaseEqual;
00133 }
00134
00135 klfDbg( "... and the result is compareflags="<<compareflags ) ;
00136 return compareflags;
00137 }
00138
00139
00140
00141
00142
00143
00144
00145 KLF_EXPORT bool klfMatch(const QVariant& testForHitCandidateValue, const QVariant& queryValue,
00146 Qt::MatchFlags flags, const QString& queryStringCache )
00147 {
00148
00149
00150
00151
00152
00153
00154 uint matchType = flags & 0x0F;
00155 Qt::CaseSensitivity cs = (flags & Qt::MatchCaseSensitive)
00156 ? Qt::CaseSensitive
00157 : Qt::CaseInsensitive;
00158
00159 const QVariant& v = testForHitCandidateValue;
00160
00161
00162 if (matchType == Qt::MatchExactly)
00163 return (queryValue == v);
00164
00165
00166 QString text = !queryStringCache.isNull() ? queryStringCache : queryValue.toString();
00167 QString t = v.toString();
00168 switch (matchType) {
00169 case Qt::MatchRegExp:
00170 return (QRegExp(text, cs).exactMatch(t));
00171 case Qt::MatchWildcard:
00172 return (QRegExp(text, cs, QRegExp::Wildcard).exactMatch(t));
00173 case Qt::MatchStartsWith:
00174 return (t.startsWith(text, cs));
00175 case Qt::MatchEndsWith:
00176 return (t.endsWith(text, cs));
00177 case Qt::MatchFixedString:
00178 return (QString::compare(t, text, cs) == 0);
00179 case Qt::MatchContains:
00180 default:
00181 return (t.contains(text, cs));
00182 }
00183 }
00184
00185
00186
00187
00188
00189
00190 static QStringList __search_find_test(const QString& root, const QStringList& pathlist,
00191 int level, int limit)
00192 {
00193 if (limit == 0)
00194 return QStringList();
00195
00196 if (limit < 0)
00197 limit = -1;
00198
00199 klfDebugf(("root=`%s', pathlist=`%s', level=%d, limit=%d", qPrintable(root), qPrintable(pathlist.join("\t")),
00200 level, limit));
00201
00202 QStringList newpathlist = pathlist;
00203
00204 QStringList levelpathlist;
00205 int k;
00206 for (k = 0; k < level; ++k) { levelpathlist << newpathlist[k]; }
00207
00208 QString flpath = root+levelpathlist.join("/");
00209 klfDebugf(("our path = `%s' ...", qPrintable(flpath)));
00210 QFileInfo flinfo(flpath);
00211 if (flinfo.isDir() && level < pathlist.size()) {
00212 klfDebugf(("... is dir.")) ;
00213 QDir d(flpath);
00214 QStringList entries;
00215 entries = d.entryList(QStringList()<<pathlist[level], QDir::AllEntries|QDir::System|QDir::Hidden);
00216 if (entries.size()) {
00217 klfDebugf(("got entry list: %s", qPrintable(entries.join("\t"))));
00218 }
00219 QStringList hitlist;
00220 for (k = 0; k < (int)entries.size(); ++k) {
00221 newpathlist[level] = entries[k];
00222 hitlist += __search_find_test(root, newpathlist, level+1, limit - hitlist.size());
00223 if (limit >= 0 && (int)hitlist.size() >= limit)
00224 break;
00225 }
00226 return hitlist;
00227 }
00228 if (flinfo.exists()) {
00229 klfDebugf(("... is existing file.")) ;
00230 return QStringList() << QDir::toNativeSeparators(root+pathlist.join("/"));
00231 }
00232 klfDebugf(("... is invalid.")) ;
00233 return QStringList();
00234 }
00235
00236
00237
00238
00239
00240
00241
00242
00243 KLF_EXPORT QStringList klfSearchFind(const QString& wildcard_expression, int limit)
00244 {
00245 klfDbg("looking for "+wildcard_expression) ;
00246
00247 QString expr;
00248 expr = QDir::fromNativeSeparators(wildcard_expression);
00249 QStringList pathlist = expr.split("/", QString::SkipEmptyParts);
00250 QString root = "/";
00251
00252 static QRegExp driveregexp("^[A-Za-z]?:$");
00253 if (driveregexp.exactMatch(pathlist[0])) {
00254
00255 root = pathlist[0]+"/";
00256 pathlist.pop_front();
00257 }
00258 return __search_find_test(root, pathlist, 0, limit);
00259 }
00260
00261 KLF_EXPORT QString klfSearchPath(const QString& programName, const QString& extra_path)
00262 {
00263 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00264
00265 static const QString PATH = getenv("PATH");
00266 static const QString pathsep = QString("")+KLF_PATH_SEP;
00267
00268 QFileInfo fi(programName);
00269 if (fi.isAbsolute() && fi.exists() && fi.isExecutable())
00270 return programName;
00271
00272
00273 QString path = PATH;
00274 if (!extra_path.isEmpty())
00275 path = extra_path + pathsep + path;
00276
00277 const QStringList paths = path.split(pathsep, QString::KeepEmptyParts);
00278 QString test;
00279 int k, j;
00280 for (k = 0; k < (int)paths.size(); ++k) {
00281 klfDbg("searching for "<<programName<<" in "<<paths[k]) ;
00282 QStringList hits = klfSearchFind(paths[k]+"/"+programName);
00283 klfDbg("\t...resulting in hits = "<<hits) ;
00284 for (j = 0; j < (int)hits.size(); ++j) {
00285 if ( QFileInfo(hits[j]).isExecutable() ) {
00286 klfDbg("\tFound definitive (executable) hit at "+hits[j]) ;
00287 return hits[j];
00288 }
00289 }
00290 }
00291 return QString::null;
00292 }
00293
00294 KLF_EXPORT QString klfSearchPath(const QString& fname, const QStringList& paths)
00295 {
00296 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00297
00298 if (QFileInfo(fname).isAbsolute() && QFile::exists(fname))
00299 return fname;
00300
00301 QString test;
00302 int k;
00303 QStringList hits;
00304 for (k = 0; k < (int)paths.size(); ++k) {
00305 klfDbg("searching for "<<fname<<" in "<<paths[k]) ;
00306 hits = klfSearchFind(paths[k]+"/"+fname);
00307 klfDbg("\t...resulting in hits = "<<hits) ;
00308 if (hits.size() > 0) {
00309 klfDbg("\t...returning "<<hits[0]);
00310 return hits[0];
00311 }
00312 }
00313 return QString::null;
00314 }
00315
00316 KLF_EXPORT QString klfPrefixedPath(const QString& path_, const QString& ref_)
00317 {
00318 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00319
00320 QString path = path_;
00321 QString ref = ref_;
00322
00323 klfDbg("path="<<path<<"; reference="<<ref) ;
00324
00325 if (path == "~") {
00326 return QDir::homePath();
00327 }
00328 if (path.startsWith("~/")) {
00329 path = QDir::homePath() + "/" + path.mid(2);
00330 }
00331
00332 QFileInfo fi(path);
00333
00334 if (fi.isAbsolute()) {
00335 return fi.absoluteFilePath();
00336 }
00337
00338 if (!ref.isEmpty()) {
00339 if (ref == "~") {
00340 ref = QDir::homePath();
00341 } else if (ref.startsWith("~/")) {
00342 ref = QDir::homePath() + "/" + path.mid(2);
00343 }
00344 ref = QFileInfo(ref).absoluteFilePath();
00345 } else {
00346 ref = QCoreApplication::applicationDirPath();
00347 }
00348
00349
00350 if (!ref.endsWith("/")) {
00351 ref += "/";
00352 }
00353 klfDbg("reference is "<<ref) ;
00354
00355 QString result = QFileInfo(ref + path).absoluteFilePath();
00356 klfDbg("result = " << result) ;
00357 return result;
00358 }
00359
00360
00361
00362
00363
00364 QString klfGetEnvironmentVariable(const QStringList& env, const QString& var)
00365 {
00366 QString vareq = var + QLatin1String("=");
00367
00368 int k;
00369 for (k = 0; k < env.size(); ++k) {
00370 if (env[k].startsWith(vareq)) {
00371 return env[k].mid(vareq.length());
00372 }
00373 }
00374
00375 return QString();
00376 }
00377
00378 KLF_EXPORT void klfSetEnvironmentVariable(QStringList * env, const QString& var,
00379 const QString& value)
00380 {
00381 QString vareq = var + QLatin1String("=");
00382
00383 int k;
00384 for (k = 0; k < env->size(); ++k) {
00385 if (env->operator[](k).startsWith(vareq)) {
00386 env->operator[](k) = vareq+value;
00387 return;
00388 }
00389 }
00390
00391 env->append(vareq+value);
00392 return;
00393 }
00394
00395 QStringList klfSetEnvironmentVariable(const QStringList& env, const QString& var,
00396 const QString& value)
00397 {
00398 QStringList env2 = env;
00399 klfSetEnvironmentVariable(&env2, var, value);
00400 return env2;
00401 }
00402
00403 QStringList klfMapToEnvironmentList(const QMap<QString,QString>& map)
00404 {
00405 QStringList list;
00406 for (QMap<QString,QString>::const_iterator it = map.begin(); it != map.end(); ++it)
00407 list << it.key() + "=" + it.value();
00408 return list;
00409 }
00410
00411 static bool parse_env_line(const QString& s, QString * var, QString * val)
00412 {
00413 KLF_ASSERT_NOT_NULL(var, "var argument is NULL!", return false; ) ;
00414 KLF_ASSERT_NOT_NULL(val, "val argument is NULL!", return false; ) ;
00415 int i = s.indexOf('=');
00416 if (i == -1) {
00417 *var = *val = QString();
00418 klfWarning("Line "<<s<<" is not an environment variable setting.") ;
00419 return false;
00420 }
00421 *var = s.mid(0, i);
00422 *val = s.mid(i+1);
00423 return true;
00424 }
00425
00426 QMap<QString,QString> klfEnvironmentListToMap(const QStringList& env)
00427 {
00428 QMap<QString,QString> map;
00429
00430 foreach (QString s, env) {
00431 QString var, val;
00432 if (!parse_env_line(s, &var, &val))
00433 continue;
00434 if (map.contains(var))
00435 klfWarning("Line "<<s<<" will overwrite previous value of variable "<<var) ;
00436 map[var] = val;
00437 }
00438
00439 return map;
00440 }
00441
00442
00443 void klfMergeEnvironment(QStringList * env, const QStringList& addvars, const QStringList& pathvars, uint actions)
00444 {
00445 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00446 foreach (QString s, addvars) {
00447 QString var, val;
00448 if (!parse_env_line(s, &var, &val))
00449 continue;
00450
00451 if (actions & KlfEnvMergeExpandVars) {
00452 val = klfExpandEnvironmentVariables(val, *env, !(actions & KlfEnvMergeExpandNotRecursive));
00453 }
00454 if (pathvars.contains(var)) {
00455
00456 val = klfSetEnvironmentPath(klfGetEnvironmentVariable(*env, var), val, actions);
00457 }
00458
00459 klfSetEnvironmentVariable(env, var, val);
00460 }
00461 }
00462
00463 QStringList klfMergeEnvironment(const QStringList& env, const QStringList& addvars,
00464 const QStringList& pathvars, uint actions)
00465 {
00466 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00467 QStringList merged = env;
00468 klfMergeEnvironment(&merged, addvars, pathvars, actions);
00469 return merged;
00470 }
00471
00472
00473 QStringList klfGetEnvironmentPath(const QStringList& env, const QString& var)
00474 {
00475 QString value = klfGetEnvironmentVariable(env, var);
00476
00477 return klfSplitEnvironmentPath(value);
00478 }
00479
00480 QStringList klfSplitEnvironmentPath(const QString& value)
00481 {
00482 if (value.isEmpty())
00483 return QStringList();
00484 QStringList items = value.split(KLF_PATH_SEP, QString::KeepEmptyParts);
00485
00486
00487
00488 if (items.size() >= 2) {
00489 if (items[0].isEmpty() && items[1].isEmpty())
00490 items.removeAt(0);
00491 if (items[items.size()-1].isEmpty() && items[items.size()-2].isEmpty())
00492 items.removeAt(items.size()-1);
00493 }
00494 return items;
00495 }
00496
00497 QString klfJoinEnvironmentPath(const QStringList& paths)
00498 {
00499 return paths.join(QString("")+KLF_PATH_SEP);
00500 }
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514 QStringList klfSetEnvironmentPath(const QStringList& oldpaths, const QStringList& newpaths, uint action)
00515 {
00516 QStringList newitems;
00517 switch (action & KlfEnvPathActionMask) {
00518 case KlfEnvPathPrepend:
00519 newitems = QStringList() << newpaths << oldpaths;
00520 break;
00521 case KlfEnvPathAppend:
00522 newitems = QStringList() << oldpaths << newpaths;
00523 break;
00524 case KlfEnvPathReplace:
00525 newitems = newpaths;
00526 break;
00527 case KlfEnvPathNoAction:
00528 newitems = oldpaths;
00529 break;
00530 default:
00531 klfWarning("No or unknown action specified! action="<<action) ;
00532 break;
00533 }
00534 if (action & KlfEnvPathNoDuplicates) {
00535
00536 QStringList newitems2;
00537 int k;
00538 for (k = 0; k < newitems.size(); ++k) {
00539 if (newitems2.contains(newitems[k]))
00540 continue;
00541 newitems2.append(newitems[k]);
00542 }
00543 newitems = newitems2;
00544 }
00545 return newitems;
00546 }
00547
00548 QString klfSetEnvironmentPath(const QString& oldpaths, const QString& newpaths, uint action)
00549 {
00550 return klfSetEnvironmentPath(klfSplitEnvironmentPath(oldpaths),
00551 klfSplitEnvironmentPath(newpaths),
00552 action) . join(QString("")+KLF_PATH_SEP);
00553 }
00554
00555 QStringList klfSetEnvironmentPath(const QStringList& env, const QStringList& newpaths,
00556 const QString& var, uint action)
00557 {
00558 QStringList newval;
00559 newval = klfSetEnvironmentPath(klfGetEnvironmentPath(env, var), newpaths, action);
00560 return klfSetEnvironmentVariable(env, var, klfJoinEnvironmentPath(newval));
00561 }
00562
00563 void klfSetEnvironmentPath(QStringList * env, const QStringList& newpaths,
00564 const QString& var, uint action)
00565 {
00566 QStringList newval;
00567 newval = klfSetEnvironmentPath(klfGetEnvironmentPath(*env, var), newpaths, action);
00568 klfSetEnvironmentVariable(env, var, klfJoinEnvironmentPath(newval));
00569 }
00570
00571
00572 static QString __klf_expandenvironmentvariables(const QString& expression, const QStringList& env,
00573 bool recursive, const QStringList& recstack)
00574 {
00575 QString s = expression;
00576 QRegExp rx("\\$(?:(\\$|(?:[A-Za-z0-9_]+))|\\{([A-Za-z0-9_]+)\\})");
00577 int i = 0;
00578 while ( (i = rx.indexIn(s, i)) != -1 ) {
00579
00580 QString envvarname = rx.cap(1);
00581 if (envvarname.isEmpty() || envvarname == QLatin1String("$")) {
00582
00583 s.replace(i, rx.matchedLength(), QLatin1String("$"));
00584 i += 1;
00585 continue;
00586 }
00587
00588
00589 if (recstack.contains(envvarname)) {
00590 klfWarning("Recursive definition detected for variable "<<envvarname<<"!") ;
00591 i += rx.matchedLength();
00592 continue;
00593 }
00594
00595 QString val;
00596 if (env.isEmpty()) {
00597 const char *svalue = getenv(qPrintable(envvarname));
00598 val = (svalue != NULL) ? QString::fromLocal8Bit(svalue) : QString();
00599 } else {
00600 val = klfGetEnvironmentVariable(env, envvarname);
00601 }
00602
00603 if (recursive) {
00604 val = __klf_expandenvironmentvariables(val, env, true, QStringList()<<recstack<<envvarname) ;
00605 }
00606 klfDbg("Replaced value of "<<envvarname<<" is "<<val) ;
00607 s.replace(i, rx.matchedLength(), val);
00608 i += val.length();
00609 }
00610
00611 return s;
00612 }
00613
00614 QString klfExpandEnvironmentVariables(const QString& expression, const QStringList& env,
00615 bool recursive)
00616 {
00617 return __klf_expandenvironmentvariables(expression, env, recursive, QStringList());
00618 }
00619
00620
00621 KLF_EXPORT QStringList klfCurrentEnvironment()
00622 {
00623 return QProcess::systemEnvironment();
00624 }
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634 KLF_EXPORT QString klfUrlLocalFilePath(const QUrl& url)
00635 {
00636 #ifdef Q_OS_WIN32
00637 QString p = url.path();
00638 if (p.startsWith("/"))
00639 p = p.mid(1);
00640 return p;
00641 #else
00642 return url.path();
00643 #endif
00644 }
00645
00646
00647
00648 KLFTarget::~KLFTarget()
00649 {
00650 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00651
00652 int k;
00653 const QList<KLFTargeter*> targeters = pTargetOf;
00654 for (k = 0; k < targeters.size(); ++k) {
00655 targeters[k]->pTarget = NULL;
00656 }
00657 }
00658
00659 KLFTargeter::~KLFTargeter()
00660 {
00661 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00662
00663 if (pTarget != NULL)
00664 pTarget->pTargetOf.removeAll(this);
00665 }
00666
00667 void KLFTargeter::setTarget(KLFTarget *target)
00668 {
00669 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00670 klfDbg("target="<<target) ;
00671
00672 if (pTarget != NULL)
00673 pTarget->pTargetOf.removeAll(this);
00674
00675 pTarget = target;
00676
00677 if (pTarget != NULL)
00678 pTarget->pTargetOf.append(this);
00679 }