From df8a6969af86dfd1b6dc0683fc878b883df1bc97 Mon Sep 17 00:00:00 2001 From: tariq Date: Sat, 1 Apr 2006 21:48:53 +0000 Subject: [PATCH] work on custom icon feature git-svn-id: https://svn.code.sf.net/p/keepassx/code/trunk@66 b624d157-de02-0410-bad0-e51aec6abb33 --- src/Database.h | 4 + src/PwManager.cpp | 227 +++++++++++++++++++++++++++++++--- src/PwManager.h | 7 ++ src/dialogs/EditEntryDlg.cpp | 6 +- src/dialogs/EditGroupDlg.cpp | 11 +- src/dialogs/SelectIconDlg.cpp | 32 ++++- src/dialogs/SelectIconDlg.h | 3 + src/forms/SelectIconDlg.ui | 6 +- src/lib/EntryView.cpp | 4 +- src/lib/GroupView.cpp | 2 +- src/main.cpp | 4 +- src/main.h | 4 +- 12 files changed, 271 insertions(+), 39 deletions(-) diff --git a/src/Database.h b/src/Database.h index fd539b6..8e25088 100644 --- a/src/Database.h +++ b/src/Database.h @@ -23,6 +23,7 @@ #include #include #include +#include #include "lib/SecString.h" using namespace std; @@ -115,6 +116,9 @@ public: virtual bool isParentGroup(CGroup* Group,CGroup* PotenialParent)=0; virtual QString getError()=0; //get first error virtual QString getErrors()=0; //get all errors in a \n seperated String + virtual QPixmap& icon(int index)=0; + virtual int numIcons()=0; + virtual void addIcon(const QPixmap& icon)=0; Q_UINT32 CryptoAlgorithmus; Q_UINT32 KeyEncRounds; diff --git a/src/PwManager.cpp b/src/PwManager.cpp index 38f027c..bf72406 100755 --- a/src/PwManager.cpp +++ b/src/PwManager.cpp @@ -26,12 +26,14 @@ #include #include #include +#include #include "crypto/sha256.h" #include "crypto/rijndael.h" #include "crypto/twoclass.h" #include "lib/random.h" using namespace std; #include "PwManager.h" +#include "main.h" #define _ERROR Errors << QString("Unexpected error in: %1, Line:%2").arg(__FILE__).arg(__LINE__); @@ -253,12 +255,97 @@ bool PwDatabase::parseCustomIconsMetaStream(const QByteArray& dta){ Q_UINT32 NumIcons,NumEntries,offset; memcpyFromLEnd32(&NumIcons,dta.data()); memcpyFromLEnd32(&NumEntries,dta.data()+4); -offset+=4; +offset=8; +CustomIcons.clear(); +for(int i=0;i dta.size()){ + CustomIcons.clear(); + return false;} + offset+=4; + if(!CustomIcons.back().loadFromData((const unsigned char*)dta.data()+offset,Size,"PNG")){ + CustomIcons.clear(); + return false;} + offset+=Size; + if(offset > dta.size()){ + CustomIcons.clear(); + return false;} +} +for(int i=0;iBinaryDesc="bin-stream"; +e->Title="Meta-Info"; +e->UserName="SYSTEM"; +e->Additional="KPX_CUSTOM_ICONS"; +e->URL="$"; +e->ImageID=0; +int Size=8; +Q_UINT32 NumEntries=0; +for(int i=0;i= BUILTIN_ICONS){ Size+=8; NumEntries++;} +} +Size+=CustomIcons.size()*1000; // 1KB +e->BinaryData.reserve(Size); +e->BinaryData.resize(8); +Q_UINT32 NumIcons=CustomIcons.size(); -return true; +memcpyToLEnd32(e->BinaryData.data(),&NumIcons); +memcpyToLEnd32(e->BinaryData.data()+4,&NumEntries); +for(int i=0;iBinaryData.append(QByteArray::fromRawData(ImgSizeBin,4)); + e->BinaryData.append(png); +} +for(Q_UINT32 i=0;i= BUILTIN_ICONS){ + char Bin[8]; + memcpyToLEnd32(Bin,&i); + Q_UINT32 id=Entries[i].ImageID-BUILTIN_ICONS; + memcpyToLEnd32(Bin+4,&id); + e->BinaryData.append(QByteArray::fromRawData(Bin,8)); + } +} + + +} + + +int PwDatabase::numIcons(){ +return BUILTIN_ICONS+CustomIcons.size(); +} + +QPixmap& PwDatabase::icon(int i){ +if(i>=BUILTIN_ICONS+CustomIcons.size()) + return EntryIcons[0]; +if(iisOpen()){ } unsigned int FileSize; -Entries+=UnkownMetaStreams; ///@FIXME ID conflicts??? + +QList MetaStreams; +for(int i=0; iAdditional.utf8().length()+1 + +MetaStreams[i]->BinaryData.length(); +} + + // Round up filesize to 16-byte boundary for Rijndael/Twofish FileSize = (FileSize + 16) - (FileSize % 16); char* buffer=new char[FileSize+16]; @@ -674,8 +772,8 @@ Flags = PWM_FLAG_SHA2; if(CryptoAlgorithmus == ALGO_AES) Flags |= PWM_FLAG_RIJNDAEL; else if(CryptoAlgorithmus == ALGO_TWOFISH) Flags |= PWM_FLAG_TWOFISH; Version = PWM_DBVER_DW; -NumGroups = Groups.size(); //-> (+MetaStreams) -NumEntries = Entries.size(); +NumGroups = Groups.size(); +NumEntries = Entries.size()+MetaStreams.size(); getRandomBytes(FinalRandomSeed,1,16,false); getRandomBytes(TrafoRandomSeed,1,32,false); @@ -750,7 +848,9 @@ for(int i = 0; i < Entries.size(); i++){ FieldType = 0x0003; FieldSize = 4; memcpyToLEnd16(buffer+pos, &FieldType); pos += 2; memcpyToLEnd32(buffer+pos, &FieldSize); pos += 4; - memcpyToLEnd32(buffer+pos, &Entries[i].ImageID); pos += 4; + Q_UINT32 ImgID=Entries[i].ImageID; + if(ImgID>=BUILTIN_ICONS)ImgID=0; + memcpyToLEnd32(buffer+pos,&ImgID); pos += 4; FieldType = 0x0004; @@ -823,6 +923,95 @@ for(int i = 0; i < Entries.size(); i++){ memcpyToLEnd16(buffer+pos, &FieldType); pos += 2; memcpyToLEnd32(buffer+pos, &FieldSize); pos += 4; } + +for(int i = 0; i < MetaStreams.size(); i++){ + FieldType = 0x0001; FieldSize = 16; + memcpyToLEnd16(buffer+pos, &FieldType); pos += 2; + memcpyToLEnd32(buffer+pos, &FieldSize); pos += 4; + memcpy(buffer+pos, &MetaStreams[i]->ID, 16); pos += 16; + + FieldType = 0x0002; FieldSize = 4; + memcpyToLEnd16(buffer+pos, &FieldType); pos += 2; + memcpyToLEnd32(buffer+pos, &FieldSize); pos += 4; + memcpyToLEnd32(buffer+pos, &MetaStreams[i]->GroupID); pos += 4; + + FieldType = 0x0003; FieldSize = 4; + memcpyToLEnd16(buffer+pos, &FieldType); pos += 2; + memcpyToLEnd32(buffer+pos, &FieldSize); pos += 4; + memcpyToLEnd32(buffer+pos, &MetaStreams[i]->ImageID); pos += 4; + + + FieldType = 0x0004; + FieldSize = MetaStreams[i]->Title.utf8().length() + 1; // Add terminating NULL character space + memcpyToLEnd16(buffer+pos, &FieldType); pos += 2; + memcpyToLEnd32(buffer+pos, &FieldSize); pos += 4; + memcpy(buffer+pos, MetaStreams[i]->Title.utf8(),FieldSize); pos += FieldSize; + + FieldType = 0x0005; + FieldSize = MetaStreams[i]->URL.utf8().length() + 1; // Add terminating NULL character space + memcpyToLEnd16(buffer+pos, &FieldType); pos += 2; + memcpyToLEnd32(buffer+pos, &FieldSize); pos += 4; + memcpy(buffer+pos, MetaStreams[i]->URL.utf8(),FieldSize); pos += FieldSize; + + FieldType = 0x0006; + FieldSize = MetaStreams[i]->UserName.utf8().length() + 1; // Add terminating NULL character space + memcpyToLEnd16(buffer+pos, &FieldType); pos += 2; + memcpyToLEnd32(buffer+pos, &FieldSize); pos += 4; + memcpy(buffer+pos, MetaStreams[i]->UserName.utf8(),FieldSize); pos += FieldSize; + + FieldType = 0x0007; + FieldSize = MetaStreams[i]->Password.length() + 1; // Add terminating NULL character space + memcpyToLEnd16(buffer+pos, &FieldType); pos += 2; + memcpyToLEnd32(buffer+pos, &FieldSize); pos += 4; + MetaStreams[i]->Password.unlock(); + memcpy(buffer+pos, MetaStreams[i]->Password.string(),FieldSize); pos += FieldSize; + MetaStreams[i]->Password.lock(); + + FieldType = 0x0008; + FieldSize = MetaStreams[i]->Additional.utf8().length() + 1; // Add terminating NULL character space + memcpyToLEnd16(buffer+pos, &FieldType); pos += 2; + memcpyToLEnd32(buffer+pos, &FieldSize); pos += 4; + memcpy(buffer+pos, MetaStreams[i]->Additional.utf8(),FieldSize); pos += FieldSize; + + FieldType = 0x0009; FieldSize = 5; + memcpyToLEnd16(buffer+pos, &FieldType); pos += 2; + memcpyToLEnd32(buffer+pos, &FieldSize); pos += 4; + dateToPackedStruct5(MetaStreams[i]->Creation,(unsigned char*)buffer+pos); pos+=5; + + + FieldType = 0x000A; FieldSize = 5; + memcpyToLEnd16(buffer+pos, &FieldType); pos += 2; + memcpyToLEnd32(buffer+pos, &FieldSize); pos += 4; + dateToPackedStruct5(MetaStreams[i]->LastMod,(unsigned char*)buffer+pos); pos+=5; + + FieldType = 0x000B; FieldSize = 5; + memcpyToLEnd16(buffer+pos, &FieldType); pos += 2; + memcpyToLEnd32(buffer+pos, &FieldSize); pos += 4; + dateToPackedStruct5(MetaStreams[i]->LastAccess,(unsigned char*)buffer+pos); pos+=5; + + FieldType = 0x000C; FieldSize = 5; + memcpyToLEnd16(buffer+pos, &FieldType); pos += 2; + memcpyToLEnd32(buffer+pos, &FieldSize); pos += 4; + dateToPackedStruct5(MetaStreams[i]->Expire,(unsigned char*)buffer+pos); pos+=5; + + FieldType = 0x000D; + FieldSize = MetaStreams[i]->BinaryDesc.utf8().length() + 1; // Add terminating NULL character space + memcpyToLEnd16(buffer+pos, &FieldType); pos += 2; + memcpyToLEnd32(buffer+pos, &FieldSize); pos += 4; + memcpy(buffer+pos, MetaStreams[i]->BinaryDesc.utf8(),FieldSize); pos += FieldSize; + + FieldType = 0x000E; FieldSize = MetaStreams[i]->BinaryData.length(); + memcpyToLEnd16(buffer+pos, &FieldType); pos += 2; + memcpyToLEnd32(buffer+pos, &FieldSize); pos += 4; + if((!MetaStreams[i]->BinaryData.isNull()) && (FieldSize != 0)) + memcpy(buffer+pos, MetaStreams[i]->BinaryData.data(), FieldSize); + pos += FieldSize; + + FieldType = 0xFFFF; FieldSize = 0; + memcpyToLEnd16(buffer+pos, &FieldType); pos += 2; + memcpyToLEnd32(buffer+pos, &FieldSize); pos += 4; +} + sha256_context context; sha256_starts(&context); sha256_update(&context,(unsigned char*)buffer+DB_HEADER_SIZE, pos - DB_HEADER_SIZE); diff --git a/src/PwManager.h b/src/PwManager.h index e21b60f..16730b9 100755 --- a/src/PwManager.h +++ b/src/PwManager.h @@ -36,6 +36,7 @@ #include #include #include +#include #include "lib/SecString.h" #include "Database.h" @@ -76,8 +77,12 @@ public: CEntry* addEntry(CEntry* NewEntry); void merge(Database* db2); bool isParentGroup(CGroup* Group,CGroup* PotenialParent); + QString getError(); //get first error QString getErrors(); //get all errors in a \n seperated String + QPixmap& icon(int index); + int numIcons(); + void addIcon(const QPixmap& icon); QListGroups; QListEntries; @@ -85,6 +90,7 @@ private: bool IsMetaStream(CEntry& Entry); bool parseMetaStream(const CEntry& Entry); bool parseCustomIconsMetaStream(const QByteArray& data); + void createCustomIconsMetaStream(CEntry* dst); void transformKey(Q_UINT8* src,Q_UINT8* dst,Q_UINT8* seed,int rounds); bool readHeader(char* raw); bool isGroupIdInUse(Q_UINT32 GroupID); @@ -93,6 +99,7 @@ private: Q_UINT32 getNewEntrySid(); bool convHexToBinaryKey(char* HexKey, char* dst); QStringList Errors; + QList CustomIcons; QList UnkownMetaStreams; }; diff --git a/src/dialogs/EditEntryDlg.cpp b/src/dialogs/EditEntryDlg.cpp index 538eab7..5877b5d 100755 --- a/src/dialogs/EditEntryDlg.cpp +++ b/src/dialogs/EditEntryDlg.cpp @@ -133,10 +133,10 @@ if(event->spontaneous()==false){ } void CEditEntryDlg::InitIconComboBox(){ -for(int i=0;iinsertItem(EntryIcons[i],"",i); +for(int i=0;inumIcons();i++){ + Combo_IconPicker->insertItem(db->icon(i),"",i); } -Combo_IconPicker->setCurrentItem(entry->ImageID); + Combo_IconPicker->setCurrentItem(entry->ImageID); } diff --git a/src/dialogs/EditGroupDlg.cpp b/src/dialogs/EditGroupDlg.cpp index 43054da..f3e31b8 100755 --- a/src/dialogs/EditGroupDlg.cpp +++ b/src/dialogs/EditGroupDlg.cpp @@ -44,12 +44,13 @@ CEditGroupDialog::~CEditGroupDialog() void CEditGroupDialog::showEvent(QShowEvent *event){ if(event->spontaneous()==false){ -EditTitle->setText(GroupName); -for(int i=0;iinsertItem(EntryIcons[i],"",i); + EditTitle->setText(GroupName); + for(int i=0;inumIcons();i++){ + ComboIconPicker->insertItem(db->icon(i),"",i); + } + ComboIconPicker->setCurrentItem(IconID); +} } -ComboIconPicker->setCurrentItem(IconID); -}} void CEditGroupDialog::OnOK() { diff --git a/src/dialogs/SelectIconDlg.cpp b/src/dialogs/SelectIconDlg.cpp index 29cc1ac..59d6049 100644 --- a/src/dialogs/SelectIconDlg.cpp +++ b/src/dialogs/SelectIconDlg.cpp @@ -18,13 +18,41 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ +#include +#include +#include +#include +#include +#include #include "SelectIconDlg.h" + CSelectIconDlg::CSelectIconDlg(Database* database,QWidget* parent,const char* name, bool modal, Qt::WFlags fl):QDialog(parent,name,modal,fl){ setupUi(this); db=database; -for(int i=0; iaddItem(new QListWidgetItem(QIcon(EntryIcons[i]),QString::number(i))); + +connect(Button_AddIcon, SIGNAL(clicked()), this, SLOT(OnAddIcon())); + +for(int i=0; inumIcons(); i++){ + if(iaddItem(new QListWidgetItem(QIcon(db->icon(i)),QString::number(i))); + else + List->addItem(new QListWidgetItem(QIcon(db->icon(i)),"["+QString::number(i)+"]")); +} +} + + +void CSelectIconDlg::OnAddIcon(){ +QStringList filenames=QFileDialog::getOpenFileNames(this,tr("Add Icons..."),QDir::homePath()); +QStringList errors; +for(int i=0;iaddIcon(icon.scaled(16,16,Qt::KeepAspectRatio,Qt::SmoothTransformation)); } +if(errors.size()) + QMessageBox::warning(this,tr("Error"),tr("An error occured while loading the icon(s):\n")); } \ No newline at end of file diff --git a/src/dialogs/SelectIconDlg.h b/src/dialogs/SelectIconDlg.h index f0134db..23e640f 100644 --- a/src/dialogs/SelectIconDlg.h +++ b/src/dialogs/SelectIconDlg.h @@ -30,6 +30,9 @@ class CSelectIconDlg:public QDialog, public Ui_SelectIconDlg{ public: CSelectIconDlg(Database* db,QWidget* parent = 0, const char* name = 0, bool modal = false, Qt::WFlags fl = 0); +public slots: + void OnAddIcon(); + private: Database* db; diff --git a/src/forms/SelectIconDlg.ui b/src/forms/SelectIconDlg.ui index eb3ed9c..7fede46 100644 --- a/src/forms/SelectIconDlg.ui +++ b/src/forms/SelectIconDlg.ui @@ -72,7 +72,7 @@ 6 - + Add Custom Icon... @@ -92,7 +92,7 @@ - + Pick @@ -112,7 +112,7 @@ - Button_Ok + Button_PickIcon clicked() SelectIconDlg accept() diff --git a/src/lib/EntryView.cpp b/src/lib/EntryView.cpp index de41e59..30f9ca6 100644 --- a/src/lib/EntryView.cpp +++ b/src/lib/EntryView.cpp @@ -155,7 +155,7 @@ void KeepassEntryView::setEntry(CEntry* entry){ tmp->setText(j++,entry->LastAccess.date().toString(Qt::LocalDate));} if(config.Columns[9]){ tmp->setText(j++,entry->BinaryDesc);} - Items.back()->setIcon(0,EntryIcons[entry->ImageID]); + Items.back()->setIcon(0,db->icon(entry->ImageID)); } void KeepassEntryView::refreshItems(){ @@ -193,7 +193,7 @@ for(int i=0;isetText(j++,entry->LastAccess.date().toString(Qt::LocalDate));} if(config.Columns[9]){ tmp->setText(j++,entry->BinaryDesc);} - tmp->setIcon(0,EntryIcons[entry->ImageID]); + tmp->setIcon(0,db->icon(entry->ImageID)); } } diff --git a/src/lib/GroupView.cpp b/src/lib/GroupView.cpp index 45295f0..73ffffa 100644 --- a/src/lib/GroupView.cpp +++ b/src/lib/GroupView.cpp @@ -231,7 +231,7 @@ if(db->group(i).Level==0){ Items.back()->pGroup=&db->group(i); } } -Items.back()->setIcon(0,EntryIcons[db->group(i).ImageID]); +Items.back()->setIcon(0,db->icon(db->group(i).ImageID)); } for(int i=0;i #define KEEPASS_VERSION "0.2.1" -#define NUM_CLIENT_ICONS 62 +#define BUILTIN_ICONS 62 typedef enum tKeyType {PASSWORD=0,KEYFILE=1,BOTH=2}; class CConfig; @@ -66,4 +66,4 @@ extern QIcon *Icon_Configure; extern QIcon *Icon_Help; -#endif \ No newline at end of file +#endif