/*************************************************************************** * 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; either version 2 of the License, or * * (at your option) any later version. * * * * 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 #include "plugins/interfaces/IFileDialog.h" #include "plugins/interfaces/IKdeInit.h" #include "plugins/interfaces/IGnomeInit.h" #include "lib/FileDialogs.h" #include "main.h" #include "lib/FileDialogs.h" #include "PwmConfig.h" #include "StandardDatabase.h" #include "mainwindow.h" #include "crypto/yarrow.h" using namespace std; #ifdef Q_WS_X11 #include #define XK_LATIN1 #define XK_MISCELLANY #define XK_XKB_KEYS #include #include #endif #define CSTR(x)(x.toUtf8().data()) QHashPixmapCache; QHashIconCache; CConfig config; QSettings* settings; QString AppDir; QString PluginLoadError; bool TrActive; QString DetailViewTemplate; QPixmap* EntryIcons; 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); int main(int argc, char **argv) { QString ArgFile,ArgCfg,ArgLang,IniFilename; QApplication* app=NULL; AppDir=QString(argv[0]); AppDir.truncate(AppDir.lastIndexOf("/")); //Load Config if(ArgCfg==QString()){ if(!QDir(QDir::homePath()+"/.keepass").exists()){ QDir conf(QDir::homePath()); if(!conf.mkdir(".keepass")){ cout << "Warning: Could not create directory '~/.keepass'." << endl;} } IniFilename=QDir::homePath()+"/.keepass/config"; config.loadFromIni(IniFilename); } else{ IniFilename=ArgCfg; config.loadFromIni(IniFilename);} settings = new QSettings(QDir::homePath()+"/.keepassx/config",QSettings::IniFormat); fileDlgHistory.load(); //Plugins if(config.IntegrPlugin!=CConfig::NONE){ QString LibName="libkeepassx-"; if(config.IntegrPlugin==CConfig::KDE) LibName+="kde.so"; else if(config.IntegrPlugin==CConfig::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{ IFileDialog* fdlg=qobject_cast(plugin.instance()); KpxFileDialogs::setPlugin(fdlg); if(config.IntegrPlugin==CConfig::KDE){ IKdeInit* kdeinit=qobject_cast(plugin.instance()); app=kdeinit->getMainAppObject(argc,argv); if(!app)PluginLoadError=QObject::tr("Initialization failed."); } if(config.IntegrPlugin==CConfig::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(!app) QApplication* app=new QApplication(argc,argv); parseCmdLineArgs(argc,argv,ArgFile,ArgCfg,ArgLang); //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(); 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(!config.saveToIni(IniFilename)) QMessageBox::warning(NULL,QObject::tr("Warning"), QObject::tr("Could not save configuration file.\nMake sure you have write access to '~/.keepass'."), QObject::tr("OK"),"","",0.0); 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 settings; 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(settings->value("BrowserCmd","<>").toString() == "<>"){ QDesktopServices::openUrl(url); } else{ QStringList args=settings->value("BrowserCmd","<>").toString().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;iload(prefix+loc+".qm",paths[i])) return true; for(int i=0;iload(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 Use specified file for loading/saving the configuration." << 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)"<