You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
563 lines
19 KiB
563 lines
19 KiB
/***************************************************************************
|
|
* Copyright (C) 1992-2007 Trolltech ASA *
|
|
* *
|
|
* Copyright (C) 2005-2007 by Tarek Saidi *
|
|
* tarek.saidi@arcor.de *
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; version 2 of the License. *
|
|
* *
|
|
* This program is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU General Public License *
|
|
* along with this program; if not, write to the *
|
|
* Free Software Foundation, Inc., *
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
***************************************************************************/
|
|
|
|
#include <iostream>
|
|
#include <qapplication.h>
|
|
#include <qlibrary.h>
|
|
#include <qlocale.h>
|
|
#include <qdir.h>
|
|
#include <QMessageBox>
|
|
#include <QTranslator>
|
|
#include <QPainter>
|
|
#include <QImage>
|
|
#include <QStyleFactory>
|
|
#include <QProcess>
|
|
#include <QLibraryInfo>
|
|
#include <QPluginLoader>
|
|
#include <QDesktopServices>
|
|
#include <QUrl>
|
|
|
|
#include "plugins/interfaces/IFileDialog.h"
|
|
#include "plugins/interfaces/IKdeInit.h"
|
|
#include "plugins/interfaces/IGnomeInit.h"
|
|
#include "plugins/interfaces/IIconTheme.h"
|
|
#include "lib/FileDialogs.h"
|
|
|
|
#include "main.h"
|
|
#include "lib/FileDialogs.h"
|
|
#include "lib/bookmarks.h"
|
|
#include "KpxConfig.h"
|
|
#include "Kdb3Database.h"
|
|
#include "mainwindow.h"
|
|
#include "crypto/yarrow.h"
|
|
using namespace std;
|
|
|
|
#ifdef Q_WS_X11
|
|
#include <X11/extensions/XTest.h>
|
|
#define XK_LATIN1
|
|
#define XK_MISCELLANY
|
|
#define XK_XKB_KEYS
|
|
#include <X11/keysymdef.h>
|
|
#include <X11/Xlib.h>
|
|
#endif
|
|
|
|
#define CSTR(x)(x.toUtf8().data())
|
|
|
|
QHash<QString,QPixmap*>PixmapCache;
|
|
QHash<QString,QIcon*>IconCache;
|
|
|
|
KpxConfig *config;
|
|
QString AppDir;
|
|
QString PluginLoadError;
|
|
bool TrActive;
|
|
QString DetailViewTemplate;
|
|
|
|
QPixmap* EntryIcons;
|
|
IIconTheme* IconLoader=NULL;
|
|
char ** argv;
|
|
|
|
inline void loadImages();
|
|
inline void parseCmdLineArgs(int argc, char** argv,QString &ArgFile,QString& ArgCfg,QString& ArgLang);
|
|
bool loadTranslation(QTranslator* tr,const QString& prefix,const QString& LocaleCode,const QStringList& SearchPaths);
|
|
|
|
void test_getAllWindowTitles(){
|
|
#ifdef Q_WS_X11
|
|
Display* pDisplay = XOpenDisplay( NULL );
|
|
Window r,p;
|
|
Window* c;
|
|
unsigned int num_ch=0;
|
|
XQueryTree(pDisplay,DefaultRootWindow(pDisplay),&r,&p,&c,&num_ch);
|
|
qDebug("%u",num_ch);
|
|
for(int i=0;i<num_ch;i++){
|
|
int num_prop=0;
|
|
Atom* atom=XListProperties(pDisplay,c[i],&num_prop);
|
|
for(int p=0;p<num_prop;p++){
|
|
qDebug("%i %i: %s",i,p,XGetAtomName(pDisplay,atom[p]));
|
|
}
|
|
XFree(atom);
|
|
|
|
}
|
|
#endif
|
|
}
|
|
|
|
int main(int argc, char **_argv)
|
|
{
|
|
argv=_argv;
|
|
QString ArgFile,ArgCfg,ArgLang,IniFilename;
|
|
QApplication* app=NULL;
|
|
AppDir=applicationDirPath();
|
|
parseCmdLineArgs(argc,argv,ArgFile,ArgCfg,ArgLang);
|
|
qDebug(CSTR(QDir::current().absolutePath()));
|
|
|
|
//Load Config
|
|
if(ArgCfg.isEmpty()){
|
|
if(!QDir(QDir::homePath()+"/.keepassx").exists()){
|
|
QDir conf(QDir::homePath());
|
|
if(!conf.mkdir(".keepassx")){
|
|
cout << "Warning: Could not create directory '~/.keepassx'." << endl;}
|
|
}
|
|
IniFilename=QDir::homePath()+"/.keepassx/config";
|
|
}
|
|
else
|
|
IniFilename=ArgCfg;
|
|
|
|
|
|
config = new KpxConfig(IniFilename);
|
|
fileDlgHistory.load();
|
|
|
|
//Plugins
|
|
if(config->integrPlugin()!=KpxConfig::NoIntegr){
|
|
QString LibName="libkeepassx-";
|
|
if(config->integrPlugin()==KpxConfig::KDE)
|
|
LibName+="kde.so";
|
|
else if(config->integrPlugin()==KpxConfig::Gnome)
|
|
LibName+="gnome.so";
|
|
QString filename=findPlugin(LibName);
|
|
if(filename!=QString()){
|
|
QPluginLoader plugin(filename);
|
|
if(!plugin.load()){
|
|
PluginLoadError=plugin.errorString();
|
|
qWarning("Could not load desktop integration plugin:");
|
|
qWarning(CSTR(PluginLoadError));
|
|
}
|
|
else{
|
|
QObject *plugininstance=plugin.instance();
|
|
IFileDialog* fdlg=qobject_cast<IFileDialog*>(plugininstance);
|
|
IconLoader=qobject_cast<IIconTheme*>(plugininstance);
|
|
if(IconLoader==NULL){
|
|
qWarning("Error: Integration Plugin: Could not initialize IconTheme interface.");
|
|
}
|
|
KpxFileDialogs::setPlugin(fdlg);
|
|
if(config->integrPlugin()==KpxConfig::KDE){
|
|
IKdeInit* kdeinit=qobject_cast<IKdeInit*>(plugin.instance());
|
|
app=kdeinit->getMainAppObject(argc,argv);
|
|
if(!app)PluginLoadError=QObject::tr("Initialization failed.");
|
|
}
|
|
if(config->integrPlugin()==KpxConfig::Gnome){
|
|
IGnomeInit* ginit=qobject_cast<IGnomeInit*>(plugin.instance());
|
|
if(!ginit->init(argc,argv)){
|
|
KpxFileDialogs::setPlugin(NULL);
|
|
qWarning("GtkIntegrPlugin: Gtk init failed.");
|
|
PluginLoadError=QObject::tr("Initialization failed.");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else{
|
|
qWarning(CSTR(QString("Could not load desktop integration plugin: File '%1' not found.").arg(LibName)));
|
|
PluginLoadError=QObject::tr("Could not locate library file.");
|
|
}
|
|
}
|
|
if(!app) QApplication* app=new QApplication(argc,argv);
|
|
|
|
|
|
//Internationalization
|
|
QLocale loc;
|
|
if(!ArgLang.size())
|
|
loc=QLocale::system();
|
|
else
|
|
loc=QLocale(ArgLang);
|
|
|
|
QTranslator* translator = NULL;
|
|
QTranslator* qtTranslator=NULL;
|
|
translator=new QTranslator;
|
|
qtTranslator=new QTranslator;
|
|
|
|
if(loadTranslation(translator,"keepass-",loc.name(),QStringList()
|
|
<< app->applicationDirPath()+"/../share/keepass/i18n/"
|
|
<< QDir::homePath()+"/.keepassx/" ))
|
|
{app->installTranslator(translator);
|
|
TrActive=true;}
|
|
else{
|
|
if(loc.name()!="en_US")
|
|
qWarning(QString("Kpx: No Translation found for '%1 (%2)'using 'English (UnitedStates)'")
|
|
.arg(QLocale::languageToString(loc.language()))
|
|
.arg(QLocale::countryToString(loc.country())).toAscii());
|
|
delete translator;
|
|
TrActive=false;
|
|
}
|
|
|
|
if(loadTranslation(qtTranslator,"qt_",loc.name(),QStringList()
|
|
<< QLibraryInfo::location(QLibraryInfo::TranslationsPath)
|
|
<< app->applicationDirPath()+"/../share/keepass/i18n/"
|
|
<< QDir::homePath()+"/.keepass/" ))
|
|
app->installTranslator(qtTranslator);
|
|
else{
|
|
if(loc.name()!="en_US")
|
|
qWarning(QString("Qt: No Translation found for '%1 (%2)'using 'English (UnitedStates)'")
|
|
.arg(QLocale::languageToString(loc.language()))
|
|
.arg(QLocale::countryToString(loc.country())).toAscii());
|
|
delete qtTranslator;
|
|
}
|
|
|
|
|
|
QFile templ(QDir::homePath()+"/.keepassx/detailview-template.html"); ///FIXME ArgCfg
|
|
if(templ.open(QIODevice::ReadOnly)){
|
|
DetailViewTemplate=QString::fromUtf8(templ.readAll());
|
|
templ.close();
|
|
}
|
|
else loadDefaultDetailViewTemplate();
|
|
|
|
loadImages();
|
|
KpxBookmarks::load(QDir::homePath()+"/.keepassx/bookmarks");
|
|
initYarrow(); //init random number generator
|
|
SecString::generateSessionKey();
|
|
|
|
int r=0;
|
|
KeepassMainWindow *mainWin = new KeepassMainWindow(ArgFile);
|
|
if(mainWin->Start){
|
|
mainWin->show();
|
|
r=app->exec();
|
|
}
|
|
delete mainWin;
|
|
|
|
if(templ.open(QIODevice::WriteOnly)){
|
|
templ.write(DetailViewTemplate.toUtf8());
|
|
templ.close();
|
|
}
|
|
else{
|
|
qWarning("Failed to save detail view template: %s",decodeFileError(templ.error()).toUtf8().data());
|
|
}
|
|
|
|
|
|
fileDlgHistory.save();
|
|
delete app;
|
|
delete config;
|
|
return r;
|
|
}
|
|
|
|
|
|
void loadDefaultDetailViewTemplate(){
|
|
QFile templ(":/default-detailview.html");
|
|
templ.open(QIODevice::ReadOnly);
|
|
DetailViewTemplate=QString::fromUtf8(templ.readAll());
|
|
templ.close();
|
|
DetailViewTemplate.replace("Group",QCoreApplication::translate("DetailViewTemplate","Group"));
|
|
DetailViewTemplate.replace("Title",QCoreApplication::translate("DetailViewTemplate","Title"));
|
|
DetailViewTemplate.replace("Username",QCoreApplication::translate("DetailViewTemplate","Username"));
|
|
DetailViewTemplate.replace("Password",QCoreApplication::translate("DetailViewTemplate","Password"));
|
|
DetailViewTemplate.replace("URL",QCoreApplication::translate("DetailViewTemplate","URL"));
|
|
DetailViewTemplate.replace("Creation",QCoreApplication::translate("DetailViewTemplate","Creation"));
|
|
DetailViewTemplate.replace("Last Access",QCoreApplication::translate("DetailViewTemplate","Last Access"));
|
|
DetailViewTemplate.replace("Last Modification",QCoreApplication::translate("DetailViewTemplate","Last Modification"));
|
|
DetailViewTemplate.replace("Expiration",QCoreApplication::translate("DetailViewTemplate","Expiration"));
|
|
DetailViewTemplate.replace("Comment",QCoreApplication::translate("DetailViewTemplate","Comment"));
|
|
}
|
|
|
|
//obsolete
|
|
void createBanner(QLabel *Banner,const QPixmap* symbol,QString text){
|
|
QPixmap Pixmap;
|
|
createBanner(&Pixmap,symbol,text
|
|
,Banner->width()
|
|
,config->bannerColor1()
|
|
,config->bannerColor2()
|
|
,config->bannerTextColor());
|
|
Banner->setPixmap(Pixmap);
|
|
}
|
|
|
|
void createBanner(QPixmap* Pixmap,const QPixmap* IconAlpha,const QString& Text,int Width){
|
|
createBanner(Pixmap,IconAlpha,Text,Width,config->bannerColor1(),config->bannerColor2(),config->bannerTextColor());
|
|
}
|
|
|
|
void createBanner(QPixmap* Pixmap,const QPixmap* IconAlpha,const QString& Text,int Width, QColor Color1, QColor Color2, QColor TextColor){
|
|
*Pixmap=QPixmap(Width,50);
|
|
QPainter painter(Pixmap);
|
|
QLinearGradient grad(0,0,Width,0);
|
|
grad.setColorAt(0,Color1);
|
|
grad.setColorAt(1,Color2);
|
|
painter.setPen(Qt::NoPen);
|
|
painter.setBrush(grad);
|
|
painter.drawRect(0,0,Width,50);
|
|
|
|
QPixmap Icon(32,32);
|
|
if(IconAlpha){
|
|
Icon.fill(TextColor);
|
|
Icon.setAlphaChannel(*IconAlpha);
|
|
painter.drawPixmap(10,10,Icon);
|
|
}
|
|
|
|
painter.setPen(QPen(TextColor));
|
|
painter.setFont(QFont(QApplication::font().family(),16));
|
|
painter.drawText(50,35,Text);
|
|
}
|
|
|
|
QString decodeFileError(QFile::FileError Code){
|
|
switch(Code){
|
|
case QFile::NoError: return QApplication::translate("FileErrors","No error occurred.");
|
|
case QFile::ReadError: return QApplication::translate("FileErrors","An error occurred while reading from the file.");
|
|
case QFile::WriteError: return QApplication::translate("FileErrors","An error occurred while writing to the file.");
|
|
case QFile::FatalError: return QApplication::translate("FileErrors","A fatal error occurred.");
|
|
case QFile::ResourceError: return QApplication::translate("FileErrors","An resource error occurred.");
|
|
case QFile::OpenError: return QApplication::translate("FileErrors","The file could not be opened.");
|
|
case QFile::AbortError: return QApplication::translate("FileErrors","The operation was aborted.");
|
|
case QFile::TimeOutError: return QApplication::translate("FileErrors","A timeout occurred.");
|
|
case QFile::UnspecifiedError: return QApplication::translate("FileErrors","An unspecified error occurred.");
|
|
case QFile::RemoveError: return QApplication::translate("FileErrors","The file could not be removed.");
|
|
case QFile::RenameError: return QApplication::translate("FileErrors","The file could not be renamed.");
|
|
case QFile::PositionError: return QApplication::translate("FileErrors","The position in the file could not be changed.");
|
|
case QFile::ResizeError: return QApplication::translate("FileErrors","The file could not be resized.");
|
|
case QFile::PermissionsError: return QApplication::translate("FileErrors","The file could not be accessed.");
|
|
case QFile::CopyError: return QApplication::translate("FileErrors","The file could not be copied.");
|
|
}
|
|
}
|
|
|
|
void openBrowser(QString UrlString){
|
|
QUrl url(UrlString);
|
|
if(url.scheme().isEmpty())
|
|
url=QUrl("http://"+UrlString);
|
|
if(config->urlCmd().isEmpty()){
|
|
QDesktopServices::openUrl(url);
|
|
}
|
|
else{
|
|
QStringList args=config->urlCmd().arg(url.toString()).split(' ');
|
|
QString cmd=args.takeFirst();
|
|
QProcess::startDetached(cmd,args);
|
|
}
|
|
}
|
|
|
|
///TODO 0.2.3 remove
|
|
void loadImg(QString name,QPixmap& Img){
|
|
if(Img.load(AppDir+"/../share/keepass/icons/"+name)==false){
|
|
if(Img.load(AppDir+"/share/"+name)==false){
|
|
QMessageBox::critical(0,QObject::tr("Error"),QObject::tr("File '%1' could not be found.")
|
|
.arg(name),QObject::tr("OK"),0,0,2,1);
|
|
exit(1);
|
|
}}
|
|
|
|
}
|
|
|
|
///TODO 0.2.3 remove
|
|
void loadImages(){
|
|
bool small=true;
|
|
QString ThemeDir=AppDir+"/../share/keepass/icons/nuvola/32x32";
|
|
QPixmap tmpImg;
|
|
loadImg("clientic.png",tmpImg);
|
|
EntryIcons=new QPixmap[BUILTIN_ICONS];
|
|
for(int i=0;i<BUILTIN_ICONS;i++){
|
|
EntryIcons[i]=tmpImg.copy(i*16,0,16,16);}
|
|
|
|
}
|
|
|
|
const QIcon& getIcon(const QString& name){
|
|
QIcon* CachedIcon=IconCache.value(name);
|
|
if(CachedIcon)
|
|
return *CachedIcon;
|
|
QIcon* NewIcon=NULL;
|
|
if(IconLoader){
|
|
NewIcon=new QIcon(IconLoader->getIcon(name));
|
|
if(NewIcon->isNull()){
|
|
delete NewIcon;
|
|
NewIcon=NULL;
|
|
}
|
|
else
|
|
IconCache.insert(name,NewIcon);
|
|
}
|
|
if(!NewIcon)
|
|
{
|
|
QFileInfo IconFile(AppDir+"/../share/keepass/icons/"+name+".png");
|
|
if(!IconFile.isFile() || !IconFile.exists() || !IconFile.isReadable()){
|
|
///TODO 0.2.3 error handling
|
|
qWarning("%s",CSTR(name));
|
|
}
|
|
NewIcon=new QIcon(AppDir+"/../share/keepass/icons/"+name+".png");
|
|
IconCache.insert(name,NewIcon);
|
|
}
|
|
return *NewIcon;
|
|
}
|
|
|
|
const QPixmap* getPixmap(const QString& name){
|
|
QPixmap* CachedPixmap=PixmapCache.value(name);
|
|
if(CachedPixmap)
|
|
return CachedPixmap;
|
|
QImage img;
|
|
if(!img.load(AppDir+"/../share/keepass/icons/"+name+".png")){
|
|
///TODO 0.2.3 error handling
|
|
qWarning("%s",CSTR(name));
|
|
}
|
|
QPixmap* NewPixmap=new QPixmap(QPixmap::fromImage(img));
|
|
PixmapCache.insert(name,NewPixmap);
|
|
return NewPixmap;
|
|
}
|
|
|
|
|
|
bool loadTranslation(QTranslator* tr,const QString& prefix,const QString& loc,const QStringList& paths){
|
|
for(int i=0;i<paths.size();i++)
|
|
if(tr->load(prefix+loc+".qm",paths[i])) return true;
|
|
for(int i=0;i<paths.size();i++){
|
|
QDir dir(paths[i]);
|
|
QStringList TrFiles=dir.entryList(QStringList()<<"*.qm",QDir::Files);
|
|
for(int j=0;j<TrFiles.size();j++){
|
|
if(TrFiles[j].left(prefix.length()+2)==prefix+loc.left(2)){
|
|
if(tr->load(TrFiles[j],paths[i]))return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
void parseCmdLineArgs(int argc, char** argv,QString &ArgFile,QString& ArgCfg,QString& ArgLang){
|
|
if(argc>1){
|
|
int i=1;
|
|
if(argv[i][0]!='-'){
|
|
ArgFile=QString::fromUtf8(argv[i]);
|
|
i++; }
|
|
for(i; i<argc;i++){
|
|
if(QString(argv[i])=="-help"){
|
|
cout << "KeePassX" << KEEPASS_VERSION << endl;
|
|
cout << "Usage: keepass [Filename] [Options]" << endl;
|
|
cout << " -help This Help" << endl;
|
|
cout << " -cfg <CONFIG> Use specified file for loading/saving the configuration." << endl;
|
|
cout << " -lang <LOCALE> Use specified language instead of systems default." << endl;
|
|
cout << " <LOCALE> is the ISO-639 language code with or without ISO-3166 country code" << endl;
|
|
cout << " Examples: de German" << endl;
|
|
cout << " de_CH German(Switzerland)"<<endl;
|
|
cout << " pt_BR Portuguese(Brazil)"<<endl;
|
|
exit(0);
|
|
}
|
|
else if(QString(argv[i])=="-cfg"){
|
|
if(i-1==argc){ cout << "Missing argument for -cfg" << endl; exit(1);}
|
|
else{ArgCfg=QString::fromUtf8(argv[i+1]); i++;}
|
|
}
|
|
else if(QString(argv[i])=="-lang"){
|
|
if(i-1==argc) cout << "Missing argument for -lang" << endl;
|
|
else{ArgLang=QString::fromUtf8(argv[i+1]); i++;}
|
|
}
|
|
else if(QString(argv[i])=="-test"){/*
|
|
if (testDatabase()) exit(0);
|
|
else exit(1);*/
|
|
}
|
|
else{cout << "** Unrecognized argument: " << argv[i] << endl;
|
|
exit(1);}
|
|
}
|
|
}
|
|
}
|
|
|
|
void showErrMsg(const QString& msg,QWidget* parent){
|
|
QMessageBox::critical(parent,QObject::tr("Error"),msg,QObject::tr("OK"));
|
|
}
|
|
|
|
QString findPlugin(const QString& filename){
|
|
QFileInfo info;
|
|
|
|
info.setFile(AppDir+"/../lib/"+filename);
|
|
if(info.exists() && info.isFile())
|
|
return AppDir+"/../lib/"+filename;
|
|
|
|
return QString();
|
|
}
|
|
|
|
|
|
QString makePathRelative(const QString& AbsDir,const QString& CurDir){
|
|
QStringList abs=AbsDir.split('/');
|
|
QStringList cur=CurDir.split('/');
|
|
QString rel="./";
|
|
int common=0;
|
|
for(common; common < abs.size() && common < cur.size(); common++){
|
|
if(abs[common]!=cur[common])break;
|
|
}
|
|
for(int i=0;i<cur.size()-common;i++)
|
|
rel.append("../");
|
|
for(int i=common;i<abs.size();i++)
|
|
rel.append(abs[i]+"/");
|
|
return rel;
|
|
}
|
|
|
|
|
|
QString applicationDirPath(){
|
|
QString filepath=applicationFilePath();
|
|
filepath.truncate(filepath.lastIndexOf("/"));
|
|
return filepath;
|
|
}
|
|
|
|
QString applicationFilePath()
|
|
{
|
|
#if defined( Q_WS_WIN )
|
|
QFileInfo filePath;
|
|
QT_WA({
|
|
wchar_t module_name[256];
|
|
GetModuleFileNameW(0, module_name, sizeof(module_name) / sizeof(wchar_t));
|
|
filePath = QString::fromUtf16((ushort *)module_name);
|
|
}, {
|
|
char module_name[256];
|
|
GetModuleFileNameA(0, module_name, sizeof(module_name));
|
|
filePath = QString::fromLocal8Bit(module_name);
|
|
});
|
|
|
|
return filePath.filePath();
|
|
#elif defined(Q_WS_MAC)
|
|
QString qAppFileName_str = qAppFileName();
|
|
if(!qAppFileName_str.isEmpty()) {
|
|
QFileInfo fi(qAppFileName_str);
|
|
return fi.exists() ? fi.canonicalFilePath() : QString();
|
|
}
|
|
#endif
|
|
#if defined( Q_OS_UNIX )
|
|
#ifdef Q_OS_LINUX
|
|
// Try looking for a /proc/<pid>/exe symlink first which points to
|
|
// the absolute path of the executable
|
|
QFileInfo pfi(QString::fromLatin1("/proc/%1/exe").arg(getpid()));
|
|
if (pfi.exists() && pfi.isSymLink())
|
|
return pfi.canonicalFilePath();
|
|
#endif
|
|
|
|
QString argv0 = QFile::decodeName(QByteArray(argv[0]));
|
|
QString absPath;
|
|
|
|
if (!argv0.isEmpty() && argv0.at(0) == QLatin1Char('/')) {
|
|
/*
|
|
If argv0 starts with a slash, it is already an absolute
|
|
file path.
|
|
*/
|
|
absPath = argv0;
|
|
} else if (argv0.contains(QLatin1Char('/'))) {
|
|
/*
|
|
If argv0 contains one or more slashes, it is a file path
|
|
relative to the current directory.
|
|
*/
|
|
absPath = QDir::current().absoluteFilePath(argv0);
|
|
} else {
|
|
/*
|
|
Otherwise, the file path has to be determined using the
|
|
PATH environment variable.
|
|
*/
|
|
QByteArray pEnv = qgetenv("PATH");
|
|
QDir currentDir = QDir::current();
|
|
QStringList paths = QString::fromLocal8Bit(pEnv.constData()).split(QLatin1String(":"));
|
|
for (QStringList::const_iterator p = paths.constBegin(); p != paths.constEnd(); ++p) {
|
|
if ((*p).isEmpty())
|
|
continue;
|
|
QString candidate = currentDir.absoluteFilePath(*p + QLatin1Char('/') + argv0);
|
|
QFileInfo candidate_fi(candidate);
|
|
if (candidate_fi.exists() && !candidate_fi.isDir()) {
|
|
absPath = candidate;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
absPath = QDir::cleanPath(absPath);
|
|
|
|
QFileInfo fi(absPath);
|
|
return fi.exists() ? fi.canonicalFilePath() : QString();
|
|
#endif
|
|
}
|
|
|