summaryrefslogtreecommitdiffabout
authorulf69 <ulf69>2004-10-16 01:05:12 (UTC)
committer ulf69 <ulf69>2004-10-16 01:05:12 (UTC)
commita6b0eba5c1aac3ba170b99c2b773fcabe10d8a40 (patch) (unidiff)
tree874b41d93e8cf796125038ea4fb5861788cfb2dd
parent6f229ba483beece68b9c408fb754864c8f0e3167 (diff)
downloadkdepimpi-a6b0eba5c1aac3ba170b99c2b773fcabe10d8a40.zip
kdepimpi-a6b0eba5c1aac3ba170b99c2b773fcabe10d8a40.tar.gz
kdepimpi-a6b0eba5c1aac3ba170b99c2b773fcabe10d8a40.tar.bz2
removed references to bzip2 compressformat
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--pwmanager/pwmanager/pwmdoc.cpp8
1 files changed, 5 insertions, 3 deletions
diff --git a/pwmanager/pwmanager/pwmdoc.cpp b/pwmanager/pwmanager/pwmdoc.cpp
index a5df8f0..0ac5517 100644
--- a/pwmanager/pwmanager/pwmdoc.cpp
+++ b/pwmanager/pwmanager/pwmdoc.cpp
@@ -1,2011 +1,2013 @@
1/*************************************************************************** 1/***************************************************************************
2 * * 2 * *
3 * copyright (C) 2003, 2004 by Michael Buesch * 3 * copyright (C) 2003, 2004 by Michael Buesch *
4 * email: mbuesch@freenet.de * 4 * email: mbuesch@freenet.de *
5 * * 5 * *
6 * This program is free software; you can redistribute it and/or modify * 6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License version 2 * 7 * it under the terms of the GNU General Public License version 2 *
8 * as published by the Free Software Foundation. * 8 * as published by the Free Software Foundation. *
9 * * 9 * *
10 ***************************************************************************/ 10 ***************************************************************************/
11 11
12/*************************************************************************** 12/***************************************************************************
13 * copyright (C) 2004 by Ulf Schenk 13 * copyright (C) 2004 by Ulf Schenk
14 * This file is originaly based on version 2.0 of pwmanager 14 * This file is originaly based on version 2.0 of pwmanager
15 * and was modified to run on embedded devices that run microkde 15 * and was modified to run on embedded devices that run microkde
16 * 16 *
17 * $Id$ 17 * $Id$
18 **************************************************************************/ 18 **************************************************************************/
19 19
20#include "pwmdoc.h" 20#include "pwmdoc.h"
21#include "pwmview.h" 21#include "pwmview.h"
22#include "blowfish.h" 22#include "blowfish.h"
23#include "sha1.h" 23#include "sha1.h"
24#include "globalstuff.h" 24#include "globalstuff.h"
25#include "gpasmanfile.h" 25#include "gpasmanfile.h"
26#include "serializer.h" 26#include "serializer.h"
27#include "compressgzip.h" 27#include "compressgzip.h"
28#include "compressbzip2.h" 28//US#include "compressbzip2.h"
29#include "randomizer.h" 29#include "randomizer.h"
30#include "pwminit.h" 30#include "pwminit.h"
31#include "libgcryptif.h" 31#include "libgcryptif.h"
32#ifdef PWM_EMBEDDED 32#ifdef PWM_EMBEDDED
33#include "pwmprefs.h" 33#include "pwmprefs.h"
34#include "kglobal.h" 34#include "kglobal.h"
35#endif 35#endif
36 36
37#include <kmessagebox.h> 37#include <kmessagebox.h>
38#include <libkcal/syncdefines.h> 38#include <libkcal/syncdefines.h>
39 39
40 40
41#ifdef CONFIG_KWALLETIF 41#ifdef CONFIG_KWALLETIF
42# include "kwalletemu.h" 42# include "kwalletemu.h"
43#endif // CONFIG_KWALLETIF 43#endif // CONFIG_KWALLETIF
44 44
45#include <qdatetime.h> 45#include <qdatetime.h>
46#include <qsize.h> 46#include <qsize.h>
47#include <qfileinfo.h> 47#include <qfileinfo.h>
48#include <qfile.h> 48#include <qfile.h>
49 49
50#include <stdio.h> 50#include <stdio.h>
51#include <stdlib.h> 51#include <stdlib.h>
52#include <errno.h> 52#include <errno.h>
53#include <string.h> 53#include <string.h>
54//US#include <iostream> 54//US#include <iostream>
55#include <algorithm> 55#include <algorithm>
56#include <sys/types.h> 56#include <sys/types.h>
57#include <sys/stat.h> 57#include <sys/stat.h>
58#include <unistd.h> 58#include <unistd.h>
59#include <stdint.h> 59#include <stdint.h>
60 60
61 61
62#ifdef PWM_EMBEDDED 62#ifdef PWM_EMBEDDED
63#ifndef Q_LONG 63#ifndef Q_LONG
64#define Q_LONG long 64#define Q_LONG long
65#endif 65#endif
66 66
67#ifndef Q_ULONG 67#ifndef Q_ULONG
68#define Q_ULONG unsigned long 68#define Q_ULONG unsigned long
69#endif 69#endif
70#endif //PWM_EMBEDDED 70#endif //PWM_EMBEDDED
71 71
72 72
73//TODO: reset to its normal value. 73//TODO: reset to its normal value.
74 #define META_CHECK_TIMER_INTERVAL10/*300*/ /* sek */ 74 #define META_CHECK_TIMER_INTERVAL10/*300*/ /* sek */
75 75
76using namespace std; 76using namespace std;
77 77
78 78
79void PwMDocList::add(PwMDoc *doc, const string &id) 79void PwMDocList::add(PwMDoc *doc, const string &id)
80{ 80{
81#ifdef PWM_DEBUG 81#ifdef PWM_DEBUG
82 // check for existance of object in debug mode only. 82 // check for existance of object in debug mode only.
83 vector<listItem>::iterator begin = docList.begin(), 83 vector<listItem>::iterator begin = docList.begin(),
84 end = docList.end(), 84 end = docList.end(),
85 i = begin; 85 i = begin;
86 while (i != end) { 86 while (i != end) {
87 if (i->doc == doc) { 87 if (i->doc == doc) {
88 BUG(); 88 BUG();
89 return; 89 return;
90 } 90 }
91 ++i; 91 ++i;
92 } 92 }
93#endif 93#endif
94 listItem newItem; 94 listItem newItem;
95 newItem.doc = doc; 95 newItem.doc = doc;
96 newItem.docId = id; 96 newItem.docId = id;
97 docList.push_back(newItem); 97 docList.push_back(newItem);
98} 98}
99 99
100void PwMDocList::edit(PwMDoc *doc, const string &newId) 100void PwMDocList::edit(PwMDoc *doc, const string &newId)
101{ 101{
102 vector<listItem>::iterator begin = docList.begin(), 102 vector<listItem>::iterator begin = docList.begin(),
103 end = docList.end(), 103 end = docList.end(),
104 i = begin; 104 i = begin;
105 while (i != end) { 105 while (i != end) {
106 if (i->doc == doc) { 106 if (i->doc == doc) {
107 i->docId = newId; 107 i->docId = newId;
108 return; 108 return;
109 } 109 }
110 ++i; 110 ++i;
111 } 111 }
112} 112}
113 113
114void PwMDocList::del(PwMDoc *doc) 114void PwMDocList::del(PwMDoc *doc)
115{ 115{
116 vector<listItem>::iterator begin = docList.begin(), 116 vector<listItem>::iterator begin = docList.begin(),
117 end = docList.end(), 117 end = docList.end(),
118 i = begin; 118 i = begin;
119 while (i != end) { 119 while (i != end) {
120 if (i->doc == doc) { 120 if (i->doc == doc) {
121 docList.erase(i); 121 docList.erase(i);
122 return; 122 return;
123 } 123 }
124 ++i; 124 ++i;
125 } 125 }
126} 126}
127 127
128bool PwMDocList::find(const string &id, listItem *ret) 128bool PwMDocList::find(const string &id, listItem *ret)
129{ 129{
130 vector<listItem>::iterator begin = docList.begin(), 130 vector<listItem>::iterator begin = docList.begin(),
131 end = docList.end(), 131 end = docList.end(),
132 i = begin; 132 i = begin;
133 while (i != end) { 133 while (i != end) {
134 if (i->docId == id) { 134 if (i->docId == id) {
135 if (ret) 135 if (ret)
136 *ret = *i; 136 *ret = *i;
137 return true; 137 return true;
138 } 138 }
139 ++i; 139 ++i;
140 } 140 }
141 return false; 141 return false;
142} 142}
143 143
144 144
145 145
146DocTimer::DocTimer(PwMDoc *_doc) 146DocTimer::DocTimer(PwMDoc *_doc)
147 : doc (_doc) 147 : doc (_doc)
148 , mpwLock (0) 148 , mpwLock (0)
149 , autoLockLock (0) 149 , autoLockLock (0)
150 , metaCheckLock (0) 150 , metaCheckLock (0)
151{ 151{
152 mpwTimer = new QTimer; 152 mpwTimer = new QTimer;
153 autoLockTimer = new QTimer; 153 autoLockTimer = new QTimer;
154 metaCheckTimer = new QTimer; 154 metaCheckTimer = new QTimer;
155 connect(mpwTimer, SIGNAL(timeout()), 155 connect(mpwTimer, SIGNAL(timeout()),
156 this, SLOT(mpwTimeout())); 156 this, SLOT(mpwTimeout()));
157 connect(autoLockTimer, SIGNAL(timeout()), 157 connect(autoLockTimer, SIGNAL(timeout()),
158 this, SLOT(autoLockTimeout())); 158 this, SLOT(autoLockTimeout()));
159 connect(metaCheckTimer, SIGNAL(timeout()), 159 connect(metaCheckTimer, SIGNAL(timeout()),
160 this, SLOT(metaCheckTimeout())); 160 this, SLOT(metaCheckTimeout()));
161} 161}
162 162
163DocTimer::~DocTimer() 163DocTimer::~DocTimer()
164{ 164{
165 delete mpwTimer; 165 delete mpwTimer;
166 delete autoLockTimer; 166 delete autoLockTimer;
167 delete metaCheckTimer; 167 delete metaCheckTimer;
168} 168}
169 169
170void DocTimer::start(TimerIDs timer) 170void DocTimer::start(TimerIDs timer)
171{ 171{
172 switch (timer) { 172 switch (timer) {
173 case id_mpwTimer: 173 case id_mpwTimer:
174 if (mpwTimer->isActive()) 174 if (mpwTimer->isActive())
175 mpwTimer->stop(); 175 mpwTimer->stop();
176 doc->setDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW); 176 doc->setDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW);
177 mpwTimer->start(conf()->confGlobPwTimeout() * 1000, true); 177 mpwTimer->start(conf()->confGlobPwTimeout() * 1000, true);
178 break; 178 break;
179 case id_autoLockTimer: 179 case id_autoLockTimer:
180 if (autoLockTimer->isActive()) 180 if (autoLockTimer->isActive())
181 autoLockTimer->stop(); 181 autoLockTimer->stop();
182 if (conf()->confGlobLockTimeout() > 0) 182 if (conf()->confGlobLockTimeout() > 0)
183 autoLockTimer->start(conf()->confGlobLockTimeout() * 1000, true); 183 autoLockTimer->start(conf()->confGlobLockTimeout() * 1000, true);
184 break; 184 break;
185 case id_metaCheckTimer: 185 case id_metaCheckTimer:
186 if (metaCheckTimer->isActive()) 186 if (metaCheckTimer->isActive())
187 metaCheckTimer->stop(); 187 metaCheckTimer->stop();
188 metaCheckTimer->start(META_CHECK_TIMER_INTERVAL * 1000, true); 188 metaCheckTimer->start(META_CHECK_TIMER_INTERVAL * 1000, true);
189 break; 189 break;
190 } 190 }
191} 191}
192 192
193void DocTimer::stop(TimerIDs timer) 193void DocTimer::stop(TimerIDs timer)
194{ 194{
195 switch (timer) { 195 switch (timer) {
196 case id_mpwTimer: 196 case id_mpwTimer:
197 mpwTimer->stop(); 197 mpwTimer->stop();
198 break; 198 break;
199 case id_autoLockTimer: 199 case id_autoLockTimer:
200 autoLockTimer->stop(); 200 autoLockTimer->stop();
201 break; 201 break;
202 case id_metaCheckTimer: 202 case id_metaCheckTimer:
203 metaCheckTimer->stop(); 203 metaCheckTimer->stop();
204 break; 204 break;
205 } 205 }
206} 206}
207 207
208void DocTimer::getLock(TimerIDs timer) 208void DocTimer::getLock(TimerIDs timer)
209{ 209{
210 switch (timer) { 210 switch (timer) {
211 case id_mpwTimer: 211 case id_mpwTimer:
212 ++mpwLock; 212 ++mpwLock;
213 break; 213 break;
214 case id_autoLockTimer: 214 case id_autoLockTimer:
215 ++autoLockLock; 215 ++autoLockLock;
216 break; 216 break;
217 case id_metaCheckTimer: 217 case id_metaCheckTimer:
218 ++metaCheckLock; 218 ++metaCheckLock;
219 break; 219 break;
220 } 220 }
221} 221}
222 222
223void DocTimer::putLock(TimerIDs timer) 223void DocTimer::putLock(TimerIDs timer)
224{ 224{
225 switch (timer) { 225 switch (timer) {
226 case id_mpwTimer: 226 case id_mpwTimer:
227 if (mpwLock) 227 if (mpwLock)
228 --mpwLock; 228 --mpwLock;
229 break; 229 break;
230 case id_autoLockTimer: 230 case id_autoLockTimer:
231 if (autoLockLock) 231 if (autoLockLock)
232 --autoLockLock; 232 --autoLockLock;
233 break; 233 break;
234 case id_metaCheckTimer: 234 case id_metaCheckTimer:
235 if (metaCheckLock) 235 if (metaCheckLock)
236 --metaCheckLock; 236 --metaCheckLock;
237 break; 237 break;
238 } 238 }
239} 239}
240 240
241void DocTimer::mpwTimeout() 241void DocTimer::mpwTimeout()
242{ 242{
243 if (mpwLock) { 243 if (mpwLock) {
244 mpwTimer->start(1000, true); 244 mpwTimer->start(1000, true);
245 return; 245 return;
246 } 246 }
247 doc->unsetDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW); 247 doc->unsetDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW);
248} 248}
249 249
250void DocTimer::autoLockTimeout() 250void DocTimer::autoLockTimeout()
251{ 251{
252 if (autoLockLock) { 252 if (autoLockLock) {
253 autoLockTimer->start(1000, true); 253 autoLockTimer->start(1000, true);
254 return; 254 return;
255 } 255 }
256 if (conf()->confGlobAutoDeepLock() && 256 if (conf()->confGlobAutoDeepLock() &&
257 doc->filename != QString::null && 257 doc->filename != QString::null &&
258 doc->filename != "") { 258 doc->filename != "") {
259 doc->deepLock(true); 259 doc->deepLock(true);
260 } else { 260 } else {
261 doc->lockAll(true); 261 doc->lockAll(true);
262 } 262 }
263} 263}
264 264
265void DocTimer::metaCheckTimeout() 265void DocTimer::metaCheckTimeout()
266{ 266{
267 if (metaCheckLock) { 267 if (metaCheckLock) {
268 // check again in one second. 268 // check again in one second.
269 metaCheckTimer->start(1000, true); 269 metaCheckTimer->start(1000, true);
270 return; 270 return;
271 } 271 }
272 if (doc->isDeepLocked()) { 272 if (doc->isDeepLocked()) {
273 metaCheckTimer->start(META_CHECK_TIMER_INTERVAL * 1000, true); 273 metaCheckTimer->start(META_CHECK_TIMER_INTERVAL * 1000, true);
274 return; 274 return;
275 } 275 }
276 if (doc->isDocEmpty()) { 276 if (doc->isDocEmpty()) {
277 metaCheckTimer->start(META_CHECK_TIMER_INTERVAL * 1000, true); 277 metaCheckTimer->start(META_CHECK_TIMER_INTERVAL * 1000, true);
278 return; 278 return;
279 } 279 }
280#ifdef CONFIG_KWALLETIF 280#ifdef CONFIG_KWALLETIF
281 KWalletEmu *kwlEmu = doc->init->kwalletEmu(); 281 KWalletEmu *kwlEmu = doc->init->kwalletEmu();
282 if (kwlEmu) 282 if (kwlEmu)
283 kwlEmu->suspendDocSignals(); 283 kwlEmu->suspendDocSignals();
284#endif // CONFIG_KWALLETIF 284#endif // CONFIG_KWALLETIF
285 /* We simply trigger all views to update their 285 /* We simply trigger all views to update their
286 * displayed values. This way they have a chance 286 * displayed values. This way they have a chance
287 * to get notified when some meta changes over time. 287 * to get notified when some meta changes over time.
288 * (for example an entry expired). 288 * (for example an entry expired).
289 * The _view_ is responsive for not updating its 289 * The _view_ is responsive for not updating its
290 * contents if nothing really changed! 290 * contents if nothing really changed!
291 */ 291 */
292 emit doc->dataChanged(doc); 292 emit doc->dataChanged(doc);
293#ifdef CONFIG_KWALLETIF 293#ifdef CONFIG_KWALLETIF
294 if (kwlEmu) 294 if (kwlEmu)
295 kwlEmu->resumeDocSignals(); 295 kwlEmu->resumeDocSignals();
296#endif // CONFIG_KWALLETIF 296#endif // CONFIG_KWALLETIF
297 metaCheckTimer->start(META_CHECK_TIMER_INTERVAL * 1000, true); 297 metaCheckTimer->start(META_CHECK_TIMER_INTERVAL * 1000, true);
298} 298}
299 299
300 300
301 301
302PwMDocList PwMDoc::openDocList; 302PwMDocList PwMDoc::openDocList;
303unsigned int PwMDocList::unnamedDocCnt = 1; 303unsigned int PwMDocList::unnamedDocCnt = 1;
304 304
305PwMDoc::PwMDoc(QObject *parent, const char *name) 305PwMDoc::PwMDoc(QObject *parent, const char *name)
306 : PwMDocUi(parent, name) 306 : PwMDocUi(parent, name)
307 , dataChangedLock (0) 307 , dataChangedLock (0)
308{ 308{
309 deleted = false; 309 deleted = false;
310 unnamedNum = 0; 310 unnamedNum = 0;
311 getOpenDocList()->add(this, getTitle().latin1()); 311 getOpenDocList()->add(this, getTitle().latin1());
312 curDocStat = 0; 312 curDocStat = 0;
313 setMaxNumEntries(); 313 setMaxNumEntries();
314 _timer = new DocTimer(this); 314 _timer = new DocTimer(this);
315 timer()->start(DocTimer::id_mpwTimer); 315 timer()->start(DocTimer::id_mpwTimer);
316 timer()->start(DocTimer::id_autoLockTimer); 316 timer()->start(DocTimer::id_autoLockTimer);
317 timer()->start(DocTimer::id_metaCheckTimer); 317 timer()->start(DocTimer::id_metaCheckTimer);
318 addCategory(DEFAULT_CATEGORY, 0, false); 318 addCategory(DEFAULT_CATEGORY, 0, false);
319 listView = 0; 319 listView = 0;
320 emit docCreated(this); 320 emit docCreated(this);
321} 321}
322 322
323PwMDoc::~PwMDoc() 323PwMDoc::~PwMDoc()
324{ 324{
325 emit docClosed(this); 325 emit docClosed(this);
326 getOpenDocList()->del(this); 326 getOpenDocList()->del(this);
327 delete _timer; 327 delete _timer;
328} 328}
329 329
330PwMerror PwMDoc::saveDoc(char compress, const QString *file) 330PwMerror PwMDoc::saveDoc(char compress, const QString *file)
331{ 331{
332 PwMerror ret, e; 332 PwMerror ret, e;
333 if (!file) { 333 if (!file) {
334 if (filename == "") 334 if (filename == "")
335 return e_filename; 335 return e_filename;
336 } else { 336 } else {
337 if (*file == "" && filename == "") 337 if (*file == "" && filename == "")
338 return e_filename; 338 return e_filename;
339 if (*file != "") 339 if (*file != "")
340 filename = *file; 340 filename = *file;
341 } 341 }
342 342
343 bool wasDeepLocked = isDeepLocked(); 343 bool wasDeepLocked = isDeepLocked();
344 if (wasDeepLocked) { 344 if (wasDeepLocked) {
345 if (deepLock(false) != e_success) 345 if (deepLock(false) != e_success)
346 return e_noPw; 346 return e_noPw;
347 } 347 }
348 348
349 if (!isPwAvailable()) { 349 if (!isPwAvailable()) {
350 /* password is not available. This means, the 350 /* password is not available. This means, the
351 * document wasn't saved, yet. 351 * document wasn't saved, yet.
352 */ 352 */
353 bool useChipcard = getDocStatFlag(DOC_STAT_USE_CHIPCARD); 353 bool useChipcard = getDocStatFlag(DOC_STAT_USE_CHIPCARD);
354 QString pw(requestNewMpw(&useChipcard)); 354 QString pw(requestNewMpw(&useChipcard));
355 if (pw != "") { 355 if (pw != "") {
356 currentPw = pw; 356 currentPw = pw;
357 } else { 357 } else {
358 return e_noPw; 358 return e_noPw;
359 } 359 }
360 if (useChipcard) { 360 if (useChipcard) {
361 setDocStatFlag(DOC_STAT_USE_CHIPCARD); 361 setDocStatFlag(DOC_STAT_USE_CHIPCARD);
362 } else { 362 } else {
363 unsetDocStatFlag(DOC_STAT_USE_CHIPCARD); 363 unsetDocStatFlag(DOC_STAT_USE_CHIPCARD);
364 } 364 }
365 } 365 }
366 366
367 int _cryptAlgo = conf()->confGlobCryptAlgo(); 367 int _cryptAlgo = conf()->confGlobCryptAlgo();
368 int _hashAlgo = conf()->confGlobHashAlgo(); 368 int _hashAlgo = conf()->confGlobHashAlgo();
369 369
370 // sanity check for the selected algorithms 370 // sanity check for the selected algorithms
371 if (_cryptAlgo < PWM_CRYPT_BLOWFISH || 371 if (_cryptAlgo < PWM_CRYPT_BLOWFISH ||
372 _cryptAlgo > PWM_CRYPT_TWOFISH128) { 372 _cryptAlgo > PWM_CRYPT_TWOFISH128) {
373 printWarn("Invalid Crypto-Algorithm selected! " 373 printWarn("Invalid Crypto-Algorithm selected! "
374 "Config-file seems to be corrupt. " 374 "Config-file seems to be corrupt. "
375 "Falling back to Blowfish."); 375 "Falling back to Blowfish.");
376 _cryptAlgo = PWM_CRYPT_BLOWFISH; 376 _cryptAlgo = PWM_CRYPT_BLOWFISH;
377 } 377 }
378 if (_hashAlgo < PWM_HASH_SHA1 || 378 if (_hashAlgo < PWM_HASH_SHA1 ||
379 _hashAlgo > PWM_HASH_TIGER) { 379 _hashAlgo > PWM_HASH_TIGER) {
380 printWarn("Invalid Hash-Algorithm selected! " 380 printWarn("Invalid Hash-Algorithm selected! "
381 "Config-file seems to be corrupt. " 381 "Config-file seems to be corrupt. "
382 "Falling back to SHA1."); 382 "Falling back to SHA1.");
383 _hashAlgo = PWM_HASH_SHA1; 383 _hashAlgo = PWM_HASH_SHA1;
384 } 384 }
385 char cryptAlgo = static_cast<char>(_cryptAlgo); 385 char cryptAlgo = static_cast<char>(_cryptAlgo);
386 char hashAlgo = static_cast<char>(_hashAlgo); 386 char hashAlgo = static_cast<char>(_hashAlgo);
387 387
388 if (conf()->confGlobMakeFileBackup()) { 388 if (conf()->confGlobMakeFileBackup()) {
389 if (!backupFile(filename)) 389 if (!backupFile(filename))
390 return e_fileBackup; 390 return e_fileBackup;
391 } 391 }
392 QString tmpFileMoved(QString::null); 392 QString tmpFileMoved(QString::null);
393 if (QFile::exists(filename)) { 393 if (QFile::exists(filename)) {
394 /* Move the existing file to some tmp file. 394 /* Move the existing file to some tmp file.
395 * When saving file succeeds, delete tmp file. Otherwise 395 * When saving file succeeds, delete tmp file. Otherwise
396 * move tmp file back. See below. 396 * move tmp file back. See below.
397 */ 397 */
398 Randomizer *rnd = Randomizer::obj(); 398 Randomizer *rnd = Randomizer::obj();
399 char rnd_buf[5]; 399 char rnd_buf[5];
400 sprintf(rnd_buf, "%X%X%X%X", rnd->genRndChar() & 0xFF, rnd->genRndChar() & 0xFF, 400 sprintf(rnd_buf, "%X%X%X%X", rnd->genRndChar() & 0xFF, rnd->genRndChar() & 0xFF,
401 rnd->genRndChar() & 0xFF, rnd->genRndChar() & 0xFF); 401 rnd->genRndChar() & 0xFF, rnd->genRndChar() & 0xFF);
402 tmpFileMoved = filename + "." + rnd_buf + ".mv"; 402 tmpFileMoved = filename + "." + rnd_buf + ".mv";
403 if (!copyFile(filename, tmpFileMoved)) 403 if (!copyFile(filename, tmpFileMoved))
404 return e_openFile; 404 return e_openFile;
405 if (!QFile::remove(filename)) { 405 if (!QFile::remove(filename)) {
406 printWarn(string("removing orig file ") 406 printWarn(string("removing orig file ")
407 + filename.latin1() 407 + filename.latin1()
408 + " failed!"); 408 + " failed!");
409 } 409 }
410 } 410 }
411 QFile f(filename); 411 QFile f(filename);
412 string serialized; 412 string serialized;
413 if (!f.open(IO_ReadWrite)) { 413 if (!f.open(IO_ReadWrite)) {
414 ret = e_openFile; 414 ret = e_openFile;
415 goto out_moveback; 415 goto out_moveback;
416 } 416 }
417 e = writeFileHeader(hashAlgo, hashAlgo, 417 e = writeFileHeader(hashAlgo, hashAlgo,
418 cryptAlgo, compress, 418 cryptAlgo, compress,
419 &currentPw, &f); 419 &currentPw, &f);
420 if (e == e_hashNotImpl) { 420 if (e == e_hashNotImpl) {
421 printDebug("PwMDoc::saveDoc(): writeFileHeader() failed: e_hashNotImpl"); 421 printDebug("PwMDoc::saveDoc(): writeFileHeader() failed: e_hashNotImpl");
422 f.close(); 422 f.close();
423 ret = e_hashNotImpl; 423 ret = e_hashNotImpl;
424 goto out_moveback; 424 goto out_moveback;
425 } else if (e != e_success) { 425 } else if (e != e_success) {
426 printDebug("PwMDoc::saveDoc(): writeFileHeader() failed"); 426 printDebug("PwMDoc::saveDoc(): writeFileHeader() failed");
427 f.close(); 427 f.close();
428 ret = e_writeHeader; 428 ret = e_writeHeader;
429 goto out_moveback; 429 goto out_moveback;
430 } 430 }
431 if (!serializeDta(&serialized)) { 431 if (!serializeDta(&serialized)) {
432 printDebug("PwMDoc::saveDoc(): serializeDta() failed"); 432 printDebug("PwMDoc::saveDoc(): serializeDta() failed");
433 f.close(); 433 f.close();
434 ret = e_serializeDta; 434 ret = e_serializeDta;
435 goto out_moveback; 435 goto out_moveback;
436 } 436 }
437 e = writeDataHash(hashAlgo, &serialized, &f); 437 e = writeDataHash(hashAlgo, &serialized, &f);
438 if (e == e_hashNotImpl) { 438 if (e == e_hashNotImpl) {
439 printDebug("PwMDoc::saveDoc(): writeDataHash() failed: e_hashNotImpl"); 439 printDebug("PwMDoc::saveDoc(): writeDataHash() failed: e_hashNotImpl");
440 f.close(); 440 f.close();
441 ret = e_hashNotImpl; 441 ret = e_hashNotImpl;
442 goto out_moveback; 442 goto out_moveback;
443 } else if (e != e_success) { 443 } else if (e != e_success) {
444 printDebug("PwMDoc::saveDoc(): writeDataHash() failed"); 444 printDebug("PwMDoc::saveDoc(): writeDataHash() failed");
445 f.close(); 445 f.close();
446 ret = e_writeHeader; 446 ret = e_writeHeader;
447 goto out_moveback; 447 goto out_moveback;
448 } 448 }
449 if (!compressDta(&serialized, compress)) { 449 if (!compressDta(&serialized, compress)) {
450 printDebug("PwMDoc::saveDoc(): compressDta() failed"); 450 printDebug("PwMDoc::saveDoc(): compressDta() failed");
451 f.close(); 451 f.close();
452 ret = e_enc; 452 ret = e_enc;
453 goto out_moveback; 453 goto out_moveback;
454 } 454 }
455 e = encrypt(&serialized, &currentPw, &f, cryptAlgo); 455 e = encrypt(&serialized, &currentPw, &f, cryptAlgo);
456 if (e == e_weakPw) { 456 if (e == e_weakPw) {
457 printDebug("PwMDoc::saveDoc(): encrypt() failed: e_weakPw"); 457 printDebug("PwMDoc::saveDoc(): encrypt() failed: e_weakPw");
458 f.close(); 458 f.close();
459 ret = e_weakPw; 459 ret = e_weakPw;
460 goto out_moveback; 460 goto out_moveback;
461 } else if (e == e_cryptNotImpl) { 461 } else if (e == e_cryptNotImpl) {
462 printDebug("PwMDoc::saveDoc(): encrypt() failed: e_cryptNotImpl"); 462 printDebug("PwMDoc::saveDoc(): encrypt() failed: e_cryptNotImpl");
463 f.close(); 463 f.close();
464 ret = e_cryptNotImpl; 464 ret = e_cryptNotImpl;
465 goto out_moveback; 465 goto out_moveback;
466 } else if (e != e_success) { 466 } else if (e != e_success) {
467 printDebug("PwMDoc::saveDoc(): encrypt() failed"); 467 printDebug("PwMDoc::saveDoc(): encrypt() failed");
468 f.close(); 468 f.close();
469 ret = e_enc; 469 ret = e_enc;
470 goto out_moveback; 470 goto out_moveback;
471 } 471 }
472 unsetDocStatFlag(DOC_STAT_DISK_DIRTY); 472 unsetDocStatFlag(DOC_STAT_DISK_DIRTY);
473 f.close(); 473 f.close();
474 if (chmod(filename.latin1(), 474 if (chmod(filename.latin1(),
475 conf()->confGlobFilePermissions())) { 475 conf()->confGlobFilePermissions())) {
476 printWarn(string("chmod failed: ") + strerror(errno)); 476 printWarn(string("chmod failed: ") + strerror(errno));
477 } 477 }
478 openDocList.edit(this, getTitle().latin1()); 478 openDocList.edit(this, getTitle().latin1());
479 if (wasDeepLocked) 479 if (wasDeepLocked)
480 deepLock(true); 480 deepLock(true);
481 if (tmpFileMoved != QString::null) { 481 if (tmpFileMoved != QString::null) {
482 // now remove the moved file. 482 // now remove the moved file.
483 if (!QFile::remove(tmpFileMoved)) { 483 if (!QFile::remove(tmpFileMoved)) {
484 printWarn(string("removing file ") 484 printWarn(string("removing file ")
485 + tmpFileMoved.latin1() 485 + tmpFileMoved.latin1()
486 + " failed!"); 486 + " failed!");
487 } 487 }
488 } 488 }
489 ret = e_success; 489 ret = e_success;
490 printDebug(string("writing file { compress: ") 490 printDebug(string("writing file { compress: ")
491 + tostr(static_cast<int>(compress)) + " cryptAlgo: " 491 + tostr(static_cast<int>(compress)) + " cryptAlgo: "
492 + tostr(static_cast<int>(cryptAlgo)) + " hashAlgo: " 492 + tostr(static_cast<int>(cryptAlgo)) + " hashAlgo: "
493 + tostr(static_cast<int>(hashAlgo)) 493 + tostr(static_cast<int>(hashAlgo))
494 + " }"); 494 + " }");
495 goto out; 495 goto out;
496out_moveback: 496out_moveback:
497 if (tmpFileMoved != QString::null) { 497 if (tmpFileMoved != QString::null) {
498 if (copyFile(tmpFileMoved, filename)) { 498 if (copyFile(tmpFileMoved, filename)) {
499 if (!QFile::remove(tmpFileMoved)) { 499 if (!QFile::remove(tmpFileMoved)) {
500 printWarn(string("removing tmp file ") 500 printWarn(string("removing tmp file ")
501 + filename.latin1() 501 + filename.latin1()
502 + " failed!"); 502 + " failed!");
503 } 503 }
504 } else { 504 } else {
505 printWarn(string("couldn't copy file ") 505 printWarn(string("couldn't copy file ")
506 + tmpFileMoved.latin1() 506 + tmpFileMoved.latin1()
507 + " back to " 507 + " back to "
508 + filename.latin1()); 508 + filename.latin1());
509 } 509 }
510 } 510 }
511out: 511out:
512 return ret; 512 return ret;
513} 513}
514 514
515PwMerror PwMDoc::openDoc(const QString *file, int openLocked) 515PwMerror PwMDoc::openDoc(const QString *file, int openLocked)
516{ 516{
517 PWM_ASSERT(file); 517 PWM_ASSERT(file);
518 PWM_ASSERT(openLocked == 0 || openLocked == 1 || openLocked == 2); 518 PWM_ASSERT(openLocked == 0 || openLocked == 1 || openLocked == 2);
519 string decrypted, dataHash; 519 string decrypted, dataHash;
520 PwMerror ret; 520 PwMerror ret;
521 char cryptAlgo, dataHashType, compress; 521 char cryptAlgo, dataHashType, compress;
522 unsigned int headerLen; 522 unsigned int headerLen;
523 523
524 if (*file == "") 524 if (*file == "")
525 return e_readFile; 525 return e_readFile;
526 filename = *file; 526 filename = *file;
527 /* check if this file is already open. 527 /* check if this file is already open.
528 * This does not catch symlinks! 528 * This does not catch symlinks!
529 */ 529 */
530 if (!isDeepLocked()) { 530 if (!isDeepLocked()) {
531 if (getOpenDocList()->find(filename.latin1())) 531 if (getOpenDocList()->find(filename.latin1()))
532 return e_alreadyOpen; 532 return e_alreadyOpen;
533 } 533 }
534 QFile f(filename); 534 QFile f(filename);
535 535
536 if (openLocked == 2) { 536 if (openLocked == 2) {
537 // open deep-locked 537 // open deep-locked
538 if (!QFile::exists(filename)) 538 if (!QFile::exists(filename))
539 return e_openFile; 539 return e_openFile;
540 if (deepLock(true, false) != e_success) 540 if (deepLock(true, false) != e_success)
541 return e_openFile; 541 return e_openFile;
542 goto out_success; 542 goto out_success;
543 } 543 }
544 544
545 if (!f.open(IO_ReadOnly)) 545 if (!f.open(IO_ReadOnly))
546 return e_openFile; 546 return e_openFile;
547 547
548 ret = checkHeader(&cryptAlgo, &currentPw, &compress, &headerLen, 548 ret = checkHeader(&cryptAlgo, &currentPw, &compress, &headerLen,
549 &dataHashType, &dataHash, &f); 549 &dataHashType, &dataHash, &f);
550 if (ret != e_success) { 550 if (ret != e_success) {
551 printDebug("PwMDoc::openDoc(): checkHeader() failed"); 551 printDebug("PwMDoc::openDoc(): checkHeader() failed");
552 f.close(); 552 f.close();
553 if (ret == e_wrongPw) { 553 if (ret == e_wrongPw) {
554 wrongMpwMsgBox(getDocStatFlag(DOC_STAT_USE_CHIPCARD)); 554 wrongMpwMsgBox(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
555 return ret; 555 return ret;
556 } else if (ret == e_noPw || 556 } else if (ret == e_noPw ||
557 ret == e_fileVer || 557 ret == e_fileVer ||
558 ret == e_fileFormat || 558 ret == e_fileFormat ||
559 ret == e_hashNotImpl) { 559 ret == e_hashNotImpl) {
560 return ret; 560 return ret;
561 } else 561 } else
562 return e_readFile; 562 return e_readFile;
563 } 563 }
564 ret = decrypt(&decrypted, headerLen, &currentPw, cryptAlgo, &f); 564 ret = decrypt(&decrypted, headerLen, &currentPw, cryptAlgo, &f);
565 if (ret == e_cryptNotImpl) { 565 if (ret == e_cryptNotImpl) {
566 printDebug("PwMDoc::openDoc(): decrypt() failed: e_cryptNotImpl"); 566 printDebug("PwMDoc::openDoc(): decrypt() failed: e_cryptNotImpl");
567 f.close(); 567 f.close();
568 return e_cryptNotImpl; 568 return e_cryptNotImpl;
569 } else if (ret != e_success) { 569 } else if (ret != e_success) {
570 printDebug("PwMDoc::openDoc(): decrypt() failed"); 570 printDebug("PwMDoc::openDoc(): decrypt() failed");
571 f.close(); 571 f.close();
572 return e_readFile; 572 return e_readFile;
573 } 573 }
574 if (!decompressDta(&decrypted, compress)) { 574 if (!decompressDta(&decrypted, compress)) {
575 printDebug("PwMDoc::openDoc(): decompressDta() failed"); 575 printDebug("PwMDoc::openDoc(): decompressDta() failed");
576 f.close(); 576 f.close();
577 return e_fileCorrupt; 577 return e_fileCorrupt;
578 } 578 }
579 ret = checkDataHash(dataHashType, &dataHash, &decrypted); 579 ret = checkDataHash(dataHashType, &dataHash, &decrypted);
580 if (ret == e_hashNotImpl) { 580 if (ret == e_hashNotImpl) {
581 printDebug("PwMDoc::openDoc(): checkDataHash() failed: e_hashNotImpl"); 581 printDebug("PwMDoc::openDoc(): checkDataHash() failed: e_hashNotImpl");
582 f.close(); 582 f.close();
583 return e_hashNotImpl; 583 return e_hashNotImpl;
584 } else if (ret != e_success) { 584 } else if (ret != e_success) {
585 printDebug("PwMDoc::openDoc(): checkDataHash() failed"); 585 printDebug("PwMDoc::openDoc(): checkDataHash() failed");
586 f.close(); 586 f.close();
587 return e_fileCorrupt; 587 return e_fileCorrupt;
588 } 588 }
589 if (!deSerializeDta(&decrypted, openLocked == 1)) { 589 if (!deSerializeDta(&decrypted, openLocked == 1)) {
590 printDebug("PwMDoc::openDoc(): deSerializeDta() failed"); 590 printDebug("PwMDoc::openDoc(): deSerializeDta() failed");
591 f.close(); 591 f.close();
592 return e_readFile; 592 return e_readFile;
593 } 593 }
594 f.close(); 594 f.close();
595 timer()->start(DocTimer::id_mpwTimer); 595 timer()->start(DocTimer::id_mpwTimer);
596 timer()->start(DocTimer::id_autoLockTimer); 596 timer()->start(DocTimer::id_autoLockTimer);
597out_success: 597out_success:
598 openDocList.edit(this, getTitle().latin1()); 598 openDocList.edit(this, getTitle().latin1());
599 emit docOpened(this); 599 emit docOpened(this);
600 return e_success; 600 return e_success;
601} 601}
602 602
603PwMerror PwMDoc::writeFileHeader(char keyHash, char dataHash, char crypt, char compress, 603PwMerror PwMDoc::writeFileHeader(char keyHash, char dataHash, char crypt, char compress,
604 QString *pw, QFile *f) 604 QString *pw, QFile *f)
605{ 605{
606 PWM_ASSERT(pw); 606 PWM_ASSERT(pw);
607 PWM_ASSERT(f); 607 PWM_ASSERT(f);
608 PWM_ASSERT(listView); 608 PWM_ASSERT(listView);
609 if (f->writeBlock(FILE_ID_HEADER, strlen(FILE_ID_HEADER)) != 609 if (f->writeBlock(FILE_ID_HEADER, strlen(FILE_ID_HEADER)) !=
610 static_cast<Q_LONG>(strlen(FILE_ID_HEADER))) { 610 static_cast<Q_LONG>(strlen(FILE_ID_HEADER))) {
611 return e_writeFile; 611 return e_writeFile;
612 } 612 }
613 if (f->putch(PWM_FILE_VER) == -1 || 613 if (f->putch(PWM_FILE_VER) == -1 ||
614 f->putch(keyHash) == -1 || 614 f->putch(keyHash) == -1 ||
615 f->putch(dataHash) == -1 || 615 f->putch(dataHash) == -1 ||
616 f->putch(crypt) == -1 || 616 f->putch(crypt) == -1 ||
617 f->putch(compress) == -1 || 617 f->putch(compress) == -1 ||
618 f->putch((getDocStatFlag(DOC_STAT_USE_CHIPCARD)) ? 618 f->putch((getDocStatFlag(DOC_STAT_USE_CHIPCARD)) ?
619 (static_cast<char>(0x01)) : (static_cast<char>(0x00))) == -1) { 619 (static_cast<char>(0x01)) : (static_cast<char>(0x00))) == -1) {
620 return e_writeFile; 620 return e_writeFile;
621 } 621 }
622 622
623 // write bytes of NUL-data. These bytes are reserved for future-use. 623 // write bytes of NUL-data. These bytes are reserved for future-use.
624 const int bufSize = 64; 624 const int bufSize = 64;
625 char tmp_buf[bufSize]; 625 char tmp_buf[bufSize];
626 memset(tmp_buf, 0x00, bufSize); 626 memset(tmp_buf, 0x00, bufSize);
627 if (f->writeBlock(tmp_buf, bufSize) != bufSize) 627 if (f->writeBlock(tmp_buf, bufSize) != bufSize)
628 return e_writeFile; 628 return e_writeFile;
629 629
630 switch (keyHash) { 630 switch (keyHash) {
631 case PWM_HASH_SHA1: { 631 case PWM_HASH_SHA1: {
632 const int hashlen = SHA1_HASH_LEN_BYTE; 632 const int hashlen = SHA1_HASH_LEN_BYTE;
633 Sha1 hash; 633 Sha1 hash;
634 hash.sha1_write(reinterpret_cast<const byte *>(pw->latin1()), pw->length()); 634 hash.sha1_write(reinterpret_cast<const byte *>(pw->latin1()), pw->length());
635 string ret = hash.sha1_read(); 635 string ret = hash.sha1_read();
636 if (f->writeBlock(ret.c_str(), hashlen) != hashlen) 636 if (f->writeBlock(ret.c_str(), hashlen) != hashlen)
637 return e_writeFile; 637 return e_writeFile;
638 break; 638 break;
639 } 639 }
640 case PWM_HASH_SHA256: 640 case PWM_HASH_SHA256:
641 /*... fall through */ 641 /*... fall through */
642 case PWM_HASH_SHA384: 642 case PWM_HASH_SHA384:
643 case PWM_HASH_SHA512: 643 case PWM_HASH_SHA512:
644 case PWM_HASH_MD5: 644 case PWM_HASH_MD5:
645 case PWM_HASH_RMD160: 645 case PWM_HASH_RMD160:
646 case PWM_HASH_TIGER: 646 case PWM_HASH_TIGER:
647 { 647 {
648 if (!LibGCryptIf::available()) 648 if (!LibGCryptIf::available())
649 return e_hashNotImpl; 649 return e_hashNotImpl;
650 LibGCryptIf gc; 650 LibGCryptIf gc;
651 PwMerror err; 651 PwMerror err;
652 unsigned char *buf; 652 unsigned char *buf;
653 size_t hashLen; 653 size_t hashLen;
654 err = gc.hash(&buf, 654 err = gc.hash(&buf,
655 &hashLen, 655 &hashLen,
656 reinterpret_cast<const unsigned char *>(pw->latin1()), 656 reinterpret_cast<const unsigned char *>(pw->latin1()),
657 pw->length(), 657 pw->length(),
658 keyHash); 658 keyHash);
659 if (err != e_success) 659 if (err != e_success)
660 return e_hashNotImpl; 660 return e_hashNotImpl;
661 if (f->writeBlock(reinterpret_cast<const char *>(buf), hashLen) 661 if (f->writeBlock(reinterpret_cast<const char *>(buf), hashLen)
662 != static_cast<Q_LONG>(hashLen)) { 662 != static_cast<Q_LONG>(hashLen)) {
663 delete [] buf; 663 delete [] buf;
664 return e_hashNotImpl; 664 return e_hashNotImpl;
665 } 665 }
666 delete [] buf; 666 delete [] buf;
667 break; 667 break;
668 } 668 }
669 default: { 669 default: {
670 return e_hashNotImpl; 670 return e_hashNotImpl;
671 } } 671 } }
672 return e_success; 672 return e_success;
673} 673}
674 674
675PwMerror PwMDoc::checkHeader(char *cryptAlgo, QString *pw, char *compress, 675PwMerror PwMDoc::checkHeader(char *cryptAlgo, QString *pw, char *compress,
676 unsigned int *headerLength, char *dataHashType, 676 unsigned int *headerLength, char *dataHashType,
677 string *dataHash, QFile *f) 677 string *dataHash, QFile *f)
678{ 678{
679 PWM_ASSERT(cryptAlgo); 679 PWM_ASSERT(cryptAlgo);
680 PWM_ASSERT(pw); 680 PWM_ASSERT(pw);
681 PWM_ASSERT(headerLength); 681 PWM_ASSERT(headerLength);
682 PWM_ASSERT(dataHashType); 682 PWM_ASSERT(dataHashType);
683 PWM_ASSERT(dataHash); 683 PWM_ASSERT(dataHash);
684 PWM_ASSERT(f); 684 PWM_ASSERT(f);
685 int tmpRet; 685 int tmpRet;
686 // check "magic" header 686 // check "magic" header
687 const char magicHdr[] = FILE_ID_HEADER; 687 const char magicHdr[] = FILE_ID_HEADER;
688 const int hdrLen = array_size(magicHdr) - 1; 688 const int hdrLen = array_size(magicHdr) - 1;
689 char tmp[hdrLen]; 689 char tmp[hdrLen];
690 if (f->readBlock(tmp, hdrLen) != hdrLen) 690 if (f->readBlock(tmp, hdrLen) != hdrLen)
691 return e_readFile; 691 return e_readFile;
692 if (memcmp(tmp, magicHdr, hdrLen) != 0) 692 if (memcmp(tmp, magicHdr, hdrLen) != 0)
693 return e_fileFormat; 693 return e_fileFormat;
694 // read and check file ver 694 // read and check file ver
695 int fileV = f->getch(); 695 int fileV = f->getch();
696 if (fileV == -1) 696 if (fileV == -1)
697 return e_fileFormat; 697 return e_fileFormat;
698 if (fileV != PWM_FILE_VER) 698 if (fileV != PWM_FILE_VER)
699 return e_fileVer; 699 return e_fileVer;
700 // read hash hash type 700 // read hash hash type
701 int keyHash = f->getch(); 701 int keyHash = f->getch();
702 if (keyHash == -1) 702 if (keyHash == -1)
703 return e_fileFormat; 703 return e_fileFormat;
704 // read data hash type 704 // read data hash type
705 tmpRet = f->getch(); 705 tmpRet = f->getch();
706 if (tmpRet == -1) 706 if (tmpRet == -1)
707 return e_fileFormat; 707 return e_fileFormat;
708 *dataHashType = tmpRet; 708 *dataHashType = tmpRet;
709 // read crypt algo 709 // read crypt algo
710 tmpRet = f->getch(); 710 tmpRet = f->getch();
711 if (tmpRet == -1) 711 if (tmpRet == -1)
712 return e_fileFormat; 712 return e_fileFormat;
713 *cryptAlgo = tmpRet; 713 *cryptAlgo = tmpRet;
714 // get compression-algo 714 // get compression-algo
715 tmpRet = f->getch(); 715 tmpRet = f->getch();
716 if (tmpRet == -1) 716 if (tmpRet == -1)
717 return e_fileFormat; 717 return e_fileFormat;
718 *compress = tmpRet; 718 *compress = tmpRet;
719 // get the MPW-flag 719 // get the MPW-flag
720 int mpw_flag = f->getch(); 720 int mpw_flag = f->getch();
721 if (mpw_flag == -1) 721 if (mpw_flag == -1)
722 return e_fileFormat; 722 return e_fileFormat;
723 if (mpw_flag == 0x01) 723 if (mpw_flag == 0x01)
724 setDocStatFlag(DOC_STAT_USE_CHIPCARD); 724 setDocStatFlag(DOC_STAT_USE_CHIPCARD);
725 else 725 else
726 unsetDocStatFlag(DOC_STAT_USE_CHIPCARD); 726 unsetDocStatFlag(DOC_STAT_USE_CHIPCARD);
727 // skip the "RESERVED"-bytes 727 // skip the "RESERVED"-bytes
728 if (!(f->at(f->at() + 64))) 728 if (!(f->at(f->at() + 64)))
729 return e_fileFormat; 729 return e_fileFormat;
730 730
731 *pw = requestMpw(getDocStatFlag(DOC_STAT_USE_CHIPCARD)); 731 *pw = requestMpw(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
732 if (*pw == "") { 732 if (*pw == "") {
733 /* the user didn't give a master-password 733 /* the user didn't give a master-password
734 * or didn't insert a chipcard 734 * or didn't insert a chipcard
735 */ 735 */
736 return e_noPw; 736 return e_noPw;
737 } 737 }
738 // verify key-hash 738 // verify key-hash
739 switch (keyHash) { 739 switch (keyHash) {
740 case PWM_HASH_SHA1: { 740 case PWM_HASH_SHA1: {
741 // read hash from header 741 // read hash from header
742 const int hashLen = SHA1_HASH_LEN_BYTE; 742 const int hashLen = SHA1_HASH_LEN_BYTE;
743 string readHash; 743 string readHash;
744 int i; 744 int i;
745 for (i = 0; i < hashLen; ++i) 745 for (i = 0; i < hashLen; ++i)
746 readHash.push_back(f->getch()); 746 readHash.push_back(f->getch());
747 Sha1 hash; 747 Sha1 hash;
748 hash.sha1_write(reinterpret_cast<const byte *>(pw->latin1()), pw->length()); 748 hash.sha1_write(reinterpret_cast<const byte *>(pw->latin1()), pw->length());
749 string ret = hash.sha1_read(); 749 string ret = hash.sha1_read();
750 if (ret != readHash) 750 if (ret != readHash)
751 return e_wrongPw;// hash doesn't match (wrong key) 751 return e_wrongPw;// hash doesn't match (wrong key)
752 break; 752 break;
753 } 753 }
754 case PWM_HASH_SHA256: 754 case PWM_HASH_SHA256:
755 /*... fall through */ 755 /*... fall through */
756 case PWM_HASH_SHA384: 756 case PWM_HASH_SHA384:
757 case PWM_HASH_SHA512: 757 case PWM_HASH_SHA512:
758 case PWM_HASH_MD5: 758 case PWM_HASH_MD5:
759 case PWM_HASH_RMD160: 759 case PWM_HASH_RMD160:
760 case PWM_HASH_TIGER: { 760 case PWM_HASH_TIGER: {
761 if (!LibGCryptIf::available()) 761 if (!LibGCryptIf::available())
762 return e_hashNotImpl; 762 return e_hashNotImpl;
763 LibGCryptIf gc; 763 LibGCryptIf gc;
764 PwMerror err; 764 PwMerror err;
765 unsigned char *buf; 765 unsigned char *buf;
766 size_t hashLen; 766 size_t hashLen;
767 err = gc.hash(&buf, 767 err = gc.hash(&buf,
768 &hashLen, 768 &hashLen,
769 reinterpret_cast<const unsigned char *>(pw->latin1()), 769 reinterpret_cast<const unsigned char *>(pw->latin1()),
770 pw->length(), 770 pw->length(),
771 keyHash); 771 keyHash);
772 if (err != e_success) 772 if (err != e_success)
773 return e_hashNotImpl; 773 return e_hashNotImpl;
774 string calcHash(reinterpret_cast<const char *>(buf), 774 string calcHash(reinterpret_cast<const char *>(buf),
775 static_cast<string::size_type>(hashLen)); 775 static_cast<string::size_type>(hashLen));
776 delete [] buf; 776 delete [] buf;
777 // read hash from header 777 // read hash from header
778 string readHash; 778 string readHash;
779 size_t i; 779 size_t i;
780 for (i = 0; i < hashLen; ++i) 780 for (i = 0; i < hashLen; ++i)
781 readHash.push_back(f->getch()); 781 readHash.push_back(f->getch());
782 if (calcHash != readHash) 782 if (calcHash != readHash)
783 return e_wrongPw;// hash doesn't match (wrong key) 783 return e_wrongPw;// hash doesn't match (wrong key)
784 break; 784 break;
785 } 785 }
786 default: { 786 default: {
787 return e_hashNotImpl; 787 return e_hashNotImpl;
788 } } 788 } }
789 // read the data-hash from the file 789 // read the data-hash from the file
790 unsigned int hashLen, i; 790 unsigned int hashLen, i;
791 switch (*dataHashType) { 791 switch (*dataHashType) {
792 case PWM_HASH_SHA1: 792 case PWM_HASH_SHA1:
793 hashLen = SHA1_HASH_LEN_BYTE; 793 hashLen = SHA1_HASH_LEN_BYTE;
794 break; 794 break;
795 case PWM_HASH_SHA256: 795 case PWM_HASH_SHA256:
796 /*... fall through */ 796 /*... fall through */
797 case PWM_HASH_SHA384: 797 case PWM_HASH_SHA384:
798 case PWM_HASH_SHA512: 798 case PWM_HASH_SHA512:
799 case PWM_HASH_MD5: 799 case PWM_HASH_MD5:
800 case PWM_HASH_RMD160: 800 case PWM_HASH_RMD160:
801 case PWM_HASH_TIGER: { 801 case PWM_HASH_TIGER: {
802 if (!LibGCryptIf::available()) 802 if (!LibGCryptIf::available())
803 return e_hashNotImpl; 803 return e_hashNotImpl;
804 LibGCryptIf gc; 804 LibGCryptIf gc;
805 hashLen = gc.hashLength(*dataHashType); 805 hashLen = gc.hashLength(*dataHashType);
806 if (hashLen == 0) 806 if (hashLen == 0)
807 return e_hashNotImpl; 807 return e_hashNotImpl;
808 break; 808 break;
809 } 809 }
810 default: 810 default:
811 return e_hashNotImpl; 811 return e_hashNotImpl;
812 } 812 }
813 *dataHash = ""; 813 *dataHash = "";
814 for (i = 0; i < hashLen; ++i) { 814 for (i = 0; i < hashLen; ++i) {
815 tmpRet = f->getch(); 815 tmpRet = f->getch();
816 if (tmpRet == -1) 816 if (tmpRet == -1)
817 return e_fileFormat; 817 return e_fileFormat;
818 dataHash->push_back(static_cast<char>(tmpRet)); 818 dataHash->push_back(static_cast<char>(tmpRet));
819 } 819 }
820 *headerLength = f->at(); 820 *headerLength = f->at();
821#ifndef PWM_EMBEDDED 821#ifndef PWM_EMBEDDED
822 printDebug(string("opening file { compress: ") 822 printDebug(string("opening file { compress: ")
823 + tostr(static_cast<int>(*compress)) + " cryptAlgo: " 823 + tostr(static_cast<int>(*compress)) + " cryptAlgo: "
824 + tostr(static_cast<int>(*cryptAlgo)) + " keyHashAlgo: " 824 + tostr(static_cast<int>(*cryptAlgo)) + " keyHashAlgo: "
825 + tostr(static_cast<int>(keyHash)) 825 + tostr(static_cast<int>(keyHash))
826 + " }"); 826 + " }");
827#else 827#else
828 printDebug(string("opening file { compress: ") 828 printDebug(string("opening file { compress: ")
829 + tostr((int)(*compress)) + " cryptAlgo: " 829 + tostr((int)(*compress)) + " cryptAlgo: "
830 + tostr((int)(*cryptAlgo)) + " keyHashAlgo: " 830 + tostr((int)(*cryptAlgo)) + " keyHashAlgo: "
831 + tostr((int)(keyHash)) 831 + tostr((int)(keyHash))
832 + " }"); 832 + " }");
833#endif 833#endif
834 834
835 return e_success; 835 return e_success;
836} 836}
837 837
838PwMerror PwMDoc::writeDataHash(char dataHash, string *d, QFile *f) 838PwMerror PwMDoc::writeDataHash(char dataHash, string *d, QFile *f)
839{ 839{
840 PWM_ASSERT(d); 840 PWM_ASSERT(d);
841 PWM_ASSERT(f); 841 PWM_ASSERT(f);
842 842
843 switch (dataHash) { 843 switch (dataHash) {
844 case PWM_HASH_SHA1: { 844 case PWM_HASH_SHA1: {
845 const int hashLen = SHA1_HASH_LEN_BYTE; 845 const int hashLen = SHA1_HASH_LEN_BYTE;
846 Sha1 h; 846 Sha1 h;
847 h.sha1_write(reinterpret_cast<const byte *>(d->c_str()), d->size()); 847 h.sha1_write(reinterpret_cast<const byte *>(d->c_str()), d->size());
848 string hRet = h.sha1_read(); 848 string hRet = h.sha1_read();
849 if (f->writeBlock(hRet.c_str(), hashLen) != hashLen) 849 if (f->writeBlock(hRet.c_str(), hashLen) != hashLen)
850 return e_writeFile; 850 return e_writeFile;
851 break; 851 break;
852 } 852 }
853 case PWM_HASH_SHA256: 853 case PWM_HASH_SHA256:
854 /*... fall through */ 854 /*... fall through */
855 case PWM_HASH_SHA384: 855 case PWM_HASH_SHA384:
856 case PWM_HASH_SHA512: 856 case PWM_HASH_SHA512:
857 case PWM_HASH_MD5: 857 case PWM_HASH_MD5:
858 case PWM_HASH_RMD160: 858 case PWM_HASH_RMD160:
859 case PWM_HASH_TIGER: { 859 case PWM_HASH_TIGER: {
860 if (!LibGCryptIf::available()) 860 if (!LibGCryptIf::available())
861 return e_hashNotImpl; 861 return e_hashNotImpl;
862 LibGCryptIf gc; 862 LibGCryptIf gc;
863 PwMerror err; 863 PwMerror err;
864 unsigned char *buf; 864 unsigned char *buf;
865 size_t hashLen; 865 size_t hashLen;
866 err = gc.hash(&buf, 866 err = gc.hash(&buf,
867 &hashLen, 867 &hashLen,
868 reinterpret_cast<const unsigned char *>(d->c_str()), 868 reinterpret_cast<const unsigned char *>(d->c_str()),
869 d->size(), 869 d->size(),
870 dataHash); 870 dataHash);
871 if (err != e_success) 871 if (err != e_success)
872 return e_hashNotImpl; 872 return e_hashNotImpl;
873 if (f->writeBlock(reinterpret_cast<const char *>(buf), hashLen) 873 if (f->writeBlock(reinterpret_cast<const char *>(buf), hashLen)
874 != static_cast<Q_LONG>(hashLen)) { 874 != static_cast<Q_LONG>(hashLen)) {
875 delete [] buf; 875 delete [] buf;
876 return e_hashNotImpl; 876 return e_hashNotImpl;
877 } 877 }
878 delete [] buf; 878 delete [] buf;
879 break; 879 break;
880 } 880 }
881 default: { 881 default: {
882 return e_hashNotImpl; 882 return e_hashNotImpl;
883 } } 883 } }
884 884
885 return e_success; 885 return e_success;
886} 886}
887 887
888bool PwMDoc::backupFile(const QString &filePath) 888bool PwMDoc::backupFile(const QString &filePath)
889{ 889{
890 QFileInfo fi(filePath); 890 QFileInfo fi(filePath);
891 if (!fi.exists()) 891 if (!fi.exists())
892 return true; // Yes, true is correct. 892 return true; // Yes, true is correct.
893 QString pathOnly(fi.dirPath(true)); 893 QString pathOnly(fi.dirPath(true));
894 QString nameOnly(fi.fileName()); 894 QString nameOnly(fi.fileName());
895 QString backupPath = pathOnly 895 QString backupPath = pathOnly
896 + "/~" 896 + "/~"
897 + nameOnly 897 + nameOnly
898 + ".backup"; 898 + ".backup";
899 return copyFile(filePath, backupPath); 899 return copyFile(filePath, backupPath);
900} 900}
901 901
902bool PwMDoc::copyFile(const QString &src, const QString &dst) 902bool PwMDoc::copyFile(const QString &src, const QString &dst)
903{ 903{
904 QFileInfo fi(src); 904 QFileInfo fi(src);
905 if (!fi.exists()) 905 if (!fi.exists())
906 return false; 906 return false;
907 if (QFile::exists(dst)) { 907 if (QFile::exists(dst)) {
908 if (!QFile::remove(dst)) 908 if (!QFile::remove(dst))
909 return false; 909 return false;
910 } 910 }
911 QFile srcFd(src); 911 QFile srcFd(src);
912 if (!srcFd.open(IO_ReadOnly)) 912 if (!srcFd.open(IO_ReadOnly))
913 return false; 913 return false;
914 QFile dstFd(dst); 914 QFile dstFd(dst);
915 if (!dstFd.open(IO_ReadWrite)) { 915 if (!dstFd.open(IO_ReadWrite)) {
916 srcFd.close(); 916 srcFd.close();
917 return false; 917 return false;
918 } 918 }
919 const int tmpBuf_size = 512; 919 const int tmpBuf_size = 512;
920 char tmpBuf[tmpBuf_size]; 920 char tmpBuf[tmpBuf_size];
921 Q_LONG bytesRead, bytesWritten; 921 Q_LONG bytesRead, bytesWritten;
922 922
923 while (!srcFd.atEnd()) { 923 while (!srcFd.atEnd()) {
924 bytesRead = srcFd.readBlock(tmpBuf, 924 bytesRead = srcFd.readBlock(tmpBuf,
925 static_cast<Q_ULONG>(tmpBuf_size)); 925 static_cast<Q_ULONG>(tmpBuf_size));
926 if (bytesRead == -1) { 926 if (bytesRead == -1) {
927 srcFd.close(); 927 srcFd.close();
928 dstFd.close(); 928 dstFd.close();
929 return false; 929 return false;
930 } 930 }
931 bytesWritten = dstFd.writeBlock(tmpBuf, 931 bytesWritten = dstFd.writeBlock(tmpBuf,
932 static_cast<Q_ULONG>(bytesRead)); 932 static_cast<Q_ULONG>(bytesRead));
933 if (bytesWritten != bytesRead) { 933 if (bytesWritten != bytesRead) {
934 srcFd.close(); 934 srcFd.close();
935 dstFd.close(); 935 dstFd.close();
936 return false; 936 return false;
937 } 937 }
938 } 938 }
939 srcFd.close(); 939 srcFd.close();
940 dstFd.close(); 940 dstFd.close();
941 return true; 941 return true;
942} 942}
943 943
944PwMerror PwMDoc::addEntry(const QString &category, PwMDataItem *d, 944PwMerror PwMDoc::addEntry(const QString &category, PwMDataItem *d,
945 bool dontFlagDirty, bool updateMeta) 945 bool dontFlagDirty, bool updateMeta)
946{ 946{
947 PWM_ASSERT(d); 947 PWM_ASSERT(d);
948 unsigned int cat = 0; 948 unsigned int cat = 0;
949 949
950 if (isDeepLocked()) { 950 if (isDeepLocked()) {
951 PwMerror ret; 951 PwMerror ret;
952 ret = deepLock(false); 952 ret = deepLock(false);
953 if (ret != e_success) 953 if (ret != e_success)
954 return e_lock; 954 return e_lock;
955 } 955 }
956 956
957 addCategory(category, &cat); 957 addCategory(category, &cat);
958 958
959 if (numEntries(category) >= maxEntries) 959 if (numEntries(category) >= maxEntries)
960 return e_maxAllowedEntr; 960 return e_maxAllowedEntr;
961 961
962 vector<unsigned int> foundPositions; 962 vector<unsigned int> foundPositions;
963 /* historically this was: 963 /* historically this was:
964 *const int searchIn = SEARCH_IN_DESC | SEARCH_IN_NAME | 964 *const int searchIn = SEARCH_IN_DESC | SEARCH_IN_NAME |
965 * SEARCH_IN_URL | SEARCH_IN_LAUNCHER; 965 * SEARCH_IN_URL | SEARCH_IN_LAUNCHER;
966 * But for now we only search in desc. 966 * But for now we only search in desc.
967 * That's a tweak to be KWallet compatible. But it should not add 967 * That's a tweak to be KWallet compatible. But it should not add
968 * usability-drop onto PwManager, does it? 968 * usability-drop onto PwManager, does it?
969 * (And yes, "int" was a bug. Correct is "unsigned int") 969 * (And yes, "int" was a bug. Correct is "unsigned int")
970 */ 970 */
971 const unsigned int searchIn = SEARCH_IN_DESC; 971 const unsigned int searchIn = SEARCH_IN_DESC;
972 findEntry(cat, *d, searchIn, &foundPositions, true); 972 findEntry(cat, *d, searchIn, &foundPositions, true);
973 if (foundPositions.size()) { 973 if (foundPositions.size()) {
974 // DOH! We found this entry. 974 // DOH! We found this entry.
975 return e_entryExists; 975 return e_entryExists;
976 } 976 }
977 977
978 d->listViewPos = -1; 978 d->listViewPos = -1;
979 d->lockStat = conf()->confGlobNewEntrLockStat(); 979 d->lockStat = conf()->confGlobNewEntrLockStat();
980 if (updateMeta) { 980 if (updateMeta) {
981 d->meta.create = QDateTime::currentDateTime(); 981 d->meta.create = QDateTime::currentDateTime();
982 d->meta.update = d->meta.create; 982 d->meta.update = d->meta.create;
983 } 983 }
984 dti.dta[cat].d.push_back(*d); 984 dti.dta[cat].d.push_back(*d);
985 985
986 delAllEmptyCat(true); 986 delAllEmptyCat(true);
987 987
988 if (!dontFlagDirty) 988 if (!dontFlagDirty)
989 flagDirty(); 989 flagDirty();
990 return e_success; 990 return e_success;
991} 991}
992 992
993PwMerror PwMDoc::addCategory(const QString &category, unsigned int *categoryIndex, 993PwMerror PwMDoc::addCategory(const QString &category, unsigned int *categoryIndex,
994 bool checkIfExist) 994 bool checkIfExist)
995{ 995{
996 if (isDeepLocked()) { 996 if (isDeepLocked()) {
997 PwMerror ret; 997 PwMerror ret;
998 ret = deepLock(false); 998 ret = deepLock(false);
999 if (ret != e_success) 999 if (ret != e_success)
1000 return e_lock; 1000 return e_lock;
1001 } 1001 }
1002 if (checkIfExist) { 1002 if (checkIfExist) {
1003 if (findCategory(category, categoryIndex)) 1003 if (findCategory(category, categoryIndex))
1004 return e_categoryExists; 1004 return e_categoryExists;
1005 } 1005 }
1006 PwMCategoryItem item; 1006 PwMCategoryItem item;
1007 item.name = category.latin1(); 1007 item.name = category.latin1();
1008 dti.dta.push_back(item); 1008 dti.dta.push_back(item);
1009 if (categoryIndex) 1009 if (categoryIndex)
1010 *categoryIndex = dti.dta.size() - 1; 1010 *categoryIndex = dti.dta.size() - 1;
1011 return e_success; 1011 return e_success;
1012} 1012}
1013 1013
1014bool PwMDoc::delEntry(const QString &category, unsigned int index, bool dontFlagDirty) 1014bool PwMDoc::delEntry(const QString &category, unsigned int index, bool dontFlagDirty)
1015{ 1015{
1016 unsigned int cat = 0; 1016 unsigned int cat = 0;
1017 1017
1018 if (!findCategory(category, &cat)) { 1018 if (!findCategory(category, &cat)) {
1019 BUG(); 1019 BUG();
1020 return false; 1020 return false;
1021 } 1021 }
1022 1022
1023 return delEntry(cat, index, dontFlagDirty); 1023 return delEntry(cat, index, dontFlagDirty);
1024} 1024}
1025 1025
1026bool PwMDoc::delEntry(unsigned int category, unsigned int index, bool dontFlagDirty) 1026bool PwMDoc::delEntry(unsigned int category, unsigned int index, bool dontFlagDirty)
1027{ 1027{
1028 if (isDeepLocked()) 1028 if (isDeepLocked())
1029 return false; 1029 return false;
1030 if (index > dti.dta[category].d.size() - 1) 1030 if (index > dti.dta[category].d.size() - 1)
1031 return false; 1031 return false;
1032 getDataChangedLock(); 1032 getDataChangedLock();
1033 if (!lockAt(category, index, false)) { 1033 if (!lockAt(category, index, false)) {
1034 putDataChangedLock(); 1034 putDataChangedLock();
1035 return false; 1035 return false;
1036 } 1036 }
1037 putDataChangedLock(); 1037 putDataChangedLock();
1038 int lvPos = dti.dta[category].d[index].listViewPos; 1038 int lvPos = dti.dta[category].d[index].listViewPos;
1039 1039
1040 // delete entry 1040 // delete entry
1041 dti.dta[category].d.erase(dti.dta[category].d.begin() + index); 1041 dti.dta[category].d.erase(dti.dta[category].d.begin() + index);
1042 1042
1043 unsigned int i, entries = numEntries(category); 1043 unsigned int i, entries = numEntries(category);
1044 if (!entries) { 1044 if (!entries) {
1045 // no more entries in this category, so 1045 // no more entries in this category, so
1046 // we can delete it, too. 1046 // we can delete it, too.
1047 BUG_ON(!delCategory(category)); 1047 BUG_ON(!delCategory(category));
1048 // delCategory() flags it dirty, so we need not to do so. 1048 // delCategory() flags it dirty, so we need not to do so.
1049 return true; 1049 return true;
1050 } 1050 }
1051 for (i = 0; i < entries; ++i) { 1051 for (i = 0; i < entries; ++i) {
1052 // decrement all listViewPositions that are greater than the deleted. 1052 // decrement all listViewPositions that are greater than the deleted.
1053 if (dti.dta[category].d[i].listViewPos > lvPos) 1053 if (dti.dta[category].d[i].listViewPos > lvPos)
1054 --dti.dta[category].d[i].listViewPos; 1054 --dti.dta[category].d[i].listViewPos;
1055 } 1055 }
1056 1056
1057 if (!dontFlagDirty) 1057 if (!dontFlagDirty)
1058 flagDirty(); 1058 flagDirty();
1059 return true; 1059 return true;
1060} 1060}
1061 1061
1062bool PwMDoc::editEntry(const QString &oldCategory, const QString &newCategory, 1062bool PwMDoc::editEntry(const QString &oldCategory, const QString &newCategory,
1063 unsigned int index, PwMDataItem *d, bool updateMeta) 1063 unsigned int index, PwMDataItem *d, bool updateMeta)
1064{ 1064{
1065 PWM_ASSERT(d); 1065 PWM_ASSERT(d);
1066 unsigned int oldCat = 0; 1066 unsigned int oldCat = 0;
1067 1067
1068 if (!findCategory(oldCategory, &oldCat)) { 1068 if (!findCategory(oldCategory, &oldCat)) {
1069 BUG(); 1069 BUG();
1070 return false; 1070 return false;
1071 } 1071 }
1072 1072
1073 return editEntry(oldCat, newCategory, index, d, updateMeta); 1073 return editEntry(oldCat, newCategory, index, d, updateMeta);
1074} 1074}
1075 1075
1076bool PwMDoc::editEntry(unsigned int oldCategory, const QString &newCategory, 1076bool PwMDoc::editEntry(unsigned int oldCategory, const QString &newCategory,
1077 unsigned int index, PwMDataItem *d, bool updateMeta) 1077 unsigned int index, PwMDataItem *d, bool updateMeta)
1078{ 1078{
1079 if (isDeepLocked()) 1079 if (isDeepLocked())
1080 return false; 1080 return false;
1081 if (updateMeta) { 1081 if (updateMeta) {
1082 d->meta.update = QDateTime::currentDateTime(); 1082 d->meta.update = QDateTime::currentDateTime();
1083 if (d->meta.create.isNull()) { 1083 if (d->meta.create.isNull()) {
1084 d->meta.create = d->meta.update; 1084 d->meta.create = d->meta.update;
1085 } 1085 }
1086 } 1086 }
1087 if (dti.dta[oldCategory].name != newCategory.latin1()) { 1087 if (dti.dta[oldCategory].name != newCategory.latin1()) {
1088 // the user changed the category. 1088 // the user changed the category.
1089 PwMerror ret; 1089 PwMerror ret;
1090 d->rev = 0; 1090 d->rev = 0;
1091 ret = addEntry(newCategory, d, true, false); 1091 ret = addEntry(newCategory, d, true, false);
1092 if (ret != e_success) 1092 if (ret != e_success)
1093 return false; 1093 return false;
1094 if (!delEntry(oldCategory, index, true)) 1094 if (!delEntry(oldCategory, index, true))
1095 return false; 1095 return false;
1096 } else { 1096 } else {
1097 d->rev = dti.dta[oldCategory].d[index].rev + 1; // increment revision counter. 1097 d->rev = dti.dta[oldCategory].d[index].rev + 1; // increment revision counter.
1098 dti.dta[oldCategory].d[index] = *d; 1098 dti.dta[oldCategory].d[index] = *d;
1099 } 1099 }
1100 flagDirty(); 1100 flagDirty();
1101 return true; 1101 return true;
1102} 1102}
1103 1103
1104unsigned int PwMDoc::numEntries(const QString &category) 1104unsigned int PwMDoc::numEntries(const QString &category)
1105{ 1105{
1106 unsigned int cat = 0; 1106 unsigned int cat = 0;
1107 1107
1108 if (!findCategory(category, &cat)) { 1108 if (!findCategory(category, &cat)) {
1109 BUG(); 1109 BUG();
1110 return 0; 1110 return 0;
1111 } 1111 }
1112 1112
1113 return numEntries(cat); 1113 return numEntries(cat);
1114} 1114}
1115 1115
1116bool PwMDoc::serializeDta(string *d) 1116bool PwMDoc::serializeDta(string *d)
1117{ 1117{
1118 PWM_ASSERT(d); 1118 PWM_ASSERT(d);
1119 Serializer ser; 1119 Serializer ser;
1120 if (!ser.serialize(dti)) 1120 if (!ser.serialize(dti))
1121 return false; 1121 return false;
1122 d->assign(ser.getXml()); 1122 d->assign(ser.getXml());
1123 if (!d->size()) 1123 if (!d->size())
1124 return false; 1124 return false;
1125 return true; 1125 return true;
1126} 1126}
1127 1127
1128bool PwMDoc::deSerializeDta(const string *d, bool entriesLocked) 1128bool PwMDoc::deSerializeDta(const string *d, bool entriesLocked)
1129{ 1129{
1130 PWM_ASSERT(d); 1130 PWM_ASSERT(d);
1131#ifndef PWM_EMBEDDED 1131#ifndef PWM_EMBEDDED
1132 try { 1132 try {
1133 1133
1134 Serializer ser(d->c_str()); 1134 Serializer ser(d->c_str());
1135 ser.setDefaultLockStat(entriesLocked); 1135 ser.setDefaultLockStat(entriesLocked);
1136 if (!ser.deSerialize(&dti)) 1136 if (!ser.deSerialize(&dti))
1137 return false; 1137 return false;
1138 } catch (PwMException) { 1138 } catch (PwMException) {
1139 return false; 1139 return false;
1140 } 1140 }
1141#else 1141#else
1142 Serializer ser(d->c_str()); 1142 Serializer ser(d->c_str());
1143 ser.setDefaultLockStat(entriesLocked); 1143 ser.setDefaultLockStat(entriesLocked);
1144 if (!ser.deSerialize(&dti)) 1144 if (!ser.deSerialize(&dti))
1145 return false; 1145 return false;
1146#endif 1146#endif
1147 1147
1148 emitDataChanged(this); 1148 emitDataChanged(this);
1149 return true; 1149 return true;
1150} 1150}
1151 1151
1152bool PwMDoc::getEntry(const QString &category, unsigned int index, 1152bool PwMDoc::getEntry(const QString &category, unsigned int index,
1153 PwMDataItem * d, bool unlockIfLocked) 1153 PwMDataItem * d, bool unlockIfLocked)
1154{ 1154{
1155 PWM_ASSERT(d); 1155 PWM_ASSERT(d);
1156 unsigned int cat = 0; 1156 unsigned int cat = 0;
1157 1157
1158 if (!findCategory(category, &cat)) { 1158 if (!findCategory(category, &cat)) {
1159 BUG(); 1159 BUG();
1160 return false; 1160 return false;
1161 } 1161 }
1162 1162
1163 return getEntry(cat, index, d, unlockIfLocked); 1163 return getEntry(cat, index, d, unlockIfLocked);
1164} 1164}
1165 1165
1166bool PwMDoc::getEntry(unsigned int category, unsigned int index, 1166bool PwMDoc::getEntry(unsigned int category, unsigned int index,
1167 PwMDataItem *d, bool unlockIfLocked) 1167 PwMDataItem *d, bool unlockIfLocked)
1168{ 1168{
1169 if (index > dti.dta[category].d.size() - 1) 1169 if (index > dti.dta[category].d.size() - 1)
1170 return false; 1170 return false;
1171 1171
1172 bool locked = isLocked(category, index); 1172 bool locked = isLocked(category, index);
1173 if (locked) { 1173 if (locked) {
1174 /* this entry is locked. We don't return a password, 1174 /* this entry is locked. We don't return a password,
1175 * until it's unlocked by the user by inserting 1175 * until it's unlocked by the user by inserting
1176 * chipcard or entering the mpw 1176 * chipcard or entering the mpw
1177 */ 1177 */
1178 if (unlockIfLocked) { 1178 if (unlockIfLocked) {
1179 if (!lockAt(category, index, false)) { 1179 if (!lockAt(category, index, false)) {
1180 return false; 1180 return false;
1181 } 1181 }
1182 locked = false; 1182 locked = false;
1183 } 1183 }
1184 } 1184 }
1185 1185
1186 *d = dti.dta[category].d[index]; 1186 *d = dti.dta[category].d[index];
1187 if (locked) 1187 if (locked)
1188 d->pw = LOCKED_STRING.latin1(); 1188 d->pw = LOCKED_STRING.latin1();
1189 1189
1190 return true; 1190 return true;
1191} 1191}
1192 1192
1193PwMerror PwMDoc::getCommentByLvp(const QString &category, int listViewPos, 1193PwMerror PwMDoc::getCommentByLvp(const QString &category, int listViewPos,
1194 string *foundComment) 1194 string *foundComment)
1195{ 1195{
1196 PWM_ASSERT(foundComment); 1196 PWM_ASSERT(foundComment);
1197 unsigned int cat = 0; 1197 unsigned int cat = 0;
1198 1198
1199 if (!findCategory(category, &cat)) 1199 if (!findCategory(category, &cat))
1200 return e_invalidArg; 1200 return e_invalidArg;
1201 1201
1202 unsigned int i, entries = numEntries(cat); 1202 unsigned int i, entries = numEntries(cat);
1203 for (i = 0; i < entries; ++i) { 1203 for (i = 0; i < entries; ++i) {
1204 if (dti.dta[cat].d[i].listViewPos == listViewPos) { 1204 if (dti.dta[cat].d[i].listViewPos == listViewPos) {
1205 *foundComment = dti.dta[cat].d[i].comment; 1205 *foundComment = dti.dta[cat].d[i].comment;
1206 if (dti.dta[cat].d[i].binary) 1206 if (dti.dta[cat].d[i].binary)
1207 return e_binEntry; 1207 return e_binEntry;
1208 return e_normalEntry; 1208 return e_normalEntry;
1209 } 1209 }
1210 } 1210 }
1211 BUG(); 1211 BUG();
1212 return e_generic; 1212 return e_generic;
1213} 1213}
1214 1214
1215bool PwMDoc::compressDta(string *d, char algo) 1215bool PwMDoc::compressDta(string *d, char algo)
1216{ 1216{
1217 PWM_ASSERT(d); 1217 PWM_ASSERT(d);
1218 switch (algo) { 1218 switch (algo) {
1219 case PWM_COMPRESS_GZIP: { 1219 case PWM_COMPRESS_GZIP: {
1220 CompressGzip comp; 1220 CompressGzip comp;
1221 return comp.compress(d); 1221 return comp.compress(d);
1222 } case PWM_COMPRESS_BZIP2: { 1222 /*US } case PWM_COMPRESS_BZIP2: {
1223 CompressBzip2 comp; 1223 CompressBzip2 comp;
1224 return comp.compress(d); 1224 return comp.compress(d);
1225*/
1225 } case PWM_COMPRESS_NONE: { 1226 } case PWM_COMPRESS_NONE: {
1226 return true; 1227 return true;
1227 } default: { 1228 } default: {
1228 BUG(); 1229 BUG();
1229 } 1230 }
1230 } 1231 }
1231 return false; 1232 return false;
1232} 1233}
1233 1234
1234bool PwMDoc::decompressDta(string *d, char algo) 1235bool PwMDoc::decompressDta(string *d, char algo)
1235{ 1236{
1236 PWM_ASSERT(d); 1237 PWM_ASSERT(d);
1237 switch (algo) { 1238 switch (algo) {
1238 case PWM_COMPRESS_GZIP: { 1239 case PWM_COMPRESS_GZIP: {
1239 CompressGzip comp; 1240 CompressGzip comp;
1240 return comp.decompress(d); 1241 return comp.decompress(d);
1241 } case PWM_COMPRESS_BZIP2: { 1242 /*US } case PWM_COMPRESS_BZIP2: {
1242 CompressBzip2 comp; 1243 CompressBzip2 comp;
1243 return comp.decompress(d); 1244 return comp.decompress(d);
1245 */
1244 } case PWM_COMPRESS_NONE: { 1246 } case PWM_COMPRESS_NONE: {
1245 return true; 1247 return true;
1246 } 1248 }
1247 } 1249 }
1248 return false; 1250 return false;
1249} 1251}
1250 1252
1251PwMerror PwMDoc::encrypt(string *d, const QString *pw, QFile *f, char algo) 1253PwMerror PwMDoc::encrypt(string *d, const QString *pw, QFile *f, char algo)
1252{ 1254{
1253 PWM_ASSERT(d); 1255 PWM_ASSERT(d);
1254 PWM_ASSERT(pw); 1256 PWM_ASSERT(pw);
1255 PWM_ASSERT(f); 1257 PWM_ASSERT(f);
1256 1258
1257 size_t encSize; 1259 size_t encSize;
1258 byte *encrypted = 0; 1260 byte *encrypted = 0;
1259 1261
1260 switch (algo) { 1262 switch (algo) {
1261 case PWM_CRYPT_BLOWFISH: { 1263 case PWM_CRYPT_BLOWFISH: {
1262 Blowfish::padNull(d); 1264 Blowfish::padNull(d);
1263 encSize = d->length(); 1265 encSize = d->length();
1264 encrypted = new byte[encSize]; 1266 encrypted = new byte[encSize];
1265 Blowfish bf; 1267 Blowfish bf;
1266 if (bf.bf_setkey((byte *) pw->latin1(), pw->length())) { 1268 if (bf.bf_setkey((byte *) pw->latin1(), pw->length())) {
1267 delete [] encrypted; 1269 delete [] encrypted;
1268 return e_weakPw; 1270 return e_weakPw;
1269 } 1271 }
1270 bf.bf_encrypt((byte *) encrypted, (byte *) d->c_str(), encSize); 1272 bf.bf_encrypt((byte *) encrypted, (byte *) d->c_str(), encSize);
1271 break; 1273 break;
1272 } 1274 }
1273 case PWM_CRYPT_AES128: 1275 case PWM_CRYPT_AES128:
1274 /*... fall through */ 1276 /*... fall through */
1275 case PWM_CRYPT_AES192: 1277 case PWM_CRYPT_AES192:
1276 case PWM_CRYPT_AES256: 1278 case PWM_CRYPT_AES256:
1277 case PWM_CRYPT_3DES: 1279 case PWM_CRYPT_3DES:
1278 case PWM_CRYPT_TWOFISH: 1280 case PWM_CRYPT_TWOFISH:
1279 case PWM_CRYPT_TWOFISH128: { 1281 case PWM_CRYPT_TWOFISH128: {
1280 if (!LibGCryptIf::available()) 1282 if (!LibGCryptIf::available())
1281 return e_cryptNotImpl; 1283 return e_cryptNotImpl;
1282 LibGCryptIf gc; 1284 LibGCryptIf gc;
1283 PwMerror err; 1285 PwMerror err;
1284 unsigned char *plain = new unsigned char[d->length() + 1024]; 1286 unsigned char *plain = new unsigned char[d->length() + 1024];
1285 memcpy(plain, d->c_str(), d->length()); 1287 memcpy(plain, d->c_str(), d->length());
1286 err = gc.encrypt(&encrypted, 1288 err = gc.encrypt(&encrypted,
1287 &encSize, 1289 &encSize,
1288 plain, 1290 plain,
1289 d->length(), 1291 d->length(),
1290 reinterpret_cast<const unsigned char *>(pw->latin1()), 1292 reinterpret_cast<const unsigned char *>(pw->latin1()),
1291 pw->length(), 1293 pw->length(),
1292 algo); 1294 algo);
1293 delete [] plain; 1295 delete [] plain;
1294 if (err != e_success) 1296 if (err != e_success)
1295 return e_cryptNotImpl; 1297 return e_cryptNotImpl;
1296 break; 1298 break;
1297 } 1299 }
1298 default: { 1300 default: {
1299 delete_ifnot_null_array(encrypted); 1301 delete_ifnot_null_array(encrypted);
1300 return e_cryptNotImpl; 1302 return e_cryptNotImpl;
1301 } } 1303 } }
1302 1304
1303 // write encrypted data to file 1305 // write encrypted data to file
1304 if (f->writeBlock(reinterpret_cast<const char *>(encrypted), 1306 if (f->writeBlock(reinterpret_cast<const char *>(encrypted),
1305 static_cast<Q_ULONG>(encSize)) 1307 static_cast<Q_ULONG>(encSize))
1306 != static_cast<Q_LONG>(encSize)) { 1308 != static_cast<Q_LONG>(encSize)) {
1307 delete_ifnot_null_array(encrypted); 1309 delete_ifnot_null_array(encrypted);
1308 return e_writeFile; 1310 return e_writeFile;
1309 } 1311 }
1310 delete_ifnot_null_array(encrypted); 1312 delete_ifnot_null_array(encrypted);
1311 return e_success; 1313 return e_success;
1312} 1314}
1313 1315
1314PwMerror PwMDoc::decrypt(string *d, unsigned int pos, const QString *pw, 1316PwMerror PwMDoc::decrypt(string *d, unsigned int pos, const QString *pw,
1315 char algo, QFile *f) 1317 char algo, QFile *f)
1316{ 1318{
1317 PWM_ASSERT(d); 1319 PWM_ASSERT(d);
1318 PWM_ASSERT(pw); 1320 PWM_ASSERT(pw);
1319 PWM_ASSERT(f); 1321 PWM_ASSERT(f);
1320 1322
1321 unsigned int cryptLen = f->size() - pos; 1323 unsigned int cryptLen = f->size() - pos;
1322 byte *encrypted = new byte[cryptLen]; 1324 byte *encrypted = new byte[cryptLen];
1323 byte *decrypted = new byte[cryptLen]; 1325 byte *decrypted = new byte[cryptLen];
1324 1326
1325 f->at(pos); 1327 f->at(pos);
1326#ifndef PWM_EMBEDDED 1328#ifndef PWM_EMBEDDED
1327 if (f->readBlock(reinterpret_cast<char *>(encrypted), 1329 if (f->readBlock(reinterpret_cast<char *>(encrypted),
1328 static_cast<Q_ULONG>(cryptLen)) 1330 static_cast<Q_ULONG>(cryptLen))
1329 != static_cast<Q_LONG>(cryptLen)) { 1331 != static_cast<Q_LONG>(cryptLen)) {
1330 delete [] encrypted; 1332 delete [] encrypted;
1331 delete [] decrypted; 1333 delete [] decrypted;
1332 return e_readFile; 1334 return e_readFile;
1333 } 1335 }
1334#else 1336#else
1335 if (f->readBlock((char *)(encrypted), 1337 if (f->readBlock((char *)(encrypted),
1336 (unsigned long)(cryptLen)) 1338 (unsigned long)(cryptLen))
1337 != (long)(cryptLen)) { 1339 != (long)(cryptLen)) {
1338 delete [] encrypted; 1340 delete [] encrypted;
1339 delete [] decrypted; 1341 delete [] decrypted;
1340 return e_readFile; 1342 return e_readFile;
1341 } 1343 }
1342#endif 1344#endif
1343 switch (algo) { 1345 switch (algo) {
1344 case PWM_CRYPT_BLOWFISH: { 1346 case PWM_CRYPT_BLOWFISH: {
1345 Blowfish bf; 1347 Blowfish bf;
1346 bf.bf_setkey((byte *) pw->latin1(), pw->length()); 1348 bf.bf_setkey((byte *) pw->latin1(), pw->length());
1347 bf.bf_decrypt(decrypted, encrypted, cryptLen); 1349 bf.bf_decrypt(decrypted, encrypted, cryptLen);
1348 break; 1350 break;
1349 } 1351 }
1350 case PWM_CRYPT_AES128: 1352 case PWM_CRYPT_AES128:
1351 /*... fall through */ 1353 /*... fall through */
1352 case PWM_CRYPT_AES192: 1354 case PWM_CRYPT_AES192:
1353 case PWM_CRYPT_AES256: 1355 case PWM_CRYPT_AES256:
1354 case PWM_CRYPT_3DES: 1356 case PWM_CRYPT_3DES:
1355 case PWM_CRYPT_TWOFISH: 1357 case PWM_CRYPT_TWOFISH:
1356 case PWM_CRYPT_TWOFISH128: { 1358 case PWM_CRYPT_TWOFISH128: {
1357 if (!LibGCryptIf::available()) 1359 if (!LibGCryptIf::available())
1358 return e_cryptNotImpl; 1360 return e_cryptNotImpl;
1359 LibGCryptIf gc; 1361 LibGCryptIf gc;
1360 PwMerror err; 1362 PwMerror err;
1361 err = gc.decrypt(&decrypted, 1363 err = gc.decrypt(&decrypted,
1362 &cryptLen, 1364 &cryptLen,
1363 encrypted, 1365 encrypted,
1364 cryptLen, 1366 cryptLen,
1365 reinterpret_cast<const unsigned char *>(pw->latin1()), 1367 reinterpret_cast<const unsigned char *>(pw->latin1()),
1366 pw->length(), 1368 pw->length(),
1367 algo); 1369 algo);
1368 if (err != e_success) { 1370 if (err != e_success) {
1369 delete [] encrypted; 1371 delete [] encrypted;
1370 delete [] decrypted; 1372 delete [] decrypted;
1371 return e_cryptNotImpl; 1373 return e_cryptNotImpl;
1372 } 1374 }
1373 break; 1375 break;
1374 } 1376 }
1375 default: { 1377 default: {
1376 delete [] encrypted; 1378 delete [] encrypted;
1377 delete [] decrypted; 1379 delete [] decrypted;
1378 return e_cryptNotImpl; 1380 return e_cryptNotImpl;
1379 } } 1381 } }
1380 delete [] encrypted; 1382 delete [] encrypted;
1381#ifndef PWM_EMBEDDED 1383#ifndef PWM_EMBEDDED
1382 d->assign(reinterpret_cast<const char *>(decrypted), 1384 d->assign(reinterpret_cast<const char *>(decrypted),
1383 static_cast<string::size_type>(cryptLen)); 1385 static_cast<string::size_type>(cryptLen));
1384#else 1386#else
1385 d->assign((const char *)(decrypted), 1387 d->assign((const char *)(decrypted),
1386 (string::size_type)(cryptLen)); 1388 (string::size_type)(cryptLen));
1387#endif 1389#endif
1388 delete [] decrypted; 1390 delete [] decrypted;
1389 if (algo == PWM_CRYPT_BLOWFISH) { 1391 if (algo == PWM_CRYPT_BLOWFISH) {
1390 if (!Blowfish::unpadNull(d)) { 1392 if (!Blowfish::unpadNull(d)) {
1391 BUG(); 1393 BUG();
1392 return e_readFile; 1394 return e_readFile;
1393 } 1395 }
1394 } 1396 }
1395 return e_success; 1397 return e_success;
1396} 1398}
1397 1399
1398PwMerror PwMDoc::checkDataHash(char dataHashType, const string *dataHash, 1400PwMerror PwMDoc::checkDataHash(char dataHashType, const string *dataHash,
1399 const string *dataStream) 1401 const string *dataStream)
1400{ 1402{
1401 PWM_ASSERT(dataHash); 1403 PWM_ASSERT(dataHash);
1402 PWM_ASSERT(dataStream); 1404 PWM_ASSERT(dataStream);
1403 switch(dataHashType) { 1405 switch(dataHashType) {
1404 case PWM_HASH_SHA1: { 1406 case PWM_HASH_SHA1: {
1405 Sha1 hash; 1407 Sha1 hash;
1406 hash.sha1_write((byte*)dataStream->c_str(), dataStream->length()); 1408 hash.sha1_write((byte*)dataStream->c_str(), dataStream->length());
1407 string ret = hash.sha1_read(); 1409 string ret = hash.sha1_read();
1408 if (ret != *dataHash) 1410 if (ret != *dataHash)
1409 return e_fileCorrupt; 1411 return e_fileCorrupt;
1410 break; 1412 break;
1411 } 1413 }
1412 case PWM_HASH_SHA256: 1414 case PWM_HASH_SHA256:
1413 /*... fall through */ 1415 /*... fall through */
1414 case PWM_HASH_SHA384: 1416 case PWM_HASH_SHA384:
1415 case PWM_HASH_SHA512: 1417 case PWM_HASH_SHA512:
1416 case PWM_HASH_MD5: 1418 case PWM_HASH_MD5:
1417 case PWM_HASH_RMD160: 1419 case PWM_HASH_RMD160:
1418 case PWM_HASH_TIGER: { 1420 case PWM_HASH_TIGER: {
1419 if (!LibGCryptIf::available()) 1421 if (!LibGCryptIf::available())
1420 return e_hashNotImpl; 1422 return e_hashNotImpl;
1421 LibGCryptIf gc; 1423 LibGCryptIf gc;
1422 PwMerror err; 1424 PwMerror err;
1423 unsigned char *buf; 1425 unsigned char *buf;
1424 size_t hashLen; 1426 size_t hashLen;
1425 err = gc.hash(&buf, 1427 err = gc.hash(&buf,
1426 &hashLen, 1428 &hashLen,
1427 reinterpret_cast<const unsigned char *>(dataStream->c_str()), 1429 reinterpret_cast<const unsigned char *>(dataStream->c_str()),
1428 dataStream->length(), 1430 dataStream->length(),
1429 dataHashType); 1431 dataHashType);
1430 if (err != e_success) 1432 if (err != e_success)
1431 return e_hashNotImpl; 1433 return e_hashNotImpl;
1432 string calcHash(reinterpret_cast<const char *>(buf), 1434 string calcHash(reinterpret_cast<const char *>(buf),
1433 static_cast<string::size_type>(hashLen)); 1435 static_cast<string::size_type>(hashLen));
1434 delete [] buf; 1436 delete [] buf;
1435 if (calcHash != *dataHash) 1437 if (calcHash != *dataHash)
1436 return e_fileCorrupt; 1438 return e_fileCorrupt;
1437 break; 1439 break;
1438 } 1440 }
1439 default: 1441 default:
1440 return e_hashNotImpl; 1442 return e_hashNotImpl;
1441 } 1443 }
1442 return e_success; 1444 return e_success;
1443} 1445}
1444 1446
1445bool PwMDoc::lockAt(unsigned int category, unsigned int index, 1447bool PwMDoc::lockAt(unsigned int category, unsigned int index,
1446 bool lock) 1448 bool lock)
1447{ 1449{
1448 if (index >= numEntries(category)) { 1450 if (index >= numEntries(category)) {
1449 BUG(); 1451 BUG();
1450 return false; 1452 return false;
1451 } 1453 }
1452 if (lock == dti.dta[category].d[index].lockStat) 1454 if (lock == dti.dta[category].d[index].lockStat)
1453 return true; 1455 return true;
1454 1456
1455 if (!lock && currentPw != "") { 1457 if (!lock && currentPw != "") {
1456 // "unlocking" and "password is already set" 1458 // "unlocking" and "password is already set"
1457 if (!getDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW)) { 1459 if (!getDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW)) {
1458 // unlocking without pw not allowed 1460 // unlocking without pw not allowed
1459 QString pw; 1461 QString pw;
1460 pw = requestMpw(getDocStatFlag(DOC_STAT_USE_CHIPCARD)); 1462 pw = requestMpw(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
1461 if (pw != "") { 1463 if (pw != "") {
1462 if (pw != currentPw) { 1464 if (pw != currentPw) {
1463 wrongMpwMsgBox(getDocStatFlag(DOC_STAT_USE_CHIPCARD)); 1465 wrongMpwMsgBox(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
1464 return false; 1466 return false;
1465 } else { 1467 } else {
1466 timer()->start(DocTimer::id_mpwTimer); 1468 timer()->start(DocTimer::id_mpwTimer);
1467 } 1469 }
1468 } else { 1470 } else {
1469 return false; 1471 return false;
1470 } 1472 }
1471 } else { 1473 } else {
1472 timer()->start(DocTimer::id_mpwTimer); 1474 timer()->start(DocTimer::id_mpwTimer);
1473 } 1475 }
1474 } 1476 }
1475 1477
1476 dti.dta[category].d[index].lockStat = lock; 1478 dti.dta[category].d[index].lockStat = lock;
1477 dti.dta[category].d[index].rev++; // increment revision counter. 1479 dti.dta[category].d[index].rev++; // increment revision counter.
1478 1480
1479 emitDataChanged(this); 1481 emitDataChanged(this);
1480 if (!lock) 1482 if (!lock)
1481 timer()->start(DocTimer::id_autoLockTimer); 1483 timer()->start(DocTimer::id_autoLockTimer);
1482 1484
1483 return true; 1485 return true;
1484 1486
1485} 1487}
1486 1488
1487bool PwMDoc::lockAt(const QString &category,unsigned int index, 1489bool PwMDoc::lockAt(const QString &category,unsigned int index,
1488 bool lock) 1490 bool lock)
1489{ 1491{
1490 unsigned int cat = 0; 1492 unsigned int cat = 0;
1491 1493
1492 if (!findCategory(category, &cat)) { 1494 if (!findCategory(category, &cat)) {
1493 BUG(); 1495 BUG();
1494 return false; 1496 return false;
1495 } 1497 }
1496 1498
1497 return lockAt(cat, index, lock); 1499 return lockAt(cat, index, lock);
1498} 1500}
1499 1501
1500bool PwMDoc::lockAll(bool lock) 1502bool PwMDoc::lockAll(bool lock)
1501{ 1503{
1502 if (!lock && isDeepLocked()) { 1504 if (!lock && isDeepLocked()) {
1503 PwMerror ret; 1505 PwMerror ret;
1504 ret = deepLock(false); 1506 ret = deepLock(false);
1505 if (ret != e_success) 1507 if (ret != e_success)
1506 return false; 1508 return false;
1507 return true; 1509 return true;
1508 } 1510 }
1509 if (isDocEmpty()) { 1511 if (isDocEmpty()) {
1510 return true; 1512 return true;
1511 } 1513 }
1512 if (!lock && currentPw != "") { 1514 if (!lock && currentPw != "") {
1513 // unlocking and password is already set 1515 // unlocking and password is already set
1514 if (!getDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW)) { 1516 if (!getDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW)) {
1515 // unlocking without pw not allowed 1517 // unlocking without pw not allowed
1516 QString pw; 1518 QString pw;
1517 pw = requestMpw(getDocStatFlag(DOC_STAT_USE_CHIPCARD)); 1519 pw = requestMpw(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
1518 if (pw != "") { 1520 if (pw != "") {
1519 if (pw != currentPw) { 1521 if (pw != currentPw) {
1520 wrongMpwMsgBox(getDocStatFlag(DOC_STAT_USE_CHIPCARD)); 1522 wrongMpwMsgBox(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
1521 return false; 1523 return false;
1522 } else { 1524 } else {
1523 timer()->start(DocTimer::id_mpwTimer); 1525 timer()->start(DocTimer::id_mpwTimer);
1524 } 1526 }
1525 } else { 1527 } else {
1526 return false; 1528 return false;
1527 } 1529 }
1528 } else { 1530 } else {
1529 timer()->start(DocTimer::id_mpwTimer); 1531 timer()->start(DocTimer::id_mpwTimer);
1530 } 1532 }
1531 } 1533 }
1532 1534
1533 vector<PwMCategoryItem>::iterator catBegin = dti.dta.begin(), 1535 vector<PwMCategoryItem>::iterator catBegin = dti.dta.begin(),
1534 catEnd = dti.dta.end(), 1536 catEnd = dti.dta.end(),
1535 catI = catBegin; 1537 catI = catBegin;
1536 vector<PwMDataItem>::iterator entrBegin, entrEnd, entrI; 1538 vector<PwMDataItem>::iterator entrBegin, entrEnd, entrI;
1537 while (catI != catEnd) { 1539 while (catI != catEnd) {
1538 entrBegin = catI->d.begin(); 1540 entrBegin = catI->d.begin();
1539 entrEnd = catI->d.end(); 1541 entrEnd = catI->d.end();
1540 entrI = entrBegin; 1542 entrI = entrBegin;
1541 while (entrI != entrEnd) { 1543 while (entrI != entrEnd) {
1542 entrI->lockStat = lock; 1544 entrI->lockStat = lock;
1543 entrI->rev++; // increment revision counter. 1545 entrI->rev++; // increment revision counter.
1544 ++entrI; 1546 ++entrI;
1545 } 1547 }
1546 ++catI; 1548 ++catI;
1547 } 1549 }
1548 1550
1549 emitDataChanged(this); 1551 emitDataChanged(this);
1550 if (lock) 1552 if (lock)
1551 timer()->stop(DocTimer::id_autoLockTimer); 1553 timer()->stop(DocTimer::id_autoLockTimer);
1552 else 1554 else
1553 timer()->start(DocTimer::id_autoLockTimer); 1555 timer()->start(DocTimer::id_autoLockTimer);
1554 1556
1555 return true; 1557 return true;
1556} 1558}
1557 1559
1558bool PwMDoc::isLocked(const QString &category, unsigned int index) 1560bool PwMDoc::isLocked(const QString &category, unsigned int index)
1559{ 1561{
1560 unsigned int cat = 0; 1562 unsigned int cat = 0;
1561 1563
1562 if (!findCategory(category, &cat)) { 1564 if (!findCategory(category, &cat)) {
1563 BUG(); 1565 BUG();
1564 return false; 1566 return false;
1565 } 1567 }
1566 1568
1567 return isLocked(cat, index); 1569 return isLocked(cat, index);
1568} 1570}
1569 1571
1570bool PwMDoc::unlockAll_tempoary(bool revert) 1572bool PwMDoc::unlockAll_tempoary(bool revert)
1571{ 1573{
1572 static vector< vector<bool> > *oldLockStates = 0; 1574 static vector< vector<bool> > *oldLockStates = 0;
1573 static bool wasDeepLocked; 1575 static bool wasDeepLocked;
1574 1576
1575 if (revert) {// revert the unlocking 1577 if (revert) {// revert the unlocking
1576 if (oldLockStates) { 1578 if (oldLockStates) {
1577 /* we actually _have_ unlocked something, because 1579 /* we actually _have_ unlocked something, because
1578 * we have allocated space for the oldLockStates. 1580 * we have allocated space for the oldLockStates.
1579 * So, go on and revert them! 1581 * So, go on and revert them!
1580 */ 1582 */
1581 if (wasDeepLocked) { 1583 if (wasDeepLocked) {
1582 PwMerror ret = deepLock(true); 1584 PwMerror ret = deepLock(true);
1583 if (ret == e_success) { 1585 if (ret == e_success) {
1584 /* deep-lock succeed. We are save. 1586 /* deep-lock succeed. We are save.
1585 * (but if it failed, just go on 1587 * (but if it failed, just go on
1586 * lock them normally) 1588 * lock them normally)
1587 */ 1589 */
1588 delete_and_null(oldLockStates); 1590 delete_and_null(oldLockStates);
1589 timer()->start(DocTimer::id_autoLockTimer); 1591 timer()->start(DocTimer::id_autoLockTimer);
1590 printDebug("tempoary unlocking of dta " 1592 printDebug("tempoary unlocking of dta "
1591 "reverted by deep-locking."); 1593 "reverted by deep-locking.");
1592 return true; 1594 return true;
1593 } 1595 }
1594 printDebug("deep-lock failed while reverting! " 1596 printDebug("deep-lock failed while reverting! "
1595 "Falling back to normal-lock."); 1597 "Falling back to normal-lock.");
1596 } 1598 }
1597 if (unlikely(!wasDeepLocked && 1599 if (unlikely(!wasDeepLocked &&
1598 numCategories() != oldLockStates->size())) { 1600 numCategories() != oldLockStates->size())) {
1599 /* DOH! We have modified "dta" while 1601 /* DOH! We have modified "dta" while
1600 * it was unlocked tempoary. DON'T DO THIS! 1602 * it was unlocked tempoary. DON'T DO THIS!
1601 */ 1603 */
1602 BUG(); 1604 BUG();
1603 delete_and_null(oldLockStates); 1605 delete_and_null(oldLockStates);
1604 timer()->start(DocTimer::id_autoLockTimer); 1606 timer()->start(DocTimer::id_autoLockTimer);
1605 return false; 1607 return false;
1606 } 1608 }
1607 vector<PwMCategoryItem>::iterator catBegin = dti.dta.begin(), 1609 vector<PwMCategoryItem>::iterator catBegin = dti.dta.begin(),
1608 catEnd = dti.dta.end(), 1610 catEnd = dti.dta.end(),
1609 catI = catBegin; 1611 catI = catBegin;
1610 vector<PwMDataItem>::iterator entrBegin, entrEnd, entrI; 1612 vector<PwMDataItem>::iterator entrBegin, entrEnd, entrI;
1611 vector< vector<bool> >::iterator oldCatStatI = oldLockStates->begin(); 1613 vector< vector<bool> >::iterator oldCatStatI = oldLockStates->begin();
1612 vector<bool>::iterator oldEntrStatBegin, 1614 vector<bool>::iterator oldEntrStatBegin,
1613 oldEntrStatEnd, 1615 oldEntrStatEnd,
1614 oldEntrStatI; 1616 oldEntrStatI;
1615 while (catI != catEnd) { 1617 while (catI != catEnd) {
1616 entrBegin = catI->d.begin(); 1618 entrBegin = catI->d.begin();
1617 entrEnd = catI->d.end(); 1619 entrEnd = catI->d.end();
1618 entrI = entrBegin; 1620 entrI = entrBegin;
1619 if (likely(!wasDeepLocked)) { 1621 if (likely(!wasDeepLocked)) {
1620 oldEntrStatBegin = oldCatStatI->begin(); 1622 oldEntrStatBegin = oldCatStatI->begin();
1621 oldEntrStatEnd = oldCatStatI->end(); 1623 oldEntrStatEnd = oldCatStatI->end();
1622 oldEntrStatI = oldEntrStatBegin; 1624 oldEntrStatI = oldEntrStatBegin;
1623 if (unlikely(catI->d.size() != oldCatStatI->size())) { 1625 if (unlikely(catI->d.size() != oldCatStatI->size())) {
1624 /* DOH! We have modified "dta" while 1626 /* DOH! We have modified "dta" while
1625 * it was unlocked tempoary. DON'T DO THIS! 1627 * it was unlocked tempoary. DON'T DO THIS!
1626 */ 1628 */
1627 BUG(); 1629 BUG();
1628 delete_and_null(oldLockStates); 1630 delete_and_null(oldLockStates);
1629 timer()->start(DocTimer::id_autoLockTimer); 1631 timer()->start(DocTimer::id_autoLockTimer);
1630 return false; 1632 return false;
1631 } 1633 }
1632 } 1634 }
1633 while (entrI != entrEnd) { 1635 while (entrI != entrEnd) {
1634 if (wasDeepLocked) { 1636 if (wasDeepLocked) {
1635 /* this is an error-fallback if 1637 /* this is an error-fallback if
1636 * deeplock didn't succeed 1638 * deeplock didn't succeed
1637 */ 1639 */
1638 entrI->lockStat = true; 1640 entrI->lockStat = true;
1639 } else { 1641 } else {
1640 entrI->lockStat = *oldEntrStatI; 1642 entrI->lockStat = *oldEntrStatI;
1641 } 1643 }
1642 ++entrI; 1644 ++entrI;
1643 if (likely(!wasDeepLocked)) 1645 if (likely(!wasDeepLocked))
1644 ++oldEntrStatI; 1646 ++oldEntrStatI;
1645 } 1647 }
1646 ++catI; 1648 ++catI;
1647 if (likely(!wasDeepLocked)) 1649 if (likely(!wasDeepLocked))
1648 ++oldCatStatI; 1650 ++oldCatStatI;
1649 } 1651 }
1650 delete_and_null(oldLockStates); 1652 delete_and_null(oldLockStates);
1651 if (unlikely(wasDeepLocked)) { 1653 if (unlikely(wasDeepLocked)) {
1652 /* error fallback... */ 1654 /* error fallback... */
1653 unsetDocStatFlag(DOC_STAT_DEEPLOCKED); 1655 unsetDocStatFlag(DOC_STAT_DEEPLOCKED);
1654 emitDataChanged(this); 1656 emitDataChanged(this);
1655 printDebug("WARNING: unlockAll_tempoary(true) " 1657 printDebug("WARNING: unlockAll_tempoary(true) "
1656 "deeplock fallback!"); 1658 "deeplock fallback!");
1657 } 1659 }
1658 printDebug("tempoary unlocking of dta reverted."); 1660 printDebug("tempoary unlocking of dta reverted.");
1659 } else { 1661 } else {
1660 printDebug("unlockAll_tempoary(true): nothing to do."); 1662 printDebug("unlockAll_tempoary(true): nothing to do.");
1661 } 1663 }
1662 timer()->start(DocTimer::id_autoLockTimer); 1664 timer()->start(DocTimer::id_autoLockTimer);
1663 } else {// unlock all data tempoary 1665 } else {// unlock all data tempoary
1664 if (unlikely(oldLockStates != 0)) { 1666 if (unlikely(oldLockStates != 0)) {
1665 /* DOH! We have already unlocked the data tempoarly. 1667 /* DOH! We have already unlocked the data tempoarly.
1666 * No need to do it twice. ;) 1668 * No need to do it twice. ;)
1667 */ 1669 */
1668 BUG(); 1670 BUG();
1669 return false; 1671 return false;
1670 } 1672 }
1671 wasDeepLocked = false; 1673 wasDeepLocked = false;
1672 bool mustUnlock = false; 1674 bool mustUnlock = false;
1673 if (isDeepLocked()) { 1675 if (isDeepLocked()) {
1674 PwMerror ret; 1676 PwMerror ret;
1675 while (1) { 1677 while (1) {
1676 ret = deepLock(false); 1678 ret = deepLock(false);
1677 if (ret == e_success) { 1679 if (ret == e_success) {
1678 break; 1680 break;
1679 } else if (ret == e_wrongPw) { 1681 } else if (ret == e_wrongPw) {
1680 wrongMpwMsgBox(getDocStatFlag(DOC_STAT_USE_CHIPCARD)); 1682 wrongMpwMsgBox(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
1681 } else { 1683 } else {
1682 printDebug("deep-unlocking failed while " 1684 printDebug("deep-unlocking failed while "
1683 "tempoary unlocking!"); 1685 "tempoary unlocking!");
1684 return false; 1686 return false;
1685 } 1687 }
1686 } 1688 }
1687 wasDeepLocked = true; 1689 wasDeepLocked = true;
1688 mustUnlock = true; 1690 mustUnlock = true;
1689 } else { 1691 } else {
1690 // first check if it's needed to unlock some entries 1692 // first check if it's needed to unlock some entries
1691 vector<PwMCategoryItem>::iterator catBegin = dti.dta.begin(), 1693 vector<PwMCategoryItem>::iterator catBegin = dti.dta.begin(),
1692 catEnd = dti.dta.end(), 1694 catEnd = dti.dta.end(),
1693 catI = catBegin; 1695 catI = catBegin;
1694 vector<PwMDataItem>::iterator entrBegin, entrEnd, entrI; 1696 vector<PwMDataItem>::iterator entrBegin, entrEnd, entrI;
1695 while (catI != catEnd) { 1697 while (catI != catEnd) {
1696 entrBegin = catI->d.begin(); 1698 entrBegin = catI->d.begin();
1697 entrEnd = catI->d.end(); 1699 entrEnd = catI->d.end();
1698 entrI = entrBegin; 1700 entrI = entrBegin;
1699 while (entrI != entrEnd) { 1701 while (entrI != entrEnd) {
1700 if (entrI->lockStat == true) { 1702 if (entrI->lockStat == true) {
1701 mustUnlock = true; 1703 mustUnlock = true;
1702 break; 1704 break;
1703 } 1705 }
1704 ++entrI; 1706 ++entrI;
1705 } 1707 }
1706 if (mustUnlock) 1708 if (mustUnlock)
1707 break; 1709 break;
1708 ++catI; 1710 ++catI;
1709 } 1711 }
1710 } 1712 }
1711 if (!mustUnlock) { 1713 if (!mustUnlock) {
1712 // nothing to do. 1714 // nothing to do.
1713 timer()->stop(DocTimer::id_autoLockTimer); 1715 timer()->stop(DocTimer::id_autoLockTimer);
1714 printDebug("unlockAll_tempoary(): nothing to do."); 1716 printDebug("unlockAll_tempoary(): nothing to do.");
1715 return true; 1717 return true;
1716 } else if (!wasDeepLocked) { 1718 } else if (!wasDeepLocked) {
1717 if (!getDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW) && 1719 if (!getDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW) &&
1718 currentPw != "") { 1720 currentPw != "") {
1719 /* we can't unlock without mpw, so 1721 /* we can't unlock without mpw, so
1720 * we need to ask for it. 1722 * we need to ask for it.
1721 */ 1723 */
1722 QString pw; 1724 QString pw;
1723 while (1) { 1725 while (1) {
1724 pw = requestMpw(getDocStatFlag(DOC_STAT_USE_CHIPCARD)); 1726 pw = requestMpw(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
1725 if (pw == "") { 1727 if (pw == "") {
1726 return false; 1728 return false;
1727 } else if (pw == currentPw) { 1729 } else if (pw == currentPw) {
1728 break; 1730 break;
1729 } 1731 }
1730 wrongMpwMsgBox(getDocStatFlag(DOC_STAT_USE_CHIPCARD)); 1732 wrongMpwMsgBox(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
1731 } 1733 }
1732 } 1734 }
1733 } 1735 }
1734 timer()->stop(DocTimer::id_autoLockTimer); 1736 timer()->stop(DocTimer::id_autoLockTimer);
1735 oldLockStates = new vector< vector<bool> >; 1737 oldLockStates = new vector< vector<bool> >;
1736 vector<bool> tmp_vec; 1738 vector<bool> tmp_vec;
1737 vector<PwMCategoryItem>::iterator catBegin = dti.dta.begin(), 1739 vector<PwMCategoryItem>::iterator catBegin = dti.dta.begin(),
1738 catEnd = dti.dta.end(), 1740 catEnd = dti.dta.end(),
1739 catI = catBegin; 1741 catI = catBegin;
1740 vector<PwMDataItem>::iterator entrBegin, entrEnd, entrI; 1742 vector<PwMDataItem>::iterator entrBegin, entrEnd, entrI;
1741 while (catI != catEnd) { 1743 while (catI != catEnd) {
1742 entrBegin = catI->d.begin(); 1744 entrBegin = catI->d.begin();
1743 entrEnd = catI->d.end(); 1745 entrEnd = catI->d.end();
1744 entrI = entrBegin; 1746 entrI = entrBegin;
1745 while (entrI != entrEnd) { 1747 while (entrI != entrEnd) {
1746 if (!wasDeepLocked) { 1748 if (!wasDeepLocked) {
1747 tmp_vec.push_back(entrI->lockStat); 1749 tmp_vec.push_back(entrI->lockStat);
1748 } 1750 }
1749 entrI->lockStat = false; 1751 entrI->lockStat = false;
1750 ++entrI; 1752 ++entrI;
1751 } 1753 }
1752 if (!wasDeepLocked) { 1754 if (!wasDeepLocked) {
1753 oldLockStates->push_back(tmp_vec); 1755 oldLockStates->push_back(tmp_vec);
1754 tmp_vec.clear(); 1756 tmp_vec.clear();
1755 } 1757 }
1756 ++catI; 1758 ++catI;
1757 } 1759 }
1758 printDebug("tempoary unlocked dta."); 1760 printDebug("tempoary unlocked dta.");
1759 } 1761 }
1760 1762
1761 return true; 1763 return true;
1762} 1764}
1763 1765
1764PwMerror PwMDoc::deepLock(bool lock, bool saveToFile) 1766PwMerror PwMDoc::deepLock(bool lock, bool saveToFile)
1765{ 1767{
1766 PwMerror ret; 1768 PwMerror ret;
1767 1769
1768 if (lock) { 1770 if (lock) {
1769 if (isDeepLocked()) 1771 if (isDeepLocked())
1770 return e_lock; 1772 return e_lock;
1771 if (saveToFile) { 1773 if (saveToFile) {
1772 if (isDocEmpty()) 1774 if (isDocEmpty())
1773 return e_docIsEmpty; 1775 return e_docIsEmpty;
1774 ret = saveDoc(conf()->confGlobCompression()); 1776 ret = saveDoc(conf()->confGlobCompression());
1775 if (ret == e_filename) { 1777 if (ret == e_filename) {
1776 /* the doc wasn't saved to a file 1778 /* the doc wasn't saved to a file
1777 * by the user, yet. 1779 * by the user, yet.
1778 */ 1780 */
1779 cantDeeplock_notSavedMsgBox(); 1781 cantDeeplock_notSavedMsgBox();
1780 return e_docNotSaved; 1782 return e_docNotSaved;
1781 } else if (ret != e_success) { 1783 } else if (ret != e_success) {
1782 return e_lock; 1784 return e_lock;
1783 } 1785 }
1784 } 1786 }
1785 timer()->stop(DocTimer::id_autoLockTimer); 1787 timer()->stop(DocTimer::id_autoLockTimer);
1786 clearDoc(); 1788 clearDoc();
1787 PwMDataItem d; 1789 PwMDataItem d;
1788 d.desc = IS_DEEPLOCKED_SHORTMSG.latin1(); 1790 d.desc = IS_DEEPLOCKED_SHORTMSG.latin1();
1789 d.comment = IS_DEEPLOCKED_MSG.latin1(); 1791 d.comment = IS_DEEPLOCKED_MSG.latin1();
1790 d.listViewPos = 0; 1792 d.listViewPos = 0;
1791 addEntry(DEFAULT_CATEGORY, &d, true); 1793 addEntry(DEFAULT_CATEGORY, &d, true);
1792 lockAt(DEFAULT_CATEGORY, 0, true); 1794 lockAt(DEFAULT_CATEGORY, 0, true);
1793 unsetDocStatFlag(DOC_STAT_DISK_DIRTY); 1795 unsetDocStatFlag(DOC_STAT_DISK_DIRTY);
1794 setDocStatFlag(DOC_STAT_DEEPLOCKED); 1796 setDocStatFlag(DOC_STAT_DEEPLOCKED);
1795 } else { 1797 } else {
1796 if (!isDeepLocked()) 1798 if (!isDeepLocked())
1797 return e_lock; 1799 return e_lock;
1798 ret = openDoc(&filename, (conf()->confGlobUnlockOnOpen()) 1800 ret = openDoc(&filename, (conf()->confGlobUnlockOnOpen())
1799 ? 0 : 1); 1801 ? 0 : 1);
1800 if (ret == e_wrongPw) { 1802 if (ret == e_wrongPw) {
1801 return e_wrongPw; 1803 return e_wrongPw;
1802 } else if (ret != e_success) { 1804 } else if (ret != e_success) {
1803 printDebug(string("PwMDoc::deepLock(false): ERR! openDoc() == ") 1805 printDebug(string("PwMDoc::deepLock(false): ERR! openDoc() == ")
1804 + tostr(static_cast<int>(ret))); 1806 + tostr(static_cast<int>(ret)));
1805 return e_lock; 1807 return e_lock;
1806 } 1808 }
1807 unsetDocStatFlag(DOC_STAT_DEEPLOCKED); 1809 unsetDocStatFlag(DOC_STAT_DEEPLOCKED);
1808 timer()->start(DocTimer::id_autoLockTimer); 1810 timer()->start(DocTimer::id_autoLockTimer);
1809 } 1811 }
1810 1812
1811 emitDataChanged(this); 1813 emitDataChanged(this);
1812 return e_success; 1814 return e_success;
1813} 1815}
1814 1816
1815void PwMDoc::_deepUnlock() 1817void PwMDoc::_deepUnlock()
1816{ 1818{
1817 deepLock(false); 1819 deepLock(false);
1818} 1820}
1819 1821
1820void PwMDoc::clearDoc() 1822void PwMDoc::clearDoc()
1821{ 1823{
1822 dti.clear(); 1824 dti.clear();
1823 PwMCategoryItem d; 1825 PwMCategoryItem d;
1824 d.name = DEFAULT_CATEGORY.latin1(); 1826 d.name = DEFAULT_CATEGORY.latin1();
1825 dti.dta.push_back(d); 1827 dti.dta.push_back(d);
1826 currentPw = ""; 1828 currentPw = "";
1827 unsetDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW); 1829 unsetDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW);
1828} 1830}
1829 1831
1830void PwMDoc::changeCurrentPw() 1832void PwMDoc::changeCurrentPw()
1831{ 1833{
1832 if (currentPw == "") 1834 if (currentPw == "")
1833 return; // doc hasn't been saved. No mpw available. 1835 return; // doc hasn't been saved. No mpw available.
1834 bool useChipcard = getDocStatFlag(DOC_STAT_USE_CHIPCARD); 1836 bool useChipcard = getDocStatFlag(DOC_STAT_USE_CHIPCARD);
1835 QString pw = requestMpwChange(&currentPw, &useChipcard); 1837 QString pw = requestMpwChange(&currentPw, &useChipcard);
1836 if (pw == "") 1838 if (pw == "")
1837 return; 1839 return;
1838 if (useChipcard) 1840 if (useChipcard)
1839 setDocStatFlag(DOC_STAT_USE_CHIPCARD); 1841 setDocStatFlag(DOC_STAT_USE_CHIPCARD);
1840 else 1842 else
1841 unsetDocStatFlag(DOC_STAT_USE_CHIPCARD); 1843 unsetDocStatFlag(DOC_STAT_USE_CHIPCARD);
1842 setCurrentPw(pw); 1844 setCurrentPw(pw);
1843} 1845}
1844 1846
1845void PwMDoc::setListViewPos(const QString &category, unsigned int index, 1847void PwMDoc::setListViewPos(const QString &category, unsigned int index,
1846 int pos) 1848 int pos)
1847{ 1849{
1848 unsigned int cat = 0; 1850 unsigned int cat = 0;
1849 1851
1850 if (!findCategory(category, &cat)) { 1852 if (!findCategory(category, &cat)) {
1851 BUG(); 1853 BUG();
1852 return; 1854 return;
1853 } 1855 }
1854 setListViewPos(cat, index, pos); 1856 setListViewPos(cat, index, pos);
1855} 1857}
1856 1858
1857void PwMDoc::setListViewPos(unsigned int category, unsigned int index, 1859void PwMDoc::setListViewPos(unsigned int category, unsigned int index,
1858 int pos) 1860 int pos)
1859{ 1861{
1860 dti.dta[category].d[index].listViewPos = pos; 1862 dti.dta[category].d[index].listViewPos = pos;
1861 1863
1862/* FIXME workaround: don't flag dirty, because this function sometimes 1864/* FIXME workaround: don't flag dirty, because this function sometimes
1863 * get's called when it shouldn't. It's because PwMView assumes 1865 * get's called when it shouldn't. It's because PwMView assumes
1864 * the user resorted the UI on behalf of signal layoutChanged(). 1866 * the user resorted the UI on behalf of signal layoutChanged().
1865 * This is somewhat broken and incorrect, but I've no other 1867 * This is somewhat broken and incorrect, but I've no other
1866 * solution for now. 1868 * solution for now.
1867 */ 1869 */
1868 //setDocStatFlag(DOC_STAT_DISK_DIRTY); 1870 //setDocStatFlag(DOC_STAT_DISK_DIRTY);
1869} 1871}
1870 1872
1871int PwMDoc::getListViewPos(const QString &category, unsigned int index) 1873int PwMDoc::getListViewPos(const QString &category, unsigned int index)
1872{ 1874{
1873 unsigned int cat = 0; 1875 unsigned int cat = 0;
1874 1876
1875 if (!findCategory(category, &cat)) { 1877 if (!findCategory(category, &cat)) {
1876 BUG(); 1878 BUG();
1877 return -1; 1879 return -1;
1878 } 1880 }
1879 1881
1880 return dti.dta[cat].d[index].listViewPos; 1882 return dti.dta[cat].d[index].listViewPos;
1881} 1883}
1882 1884
1883void PwMDoc::findEntry(unsigned int category, PwMDataItem find, unsigned int searchIn, 1885void PwMDoc::findEntry(unsigned int category, PwMDataItem find, unsigned int searchIn,
1884 vector<unsigned int> *foundPositions, bool breakAfterFound, 1886 vector<unsigned int> *foundPositions, bool breakAfterFound,
1885 bool caseSensitive, bool exactWordMatch, bool sortByLvp) 1887 bool caseSensitive, bool exactWordMatch, bool sortByLvp)
1886{ 1888{
1887 PWM_ASSERT(foundPositions); 1889 PWM_ASSERT(foundPositions);
1888 PWM_ASSERT(searchIn); 1890 PWM_ASSERT(searchIn);
1889 foundPositions->clear(); 1891 foundPositions->clear();
1890 1892
1891 unsigned int i, entries = numEntries(category); 1893 unsigned int i, entries = numEntries(category);
1892 for (i = 0; i < entries; ++i) { 1894 for (i = 0; i < entries; ++i) {
1893 if (searchIn & SEARCH_IN_DESC) { 1895 if (searchIn & SEARCH_IN_DESC) {
1894 if (!compareString(find.desc, dti.dta[category].d[i].desc, 1896 if (!compareString(find.desc, dti.dta[category].d[i].desc,
1895 caseSensitive, exactWordMatch)) { 1897 caseSensitive, exactWordMatch)) {
1896 continue; 1898 continue;
1897 } 1899 }
1898 } 1900 }
1899 if (searchIn & SEARCH_IN_NAME) { 1901 if (searchIn & SEARCH_IN_NAME) {
1900 if (!compareString(find.name, dti.dta[category].d[i].name, 1902 if (!compareString(find.name, dti.dta[category].d[i].name,
1901 caseSensitive, exactWordMatch)) { 1903 caseSensitive, exactWordMatch)) {
1902 continue; 1904 continue;
1903 } 1905 }
1904 } 1906 }
1905 if (searchIn & SEARCH_IN_PW) { 1907 if (searchIn & SEARCH_IN_PW) {
1906 bool wasLocked = isLocked(category, i); 1908 bool wasLocked = isLocked(category, i);
1907 getDataChangedLock(); 1909 getDataChangedLock();
1908 lockAt(category, i, false); 1910 lockAt(category, i, false);
1909 if (!compareString(find.pw, dti.dta[category].d[i].pw, 1911 if (!compareString(find.pw, dti.dta[category].d[i].pw,
1910 caseSensitive, exactWordMatch)) { 1912 caseSensitive, exactWordMatch)) {
1911 lockAt(category, i, wasLocked); 1913 lockAt(category, i, wasLocked);
1912 putDataChangedLock(); 1914 putDataChangedLock();
1913 continue; 1915 continue;
1914 } 1916 }
1915 lockAt(category, i, wasLocked); 1917 lockAt(category, i, wasLocked);
1916 putDataChangedLock(); 1918 putDataChangedLock();
1917 } 1919 }
1918 if (searchIn & SEARCH_IN_COMMENT) { 1920 if (searchIn & SEARCH_IN_COMMENT) {
1919 if (!compareString(find.comment, dti.dta[category].d[i].comment, 1921 if (!compareString(find.comment, dti.dta[category].d[i].comment,
1920 caseSensitive, exactWordMatch)) { 1922 caseSensitive, exactWordMatch)) {
1921 continue; 1923 continue;
1922 } 1924 }
1923 } 1925 }
1924 if (searchIn & SEARCH_IN_URL) { 1926 if (searchIn & SEARCH_IN_URL) {
1925 if (!compareString(find.url, dti.dta[category].d[i].url, 1927 if (!compareString(find.url, dti.dta[category].d[i].url,
1926 caseSensitive, exactWordMatch)) { 1928 caseSensitive, exactWordMatch)) {
1927 continue; 1929 continue;
1928 } 1930 }
1929 } 1931 }
1930 if (searchIn & SEARCH_IN_LAUNCHER) { 1932 if (searchIn & SEARCH_IN_LAUNCHER) {
1931 if (!compareString(find.launcher, dti.dta[category].d[i].launcher, 1933 if (!compareString(find.launcher, dti.dta[category].d[i].launcher,
1932 caseSensitive, exactWordMatch)) { 1934 caseSensitive, exactWordMatch)) {
1933 continue; 1935 continue;
1934 } 1936 }
1935 } 1937 }
1936 1938
1937 // all selected "searchIn" matched. 1939 // all selected "searchIn" matched.
1938 foundPositions->push_back(i); 1940 foundPositions->push_back(i);
1939 if (breakAfterFound) 1941 if (breakAfterFound)
1940 break; 1942 break;
1941 } 1943 }
1942 1944
1943 if (sortByLvp && foundPositions->size() > 1) { 1945 if (sortByLvp && foundPositions->size() > 1) {
1944 vector< pair<unsigned int /* foundPosition (real doc pos) */, 1946 vector< pair<unsigned int /* foundPosition (real doc pos) */,
1945 unsigned int /* lvp-pos */> > tmp_vec; 1947 unsigned int /* lvp-pos */> > tmp_vec;
1946 1948
1947 unsigned int i, items = foundPositions->size(); 1949 unsigned int i, items = foundPositions->size();
1948 pair<unsigned int, unsigned int> tmp_pair; 1950 pair<unsigned int, unsigned int> tmp_pair;
1949 for (i = 0; i < items; ++i) { 1951 for (i = 0; i < items; ++i) {
1950 tmp_pair.first = (*foundPositions)[i]; 1952 tmp_pair.first = (*foundPositions)[i];
1951 tmp_pair.second = dti.dta[category].d[(*foundPositions)[i]].listViewPos; 1953 tmp_pair.second = dti.dta[category].d[(*foundPositions)[i]].listViewPos;
1952 tmp_vec.push_back(tmp_pair); 1954 tmp_vec.push_back(tmp_pair);
1953 } 1955 }
1954 sort(tmp_vec.begin(), tmp_vec.end(), dta_lvp_greater()); 1956 sort(tmp_vec.begin(), tmp_vec.end(), dta_lvp_greater());
1955 foundPositions->clear(); 1957 foundPositions->clear();
1956 for (i = 0; i < items; ++i) { 1958 for (i = 0; i < items; ++i) {
1957 foundPositions->push_back(tmp_vec[i].first); 1959 foundPositions->push_back(tmp_vec[i].first);
1958 } 1960 }
1959 } 1961 }
1960} 1962}
1961 1963
1962void PwMDoc::findEntry(const QString &category, PwMDataItem find, unsigned int searchIn, 1964void PwMDoc::findEntry(const QString &category, PwMDataItem find, unsigned int searchIn,
1963 vector<unsigned int> *foundPositions, bool breakAfterFound, 1965 vector<unsigned int> *foundPositions, bool breakAfterFound,
1964 bool caseSensitive, bool exactWordMatch, bool sortByLvp) 1966 bool caseSensitive, bool exactWordMatch, bool sortByLvp)
1965{ 1967{
1966 PWM_ASSERT(foundPositions); 1968 PWM_ASSERT(foundPositions);
1967 unsigned int cat = 0; 1969 unsigned int cat = 0;
1968 1970
1969 if (!findCategory(category, &cat)) { 1971 if (!findCategory(category, &cat)) {
1970 foundPositions->clear(); 1972 foundPositions->clear();
1971 return; 1973 return;
1972 } 1974 }
1973 1975
1974 findEntry(cat, find, searchIn, foundPositions, breakAfterFound, 1976 findEntry(cat, find, searchIn, foundPositions, breakAfterFound,
1975 caseSensitive, exactWordMatch, sortByLvp); 1977 caseSensitive, exactWordMatch, sortByLvp);
1976} 1978}
1977 1979
1978bool PwMDoc::compareString(const string &s1, const string &s2, bool caseSensitive, 1980bool PwMDoc::compareString(const string &s1, const string &s2, bool caseSensitive,
1979 bool exactWordMatch) 1981 bool exactWordMatch)
1980{ 1982{
1981 QString _s1(s1.c_str()); 1983 QString _s1(s1.c_str());
1982 QString _s2(s2.c_str()); 1984 QString _s2(s2.c_str());
1983 if (!caseSensitive) { 1985 if (!caseSensitive) {
1984 _s1 = _s1.lower(); 1986 _s1 = _s1.lower();
1985 _s2 = _s2.lower(); 1987 _s2 = _s2.lower();
1986 } 1988 }
1987 if (exactWordMatch ? (_s1 == _s2) : (_s2.find(_s1) != -1)) 1989 if (exactWordMatch ? (_s1 == _s2) : (_s2.find(_s1) != -1))
1988 return true; 1990 return true;
1989 return false; 1991 return false;
1990} 1992}
1991 1993
1992bool PwMDoc::findCategory(const QString &name, unsigned int *index) 1994bool PwMDoc::findCategory(const QString &name, unsigned int *index)
1993{ 1995{
1994 vector<PwMCategoryItem>::iterator i = dti.dta.begin(), 1996 vector<PwMCategoryItem>::iterator i = dti.dta.begin(),
1995 end = dti.dta.end(); 1997 end = dti.dta.end();
1996 while (i != end) { 1998 while (i != end) {
1997 if ((*i).name == name.latin1()) { 1999 if ((*i).name == name.latin1()) {
1998 if (index) { 2000 if (index) {
1999 *index = i - dti.dta.begin(); 2001 *index = i - dti.dta.begin();
2000 } 2002 }
2001 return true; 2003 return true;
2002 } 2004 }
2003 ++i; 2005 ++i;
2004 } 2006 }
2005 return false; 2007 return false;
2006} 2008}
2007 2009
2008bool PwMDoc::renameCategory(const QString &category, const QString &newName) 2010bool PwMDoc::renameCategory(const QString &category, const QString &newName)
2009{ 2011{
2010 unsigned int cat = 0; 2012 unsigned int cat = 0;
2011 2013