work on custom icon feature

git-svn-id: https://svn.code.sf.net/p/keepassx/code/trunk@66 b624d157-de02-0410-bad0-e51aec6abb33
master
tariq 18 years ago
parent 1c513d8f3c
commit df8a6969af
  1. 4
      src/Database.h
  2. 227
      src/PwManager.cpp
  3. 7
      src/PwManager.h
  4. 6
      src/dialogs/EditEntryDlg.cpp
  5. 11
      src/dialogs/EditGroupDlg.cpp
  6. 32
      src/dialogs/SelectIconDlg.cpp
  7. 3
      src/dialogs/SelectIconDlg.h
  8. 6
      src/forms/SelectIconDlg.ui
  9. 4
      src/lib/EntryView.cpp
  10. 2
      src/lib/GroupView.cpp
  11. 4
      src/main.cpp
  12. 4
      src/main.h

@ -23,6 +23,7 @@
#include <QList>
#include <QDateTime>
#include <QFile>
#include <QPixmap>
#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;

@ -26,12 +26,14 @@
#include <qobject.h>
#include <qdatetime.h>
#include <QSysInfo>
#include <QBuffer>
#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<NumIcons;i++){
CustomIcons << QPixmap();
Q_UINT32 Size;
memcpyFromLEnd32(&Size,dta.data()+offset);
if(offset+Size > 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;i<NumEntries;i++){
Q_UINT32 Entry,Icon;
memcpyFromLEnd32(&Entry,dta.data()+offset);
offset+=4;
memcpyFromLEnd32(&Icon,dta.data()+offset);
offset+=4;
Entries[Entry].ImageID=Icon;
}
return true;
}
void PwDatabase::createCustomIconsMetaStream(CEntry* e){
e->BinaryDesc="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<Entries.size();i++){
if(Entries[i].ImageID >= 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;i<CustomIcons.size();i++){
Q_UINT32 ImgSize;
char ImgSizeBin[4];
QByteArray png;
png.reserve(1000);
QBuffer buffer(&png);
CustomIcons[i].save(&buffer,"PNG",0);
ImgSize=png.size();
memcpyToLEnd32(ImgSizeBin,&ImgSize);
e->BinaryData.append(QByteArray::fromRawData(ImgSizeBin,4));
e->BinaryData.append(png);
}
for(Q_UINT32 i=0;i<Entries.size();i++){
if(Entries[i].ImageID >= 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(i<BUILTIN_ICONS)
return EntryIcons[i];
return CustomIcons[i-BUILTIN_ICONS];
}
void PwDatabase::addIcon(const QPixmap& icon){
CustomIcons << icon;
}
void PwDatabase::transformKey(Q_UINT8* src,Q_UINT8* dst,Q_UINT8* KeySeed,int rounds){
Q_UINT8* tmp=new Q_UINT8[32];
Rijndael rijndael;
@ -466,16 +553,11 @@ Entries.removeAt(Entries.indexOf(*entry));
}
bool PwDatabase::IsMetaStream(CEntry& p){
if(p.BinaryData.isNull()) return false;
if(p.Additional == "") return false;
if(p.BinaryDesc == "") return false;
if(p.BinaryDesc != "bin-stream") return false;
if(p.Title == "") return false;
if(p.Title != "Meta-Info") return false;
if(p.UserName == "") return false;
if(p.UserName != "SYSTEM") return false;
if(p.URL == "") return false;
if(p.URL != "$") return false;
if(p.ImageID != 0) return false;
return true;
@ -646,7 +728,14 @@ if(!file->isOpen()){
}
unsigned int FileSize;
Entries+=UnkownMetaStreams; ///@FIXME ID conflicts???
QList<CEntry*> MetaStreams;
for(int i=0; i<UnkownMetaStreams.size();i++){
MetaStreams << &UnkownMetaStreams[i];
}
CEntry CustomIconsMetaStream;
createCustomIconsMetaStream(&CustomIconsMetaStream);
MetaStreams << &CustomIconsMetaStream;
FileSize=DB_HEADER_SIZE;
// Get the size of all groups (94 Byte + length of the name string)
@ -655,14 +744,23 @@ for(int i = 0; i < Groups.size(); i++){
}
// Get the size of all entries
for(int i = 0; i < Entries.size(); i++){
FileSize += 134
+Entries[i].Title.utf8().length()+1
+Entries[i].UserName.utf8().length()+1
+Entries[i].URL.utf8().length()+1
+Entries[i].Password.length()+1
+Entries[i].Additional.utf8().length()+1
+Entries[i].BinaryDesc.utf8().length()+1
+Entries[i].BinaryData.length();}
FileSize += 134
+Entries[i].Title.utf8().length()+1
+Entries[i].UserName.utf8().length()+1
+Entries[i].URL.utf8().length()+1
+Entries[i].Password.length()+1
+Entries[i].Additional.utf8().length()+1
+Entries[i].BinaryDesc.utf8().length()+1
+Entries[i].BinaryData.length();
}
for(int i=0; i < MetaStreams.size(); i++){
FileSize +=164
+MetaStreams[i]->Additional.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);

@ -36,6 +36,7 @@
#include <QDate>
#include <QTime>
#include <QStringList>
#include <QPixmap>
#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);
QList<CGroup>Groups;
QList<CEntry>Entries;
@ -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<QPixmap> CustomIcons;
QList<CEntry> UnkownMetaStreams;
};

@ -133,10 +133,10 @@ if(event->spontaneous()==false){
}
void CEditEntryDlg::InitIconComboBox(){
for(int i=0;i<NUM_CLIENT_ICONS;i++){
Combo_IconPicker->insertItem(EntryIcons[i],"",i);
for(int i=0;i<db->numIcons();i++){
Combo_IconPicker->insertItem(db->icon(i),"",i);
}
Combo_IconPicker->setCurrentItem(entry->ImageID);
Combo_IconPicker->setCurrentItem(entry->ImageID);
}

@ -44,12 +44,13 @@ CEditGroupDialog::~CEditGroupDialog()
void CEditGroupDialog::showEvent(QShowEvent *event){
if(event->spontaneous()==false){
EditTitle->setText(GroupName);
for(int i=0;i<NUM_CLIENT_ICONS;i++){
ComboIconPicker->insertItem(EntryIcons[i],"",i);
EditTitle->setText(GroupName);
for(int i=0;i<db->numIcons();i++){
ComboIconPicker->insertItem(db->icon(i),"",i);
}
ComboIconPicker->setCurrentItem(IconID);
}
}
ComboIconPicker->setCurrentItem(IconID);
}}
void CEditGroupDialog::OnOK()
{

@ -18,13 +18,41 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <QStringList>
#include <QFileDialog>
#include <QDir>
#include <QFile>
#include <QPixmap>
#include <QMessageBox>
#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; i<NUM_CLIENT_ICONS; i++){
List->addItem(new QListWidgetItem(QIcon(EntryIcons[i]),QString::number(i)));
connect(Button_AddIcon, SIGNAL(clicked()), this, SLOT(OnAddIcon()));
for(int i=0; i<db->numIcons(); i++){
if(i<BUILTIN_ICONS)
List->addItem(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;i<filenames.size();i++){
QPixmap icon;
if(!icon.load(filenames[i])){
errors+=tr("%1: File could not be loaded.\n").arg(filenames[i].section("/",-1));
continue;}
db->addIcon(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"));
}

@ -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;

@ -72,7 +72,7 @@
<number>6</number>
</property>
<item>
<widget class="QPushButton" name="pushButton" >
<widget class="QPushButton" name="Button_AddIcon" >
<property name="text" >
<string>Add Custom Icon...</string>
</property>
@ -92,7 +92,7 @@
</spacer>
</item>
<item>
<widget class="QPushButton" name="Button_Ok" >
<widget class="QPushButton" name="Button_PickIcon" >
<property name="text" >
<string>Pick</string>
</property>
@ -112,7 +112,7 @@
<resources/>
<connections>
<connection>
<sender>Button_Ok</sender>
<sender>Button_PickIcon</sender>
<signal>clicked()</signal>
<receiver>SelectIconDlg</receiver>
<slot>accept()</slot>

@ -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;i<Items.size();i++){
tmp->setText(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));
}
}

@ -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<Items.size();i++){

@ -227,8 +227,8 @@ QPixmap tmpImg;
//-----------------------
loadImg("clientic.png",tmpImg);
EntryIcons=new QPixmap[NUM_CLIENT_ICONS];
for(int i=0;i<NUM_CLIENT_ICONS;i++){
EntryIcons=new QPixmap[BUILTIN_ICONS];
for(int i=0;i<BUILTIN_ICONS;i++){
EntryIcons[i]=tmpImg.copy(i*16,0,16,16);}
//--------------------------

@ -27,7 +27,7 @@
#include <QIcon>
#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
#endif