}
-Kdb3Database::Kdb3Database() : RawMasterKey(32), RawMasterKey_CP1252(32),
+Kdb3Database::Kdb3Database() : File(NULL), RawMasterKey(32), RawMasterKey_CP1252(32),
RawMasterKey_Latin1(32), RawMasterKey_UTF8(32), MasterKey(32){
}
for(int i=0;i<Groups.size();i++)EntryIndexCounter << 0;
for(int e=0;e<Entries.size();e++){
+ int groupIndex = -1;
for(int g=0;g<Groups.size();g++){
if(Entries[e].GroupId==Groups[g].Id){
- Groups[g].Entries.append(&Entries[e]);
- Entries[e].Group=&Groups[g];
- Entries[e].Index=EntryIndexCounter[g];
- EntryIndexCounter[g]++;
+ groupIndex = g;
+ break;
}
}
+
+ if (groupIndex == -1) {
+ qWarning("Orphaned entry found, assigning to first group");
+ for(int g=0;g<Groups.size();g++){
+ if(Groups[g].Id == RootGroup.Children[0]->Id){
+ groupIndex = g;
+ break;
+ }
+ }
+ }
+
+ Groups[groupIndex].Entries.append(&Entries[e]);
+ Entries[e].Group=&Groups[groupIndex];
+ Entries[e].Index=EntryIndexCounter[groupIndex];
+ EntryIndexCounter[groupIndex]++;
}
return true;
return false;
bool Kdb3Database::loadReal(QString filename, bool readOnly, bool differentEncoding) {
- unsigned long total_size,crypto_size;
- quint32 Signature1,Signature2,Version,NumGroups,NumEntries,Flags;
- quint8 FinalRandomSeed[16];
- quint8 ContentsHash[32];
- quint8 EncryptionIV[16];
-
File = new QFile(filename);
if (readOnly) {
if(!File->open(QIODevice::ReadOnly)){
}
}
+ openedReadOnly = readOnly;
+
+ unsigned long total_size,crypto_size;
+ quint32 Signature1,Signature2,Version,NumGroups,NumEntries,Flags;
+ quint8 FinalRandomSeed[16];
+ quint8 ContentsHash[32];
+ quint8 EncryptionIV[16];
+
total_size=File->size();
char* buffer = new char[total_size];
File->read(buffer,total_size);
if ((crypto_size > 2147483446) || (!crypto_size && NumGroups)){
error=tr("Decryption failed.\nThe key is wrong or the file is damaged.");
+ KeyError=true;
LOAD_RETURN_CLEANUP
}
SHA256::hashBuffer(buffer+DB_HEADER_SIZE,FinalKey,crypto_size);
Groups.back().Parent->Children.append(&Groups.back());
}
else{
+ // Insert to root group. Try to keep Backup group at the end.
Groups.back().Parent=&RootGroup;
Groups.back().Index=RootGroup.Children.size();
- if (group->Title!="Backup" && RootGroup.Children.size() && RootGroup.Children.last()->Title=="Backup"){
+ int position = RootGroup.Children.size();
+ if (group->Title!="Backup" && !RootGroup.Children.isEmpty() && RootGroup.Children.last()->Title=="Backup"){
RootGroup.Children.last()->Index = Groups.back().Index;
Groups.back().Index--;
+ position--;
}
- Groups.back().Parent->Children.append(&Groups.back());
+ RootGroup.Children.insert(position, &Groups.back());
}
return &GroupHandles.back();
}
return group;
}
+Kdb3Database::StdEntry::StdEntry(){
+ Handle = NULL;
+ Group = NULL;
+}
+
+Kdb3Database::StdGroup::StdGroup(){
+ Index=0;
+ Id=0;
+ Parent=NULL;
+ Handle=NULL;
+}
+
Kdb3Database::StdGroup::StdGroup(const CGroup& other){
Index=0;
Id=other.Id;
Image=other.Image;
Title=other.Title;
+ Parent=NULL;
+ Handle=NULL;
}
void Kdb3Database::EntryHandle::setTitle(const QString& Title){Entry->Title=Title; }
Kdb3Database::EntryHandle::EntryHandle(Kdb3Database* db){
pDB=db;
valid=true;
+ Entry=NULL;
}
return false;
}
+ if (!File->isOpen()) {
+ if(!File->open(QIODevice::ReadWrite)){
+ error=tr("Could not open file.");
+ return false;
+ }
+ }
+
+ if(!(File->openMode() & QIODevice::WriteOnly)){
+ error = tr("The database has been opened read-only.");
+ return false;
+ }
+
//Delete old backup entries
if (config->backup() && config->backupDelete() && config->backupDeleteAfter()>0 && backupGroup()){
QDateTime time = QDateTime::currentDateTime().addDays(-config->backupDeleteAfter());
quint8 ContentsHash[32];
quint8 EncryptionIV[16];
- if(!(File->openMode() & QIODevice::WriteOnly)){
- error = tr("The database has been opened read-only.");
- return false;
- }
-
unsigned int FileSize;
QList<StdEntry> MetaStreams;
int size = EncryptedPartSize+DB_HEADER_SIZE;
- if (!File->resize(size)){
- // only recreate file if the new database is smaller
- if (File->size() > size) {
- qDebug("Unable to resize, trying to recreate file");
- if (!File->remove() || !File->open(QIODevice::ReadWrite)) {
- delete [] buffer;
- error=decodeFileError(File->error());
- return false;
- }
- }
- }
- File->seek(0);
- if (File->write(buffer,size)!=size){
- delete [] buffer;
+ if (!saveFileTransactional(buffer, size)) {
error=decodeFileError(File->error());
+ delete [] buffer;
return false;
}
- if (!syncFile(File))
- qWarning("Unable to flush file to disk");
delete [] buffer;
//if(SearchGroupID!=-1)Groups.push_back(SearchGroup);
return true;
}
+bool Kdb3Database::saveFileTransactional(char* buffer, int size) {
+ QString orgFilename = File->fileName();
+ QFile* tmpFile = new QFile(orgFilename + ".tmp");
+ if (!tmpFile->open(QIODevice::WriteOnly|QIODevice::Truncate)) {
+ tmpFile->remove();
+ delete tmpFile;
+ return false;
+ }
+ if (tmpFile->write(buffer,size) != size) {
+ tmpFile->remove();
+ delete tmpFile;
+ return false;
+ }
+ if (!syncFile(tmpFile))
+ qWarning("Unable to flush file to disk");
+ tmpFile->close();
+ if (!File->remove()) {
+ delete tmpFile;
+ return false;
+ }
+ delete File;
+ File = NULL;
+ if (!tmpFile->rename(orgFilename)) {
+ delete tmpFile;
+ File = new QFile(orgFilename);
+ return false;
+ }
+ File = tmpFile;
+ if (!tmpFile->open(QIODevice::ReadWrite)) {
+ delete tmpFile;
+ return false;
+ }
+
+ return true;
+}
+
void Kdb3Database::createCustomIconsMetaStream(StdEntry* e){
/* Rev 3 */
e->BinaryDesc="bin-stream";