Kennwortmanager KeePassX Weiterentwicklung der Version 1
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.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
 
 
 
 
 
keepassx1/src/lib/tools.cpp

408 lines
12 KiB

/***************************************************************************
* Copyright (C) 2005-2008 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 <QDesktopServices>
#include <QLibraryInfo>
#include <QProcess>
#include <QTranslator>
#if defined(Q_OS_LINUX) || defined(Q_OS_MAC)
#include <sys/mman.h>
#include <unistd.h>
#elif defined(Q_OS_WIN32)
#include <QLibrary>
#include <windows.h>
#include <io.h>
#endif
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);
painter.drawPixmap(10,10, *IconAlpha);
}
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.trimmed().isEmpty())
return;
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() || url.scheme()=="mailto"){
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);
}
}
QString makePathRelative(const QString& AbsDir,const QString& CurDir){
QStringList abs=AbsDir.split('/');
QStringList cur=CurDir.split('/');
QString rel="./";
int common;
for(common=0; 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;
}
void showErrMsg(const QString& msg,QWidget* parent){
QMessageBox::critical(parent, QApplication::translate("Main","Error"), msg);
}
QString getImageFile(const QString& name){
if (QFile::exists(DataDir+"/icons/"+name))
return DataDir+"/icons/"+name;
else{
QString errMsg = QApplication::translate("Main","File '%1' could not be found.").arg(name);
showErrMsg(errMsg);
qFatal("File '%s' could not be found.", CSTR(errMsg));
return QString();
}
}
const QIcon& getIcon(const QString& name){
static QHash<QString,QIcon*>IconCache;
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)
{
NewIcon=new QIcon(getImageFile(name+".png"));
IconCache.insert(name,NewIcon);
}
return *NewIcon;
}
const QPixmap* getPixmap(const QString& name){
static QHash<QString,QPixmap*>PixmapCache;
QPixmap* CachedPixmap=PixmapCache.value(name);
if(CachedPixmap)
return CachedPixmap;
QImage img(getImageFile(name+".png"));
QPixmap* NewPixmap=new QPixmap(QPixmap::fromImage(img));
PixmapCache.insert(name,NewPixmap);
return NewPixmap;
}
bool createKeyFile(const QString& filename,QString* error,int length, bool Hex){
QFile file(filename);
if(!file.open(QIODevice::WriteOnly|QIODevice::Truncate|QIODevice::Unbuffered)){
*error=decodeFileError(file.error());
return false;
}
if(Hex)length*=2;
unsigned char* key=new unsigned char[length];
randomize(key,length);
if(Hex){
// convert binary data to hex code (8 bit ==> 2 digits)
for(int i=0; i<length; i+=2){
unsigned char dig1,dig2;
dig1=key[i]/16;
key[i]-=(16*dig1);
dig2=key[i];
if(dig1>9)key[i]='A'+dig1-10;
else key[i]='0'+dig1;
if(dig2>9)key[i+1]='A'+dig2-10;
else key[i+1]='0'+dig2;
}
}
if(file.write((char*)key,length)==-1){
delete [] key;
*error=decodeFileError(file.error());
file.close();
return false;
}
file.close();
delete [] key;
return true;
}
bool lockPage(void* addr, int len){
#if defined(Q_OS_LINUX) || defined(Q_OS_MAC)
return (mlock(addr, len)==0);
#elif defined(Q_OS_WIN32)
return VirtualLock(addr, len);
#else
return false;
#endif
}
bool unlockPage(void* addr, int len){
#if defined(Q_OS_LINUX) || defined(Q_OS_MAC)
return (munlock(addr, len)==0);
#elif defined(Q_OS_WIN)
return VirtualUnlock(addr, len);
#else
return false;
#endif
}
bool syncFile(QFile* file) {
if (!file->flush())
return false;
#if defined(Q_OS_LINUX) || defined(Q_OS_MAC)
return (fsync(file->handle())==0);
#elif defined(Q_OS_WIN32)
return (_commit(file->handle())==0);
#else
return false;
#endif
}
QTranslator* translator = new QTranslator();
QTranslator* qtTranslator = new QTranslator();
bool translatorActive = false;
bool qtTranslatorActive = false;
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 deactivateTranslators(bool qtOnly=false){
if (translatorActive && !qtOnly){
QApplication::removeTranslator(translator);
translatorActive = false;
}
if (qtTranslatorActive){
QApplication::removeTranslator(qtTranslator);
qtTranslatorActive = false;
}
}
void installTranslator(){
QString language = config->language();
if (language=="auto")
language = QLocale::system().name();
if (language.isEmpty() || language=="en_US"){
deactivateTranslators();
return;
}
if (loadTranslation(translator,"keepassx-",language,QStringList()
<< HomeDir << DataDir+"/i18n/"))
{
if (!translatorActive){
QApplication::installTranslator(translator);
translatorActive = true;
}
}
else{
deactivateTranslators();
return;
}
if (loadTranslation(qtTranslator,"qt_",language,QStringList()
<< HomeDir << DataDir+"/i18n/"
<< QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
{
if (!qtTranslatorActive){
QApplication::installTranslator(qtTranslator);
qtTranslatorActive = true;
}
}
else{
deactivateTranslators(true);
}
}
bool isTranslationActive(){
return translatorActive;
}
bool operator<(const Translation& t1, const Translation& t2){
return t1.nameLong < t2.nameLong;
}
QList<Translation> getAllTranslations(){
QTranslator tmpTranslator;
QList<Translation> translations;
QSet<QString> names;
QStringList paths = QStringList() << DataDir+"/i18n/" << HomeDir;
QRegExp filename("keepassx-([^_]{2}_[^\\.]{2}|[^\\.]{2})\\.qm");
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 (filename.exactMatch(TrFiles[j]) && TrFiles[j]!="keepassx-xx_XX.qm" &&
tmpTranslator.load(TrFiles[j],paths[i]) && !names.contains(filename.cap(1)))
{
Translation t;
t.nameCode = filename.cap(1);
t.nameLong = tmpTranslator.translate("Translation", "$LANGUAGE_NAME", "Insert your language name in the format: English (United States)");
t.author = tmpTranslator.translate("Translation", "$TRANSLATION_AUTHOR");
QLocale l(t.nameCode);
t.nameEnglish = QLocale::languageToString(l.language());
if (t.nameCode.size()==5){
QString country = QLocale::countryToString(l.country());
int size = country.size();
for (int k=1; k<size; k++){
if (country[k].isUpper()){
country.insert(k, " ");
k += 2;
size++;
}
}
t.nameEnglish.append(" (").append(country).append(")");
}
if (t.nameLong.isEmpty())
t.nameLong = t.nameEnglish;
translations << t;
names << t.nameCode;
}
}
}
qSort(translations.begin(), translations.end());
return translations;
}
// from src/corelib/qsettings.cpp:
#ifdef Q_OS_WIN
QString qtWindowsConfigPath(int type)
{
QString result;
QLibrary library(QLatin1String("shell32"));
QT_WA( {
typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, LPTSTR, int, BOOL);
GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve("SHGetSpecialFolderPathW");
if (SHGetSpecialFolderPath) {
TCHAR path[MAX_PATH];
SHGetSpecialFolderPath(0, path, type, FALSE);
result = QString::fromUtf16((ushort*)path);
}
} , {
typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, char*, int, BOOL);
GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve("SHGetSpecialFolderPathA");
if (SHGetSpecialFolderPath) {
char path[MAX_PATH];
SHGetSpecialFolderPath(0, path, type, FALSE);
result = QString::fromLocal8Bit(path);
}
} );
return result;
}
#endif // Q_OS_WIN