/*************************************************************************** * 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 #include #include #include #include #include #include #include #include #include #include #include /* #include #include #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" #if defined(Q_WS_X11) && defined(GLOBAL_AUTOTYPE) #include "Application_X11.h" #endif using namespace std; QHashPixmapCache; QHashIconCache; KpxConfig *config; QString AppDir; QString PluginLoadError; bool TrActive; QString DetailViewTemplate; QPixmap* EntryIcons; //IIconTheme* IconLoader=NULL; //TODO plugins char ** argv; inline void loadImages(); inline void parseCmdLineArgs(int argc, char** argv,QString &ArgFile,QString& ArgCfg,QString& ArgLang,bool& ArgMin,bool& ArgLock); bool loadTranslation(QTranslator* tr,const QString& prefix,const QString& LocaleCode,const QStringList& SearchPaths); int main(int argc, char **_argv) { argv=_argv; QString ArgFile,ArgCfg,ArgLang,IniFilename; QApplication* app=NULL; AppDir=applicationDirPath(); bool ArgMin = false; bool ArgLock = false; parseCmdLineArgs(argc,argv,ArgFile,ArgCfg,ArgLang,ArgMin,ArgLock); 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(); // TODO 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(plugininstance); IconLoader=qobject_cast(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(plugin.instance()); app=kdeinit->getMainAppObject(argc,argv); if(!app)PluginLoadError=QObject::tr("Initialization failed."); } if(config->integrPlugin()==KpxConfig::Gnome){ IGnomeInit* ginit=qobject_cast(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 defined(Q_WS_X11) && defined(GLOBAL_AUTOTYPE) if(!app) new KeepassApplication(argc,argv); #else if(!app) new QApplication(argc,argv); #endif //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; } DetailViewTemplate=config->detailViewTemplate(); loadImages(); KpxBookmarks::load(); initYarrow(); //init random number generator SecString::generateSessionKey(); QApplication::setQuitOnLastWindowClosed(false); KeepassMainWindow *mainWin = new KeepassMainWindow(ArgFile,ArgMin,ArgLock); int r=app->exec(); delete mainWin; fileDlgHistory.save(); delete app; delete config; return r; } 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."); } return QString(); } void openBrowser(IEntryHandle* entry){ QString url = entry->url(); url.replace("{TITLE}", entry->title(), Qt::CaseInsensitive); url.replace("{USERNAME}", entry->username(), Qt::CaseInsensitive); if (url.contains("{PASSWORD}",Qt::CaseInsensitive)){ SecString password=entry->password(); password.unlock(); url.replace("{PASSWORD}", password, Qt::CaseInsensitive); } openBrowser(url); } void openBrowser(const QString& UrlString){ if (UrlString.startsWith("cmd://") && UrlString.length()>6){ QProcess::startDetached(UrlString.right(UrlString.length()-6)); return; } QUrl url(UrlString); if(url.scheme().isEmpty()) url=QUrl("http://"+UrlString); if(config->urlCmdDef()){ QDesktopServices::openUrl(url); } else{ QByteArray UrlEncoded = url.toEncoded(); QString browser = config->urlCmd(); if (browser.contains("%u", Qt::CaseInsensitive)) browser.replace("%u", UrlEncoded, Qt::CaseInsensitive); else if (browser.contains("%1")) browser.replace("%1", UrlEncoded); else browser.append(" ").append(UrlEncoded); QProcess::startDetached(browser); } } ///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,QApplication::translate("Main","Error"), QApplication::translate("Main","File '%1' could not be found.") .arg(name),QApplication::translate("Main","OK"),0,0,2,1); exit(1); } } } ///TODO 0.2.3 remove void loadImages(){ QPixmap tmpImg; loadImg("clientic.png",tmpImg); EntryIcons=new QPixmap[BUILTIN_ICONS]; for(int i=0;igetIcon(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;iload(prefix+loc+".qm",paths[i])) return true; for(int i=0;iload(TrFiles[j],paths[i]))return true; } } } return false; } void printHelp(){ cout << "KeePassX" << APP_VERSION << endl; cout << "Usage: keepass [Filename] [Options]" << endl; cout << " -help This Help" << endl; cout << " -cfg Use specified file for loading/saving the configuration." << endl; cout << " -min Start minimized." << endl; cout << " -lock Start locked." << endl; cout << " -lang Use specified language instead of systems default." << endl; cout << " is the ISO-639 language code with or without ISO-3166 country code" << endl; cout << " Examples: de German" << endl; cout << " de_CH German(Switzerland)"<1){ int i=1; if(argv[i][0]!='-'){ ArgFile=QString::fromUtf8(argv[i]); i++; } for(; i/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 }