00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 static const char *pilotlocaldatabase_id =
00031 "$Id: pilotLocalDatabase.cc,v 1.22 2003/07/26 16:10:52 kainhofe Exp $";
00032
00033 #include "options.h"
00034
00035 #include <stdio.h>
00036 #include <unistd.h>
00037
00038 #include <iostream>
00039
00040 #include <qstring.h>
00041 #include <qfile.h>
00042 #include <qregexp.h>
00043 #include <qdatetime.h>
00044
00045 #include <kdebug.h>
00046 #include <kglobal.h>
00047 #include <kstandarddirs.h>
00048
00049 #include "pilotLocalDatabase.h"
00050
00051 PilotLocalDatabase::PilotLocalDatabase(const QString & path,
00052 const QString & dbName, bool useDefaultPath,
00053 QObject *p, const char *n) :
00054 PilotDatabase(p,n),
00055 fPathName(path),
00056 fDBName(dbName),
00057 fAppInfo(0L),
00058 fAppLen(0),
00059 fNumRecords(0),
00060 fCurrentRecord(0),
00061 fPendingRec(-1)
00062 {
00063 FUNCTIONSETUP;
00064 fixupDBName();
00065 openDatabase();
00066
00067 if (!isDBOpen() && useDefaultPath)
00068 {
00069 if (fPathBase && !fPathBase->isEmpty())
00070 {
00071 fPathName = *fPathBase;
00072 }
00073 else
00074 {
00075 fPathName = KGlobal::dirs()->saveLocation("data",
00076 CSL1("kpilot/DBBackup/"));
00077 }
00078 fixupDBName();
00079 openDatabase();
00080 if (!isDBOpen())
00081 fPathName=path;
00082 }
00083
00084
00085 (void) pilotlocaldatabase_id;
00086 }
00087
00088 PilotLocalDatabase::PilotLocalDatabase(const QString & dbName,
00089 bool useConduitDBs, QObject *p, const char *n) :
00090 PilotDatabase(p,n),
00091 fPathName(QString::null),
00092 fDBName(dbName),
00093 fAppInfo(0L),
00094 fAppLen(0),
00095 fNumRecords(0),
00096 fCurrentRecord(0),
00097 fPendingRec(-1)
00098 {
00099 FUNCTIONSETUP;
00100 if (fPathBase && !fPathBase->isEmpty() )
00101 {
00102 fPathName = *fPathBase;
00103 if (useConduitDBs)
00104 fPathName.replace(CSL1("DBBackup/"), CSL1("conduits/"));
00105 }
00106 else
00107 {
00108 fPathName = KGlobal::dirs()->saveLocation("data",
00109 CSL1("kpilot/")+(useConduitDBs?CSL1("conduits/"):CSL1("DBBackup/")));
00110 }
00111
00112 fixupDBName();
00113 openDatabase();
00114 }
00115
00116
00117 PilotLocalDatabase::~PilotLocalDatabase()
00118 {
00119 FUNCTIONSETUP;
00120 int i;
00121
00122 closeDatabase();
00123 delete[]fAppInfo;
00124 for (i = 0; i < fNumRecords; i++)
00125 {
00126 delete fRecords[i];
00127 }
00128 }
00129
00130
00131 void PilotLocalDatabase::fixupDBName()
00132 {
00133 FUNCTIONSETUP;
00134 #if QT_VERSION < 0x30100
00135 fDBName = fDBName.replace(QRegExp(CSL1("/")),CSL1("_"));
00136 #else
00137
00138
00139 fDBName = fDBName.replace('/', CSL1("_"));
00140 #endif
00141 }
00142
00143 bool PilotLocalDatabase::createDatabase(long creator, long type, int, int flags, int version)
00144 {
00145 FUNCTIONSETUP;
00146
00147
00148 if (isDBOpen()) {
00149 #ifdef DEBUG
00150 DEBUGCONDUIT<<"Database "<<fDBName<<" already open. Cannot recreate it."<<endl;
00151 #endif
00152 return true;
00153 }
00154
00155 #ifdef DEBUG
00156 DEBUGCONDUIT<<"Creating database "<<fDBName<<endl;
00157 #endif
00158
00159
00160 memcpy(&fDBInfo.name[0], fDBName.latin1(), 34*sizeof(char));
00161 fDBInfo.creator=creator;
00162 fDBInfo.type=type;
00163 fDBInfo.more=0;
00164 fDBInfo.flags=flags;
00165 fDBInfo.miscFlags=0;
00166 fDBInfo.version=version;
00167 fDBInfo.modnum=0;
00168 fDBInfo.index=0;
00169 fDBInfo.createDate=(QDateTime::currentDateTime()).toTime_t();
00170 fDBInfo.modifyDate=(QDateTime::currentDateTime()).toTime_t();
00171 fDBInfo.backupDate=(QDateTime::currentDateTime()).toTime_t();
00172
00173 delete[] fAppInfo;
00174 fAppInfo=0L;
00175 fAppLen=0;
00176
00177 for (int i=0; i<fNumRecords; i++) {
00178 KPILOT_DELETE(fRecords[i]);
00179 fRecords[i]=NULL;
00180 }
00181 fNumRecords=0;
00182 fCurrentRecord=0;
00183 fPendingRec=0;
00184
00185
00186 setDBOpen(true);
00187 return true;
00188 }
00189
00190 int PilotLocalDatabase::deleteDatabase()
00191 {
00192 FUNCTIONSETUP;
00193 if (isDBOpen()) closeDatabase();
00194
00195 QString dbpath=dbPathName();
00196 QFile fl(dbpath);
00197 if (QFile::remove(dbPathName()))
00198 return 0;
00199 else
00200 return -1;
00201 }
00202
00203
00204
00205
00206 int PilotLocalDatabase::readAppBlock(unsigned char *buffer, int)
00207 {
00208 FUNCTIONSETUP;
00209
00210 if (!isDBOpen())
00211 {
00212 kdError() << k_funcinfo << ": DB not open!" << endl;
00213 return -1;
00214 }
00215
00216 memcpy((void *) buffer, fAppInfo, fAppLen);
00217 return fAppLen;
00218 }
00219
00220 int PilotLocalDatabase::writeAppBlock(unsigned char *buffer, int len)
00221 {
00222 FUNCTIONSETUP;
00223
00224 if (isDBOpen() == false)
00225 {
00226 kdError() << k_funcinfo << ": DB not open!" << endl;
00227 return -1;
00228 }
00229 delete[]fAppInfo;
00230 fAppLen = len;
00231 fAppInfo = new char[fAppLen];
00232
00233 memcpy(fAppInfo, (void *) buffer, fAppLen);
00234 return 0;
00235 }
00236
00237
00238
00239 int PilotLocalDatabase::recordCount()
00240 {
00241 return fNumRecords;
00242 }
00243
00244
00245
00246 QValueList<recordid_t> PilotLocalDatabase::idList()
00247 {
00248 int idlen=recordCount();
00249 QValueList<recordid_t> idlist;
00250 if (idlen<=0) return idlist;
00251
00252
00253 for (int id=0; id<idlen; id++)
00254 {
00255 idlist.append(fRecords[id]->getID());
00256 }
00257 return idlist;
00258 }
00259
00260
00261 PilotRecord *PilotLocalDatabase::readRecordById(recordid_t id)
00262 {
00263 FUNCTIONSETUP;
00264
00265 int i;
00266
00267 fPendingRec = -1;
00268 if (isDBOpen() == false)
00269 {
00270 DEBUGKPILOT << fDBName << ": DB not open!" << endl;
00271 return 0L;
00272 }
00273 for (i = 0; i < fNumRecords; i++)
00274 {
00275 if (fRecords[i]->getID() == id)
00276 {
00277 PilotRecord *newRecord = new PilotRecord(fRecords[i]);
00278
00279 return newRecord;
00280 }
00281 }
00282 return 0L;
00283 }
00284
00285
00286 PilotRecord *PilotLocalDatabase::readRecordByIndex(int index)
00287 {
00288 FUNCTIONSETUP;
00289 fPendingRec = (-1);
00290 if (isDBOpen() == false)
00291 {
00292 kdError() << k_funcinfo << ": DB not open!" << endl;
00293 return 0L;
00294 }
00295 if (index >= fNumRecords)
00296 return 0L;
00297 PilotRecord *newRecord = new PilotRecord(fRecords[index]);
00298
00299 return newRecord;
00300 }
00301
00302
00303 PilotRecord *PilotLocalDatabase::readNextRecInCategory(int category)
00304 {
00305 FUNCTIONSETUP;
00306 fPendingRec = -1;
00307 if (isDBOpen() == false)
00308 {
00309 kdError() << k_funcinfo << ": DB not open!" << endl;
00310 return 0L;
00311 }
00312 while ((fCurrentRecord < fNumRecords)
00313 && (fRecords[fCurrentRecord]->getCat() != category))
00314 {
00315 fCurrentRecord++;
00316 }
00317 if (fCurrentRecord == fNumRecords)
00318 return 0L;
00319 PilotRecord *newRecord = new PilotRecord(fRecords[fCurrentRecord]);
00320
00321 fCurrentRecord++;
00322 return newRecord;
00323 }
00324
00325
00326 PilotRecord *PilotLocalDatabase::readNextModifiedRec(int *ind)
00327 {
00328 FUNCTIONSETUP;
00329
00330 if (isDBOpen() == false)
00331 {
00332 kdError() << k_funcinfo << ": DB not open!" << endl;
00333 return 0L;
00334 }
00335
00336 while ((fCurrentRecord < fNumRecords)
00337 && !(fRecords[fCurrentRecord]->getAttrib() & dlpRecAttrDirty) && (fRecords[fCurrentRecord]->getID()>0 ))
00338 {
00339 fCurrentRecord++;
00340 }
00341 if (fCurrentRecord == fNumRecords)
00342 return 0L;
00343 PilotRecord *newRecord = new PilotRecord(fRecords[fCurrentRecord]);
00344 if (ind) *ind=fCurrentRecord;
00345
00346 fPendingRec = fCurrentRecord;
00347 fCurrentRecord++;
00348 return newRecord;
00349 }
00350
00351
00352 recordid_t PilotLocalDatabase::writeID(PilotRecord * rec)
00353 {
00354 FUNCTIONSETUP;
00355
00356 if (isDBOpen() == false)
00357 {
00358 kdError() << k_funcinfo << ": DB not open!" << endl;
00359 return 0;
00360 }
00361 if (fPendingRec == -1)
00362 {
00363 kdError() << k_funcinfo <<
00364 ": Last call was _NOT_ readNextModifiedRec()" << endl;
00365 return 0;
00366 }
00367 fRecords[fPendingRec]->setID(rec->getID());
00368 fPendingRec = -1;
00369 return rec->getID();
00370 }
00371
00372
00373 recordid_t PilotLocalDatabase::writeRecord(PilotRecord * newRecord)
00374 {
00375 FUNCTIONSETUP;
00376 int i;
00377
00378 fPendingRec = -1;
00379 if (isDBOpen() == false)
00380 {
00381 kdError() << k_funcinfo << ": DB not open!" << endl;
00382 return 0;
00383 }
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399 newRecord->setAttrib(newRecord->getAttrib() | dlpRecAttrDirty);
00400
00401
00402 if (newRecord->getID() != 0)
00403 {
00404 for (i = 0; i < fNumRecords; i++)
00405 if (fRecords[i]->getID() == newRecord->getID())
00406 {
00407 delete fRecords[i];
00408
00409 fRecords[i] = new PilotRecord(newRecord);
00410 return 0;
00411 }
00412 }
00413
00414 fRecords[fNumRecords++] = new PilotRecord(newRecord);
00415 return newRecord->getID();
00416 }
00417
00418
00419 int PilotLocalDatabase::deleteRecord(recordid_t id, bool all)
00420 {
00421 FUNCTIONSETUP;
00422 if (isDBOpen() == false)
00423 {
00424 kdError() << k_funcinfo <<": DB not open"<<endl;
00425 return -1;
00426 }
00427 if (all)
00428 {
00429 for (int i=0; i<fNumRecords; i++)
00430 {
00431 delete fRecords[i];
00432 fRecords[i]=0L;
00433 }
00434 fNumRecords=0;
00435 fCurrentRecord=0;
00436 fPendingRec=0;
00437 return 0;
00438 }
00439 else
00440 {
00441 int i=0;
00442 while ( (i<fNumRecords) && (fRecords[i]) && (fRecords[i]->getID()!=id) )
00443 i++;
00444 if ( (i<fNumRecords) && (fRecords[i]) && (fRecords[i]->getID() == id) )
00445 {
00446 delete fRecords[i];
00447 for (int j=i+1; j<fNumRecords; j++)
00448 {
00449 fRecords[j-1]=fRecords[j];
00450 }
00451 fNumRecords--;
00452 }
00453 else
00454 {
00455
00456 return -1;
00457 }
00458 }
00459 return 0;
00460 }
00461
00462
00463
00464 int PilotLocalDatabase::resetSyncFlags()
00465 {
00466 FUNCTIONSETUP;
00467
00468 int i;
00469
00470 fPendingRec = -1;
00471 if (isDBOpen() == false)
00472 {
00473 kdError() << k_funcinfo << ": DB not open!" << endl;
00474 return -1;
00475 }
00476 for (i = 0; i < fNumRecords; i++)
00477 fRecords[i]->setAttrib(fRecords[i]->
00478 getAttrib() & ~dlpRecAttrDirty);
00479 return 0;
00480 }
00481
00482
00483 int PilotLocalDatabase::resetDBIndex()
00484 {
00485 FUNCTIONSETUP;
00486 fPendingRec = -1;
00487 if (isDBOpen() == false)
00488 {
00489 kdError() << k_funcinfo << ": DB not open!" << endl;
00490 return -1;
00491 }
00492 fCurrentRecord = 0;
00493 return 0;
00494 }
00495
00496
00497 int PilotLocalDatabase::cleanup()
00498 {
00499 FUNCTIONSETUP;
00500 fPendingRec = -1;
00501 if (isDBOpen() == false)
00502 {
00503 kdError() << k_funcinfo << ": DB not open!" << endl;
00504 return -1;
00505 }
00506 int i, j;
00507
00508 for (i = 0; (i < fNumRecords) && (fRecords[i]);)
00509 if (fRecords[i]->getAttrib() & (dlpRecAttrDeleted|dlpRecAttrArchived))
00510 {
00511 delete fRecords[i];
00512
00513 if ((i + 1) < fNumRecords)
00514 for (j = i + 1; j < fNumRecords; j++)
00515 fRecords[j - 1] = fRecords[j];
00516 else
00517 fRecords[i] = 0L;
00518 fNumRecords--;
00519 }
00520 else
00521 i++;
00522
00523
00524
00525 return 0;
00526 }
00527
00528 QString PilotLocalDatabase::dbPathName() const
00529 {
00530 FUNCTIONSETUP;
00531 QString tempName(fPathName);
00532 QString slash = CSL1("/");
00533
00534 if (!tempName.endsWith(slash)) tempName += slash;
00535 tempName += getDBName();
00536 tempName += CSL1(".pdb");
00537 return tempName;
00538 }
00539
00540 void PilotLocalDatabase::openDatabase()
00541 {
00542 FUNCTIONSETUP;
00543
00544 void *tmpBuffer;
00545 pi_file *dbFile;
00546 int size, attr, cat;
00547 pi_uid_t id;
00548
00549 QString tempName = dbPathName();
00550 QCString fileName = QFile::encodeName(tempName);
00551 dbFile = pi_file_open(const_cast < char *>((const char *) fileName));
00552
00553 if (dbFile == 0L)
00554 {
00555 kdError() << k_funcinfo
00556 << ": Failed to open " << tempName << endl;
00557 return;
00558 }
00559 pi_file_get_info(dbFile, &fDBInfo);
00560 pi_file_get_app_info(dbFile, &tmpBuffer, &fAppLen);
00561 fAppInfo = new char[fAppLen];
00562
00563 memcpy(fAppInfo, tmpBuffer, fAppLen);
00564 while (pi_file_read_record(dbFile, fCurrentRecord,
00565 &tmpBuffer, &size, &attr, &cat, &id) == 0)
00566 {
00567 fRecords[fCurrentRecord] =
00568 new PilotRecord(tmpBuffer, size, attr, cat, id);
00569 fCurrentRecord++;
00570 }
00571 pi_file_close(dbFile);
00572 fNumRecords = fCurrentRecord;
00573 fCurrentRecord = 0;
00574 setDBOpen(true);
00575 }
00576
00577 void PilotLocalDatabase::closeDatabase()
00578 {
00579 FUNCTIONSETUP;
00580 pi_file *dbFile;
00581 int i;
00582
00583 if (isDBOpen() == false)
00584 {
00585 #ifdef DEBUG
00586 DEBUGCONDUIT<<"Database "<<fDBName<<" is not open. Cannot close and write it"<<endl;
00587 #endif
00588 return;
00589 }
00590
00591 QString tempName_ = dbPathName();
00592 QString newName_ = tempName_ + CSL1(".bak");
00593 QCString tempName = QFile::encodeName(tempName_);
00594 QCString newName = QFile::encodeName(newName_);
00595
00596 dbFile = pi_file_create(const_cast < char *>((const char *)newName),
00597 &fDBInfo);
00598 #ifdef DEBUG
00599 DEBUGCONDUIT<<"Created temp file "<<newName<<" for the database file "<<dbPathName()<<endl;
00600 #endif
00601
00602 pi_file_set_app_info(dbFile, fAppInfo, fAppLen);
00603 for (i = 0; i < fNumRecords; i++)
00604 {
00605 pi_file_append_record(dbFile,
00606 fRecords[i]->getData(),
00607 fRecords[i]->getLen(),
00608 fRecords[i]->getAttrib(), fRecords[i]->getCat(),
00609 fRecords[i]->getID());
00610 }
00611
00612 pi_file_close(dbFile);
00613 unlink((const char *) QFile::encodeName(tempName));
00614 rename((const char *) QFile::encodeName(newName),
00615 (const char *) QFile::encodeName(tempName));
00616 setDBOpen(false);
00617 }
00618
00619
00620 QString *PilotLocalDatabase::fPathBase = 0L;
00621
00622 void PilotLocalDatabase::setDBPath(const QString &s)
00623 {
00624 FUNCTIONSETUP;
00625
00626 #ifdef DEBUG
00627 DEBUGDAEMON << fname
00628 << ": Setting default DB path to "
00629 << s
00630 << endl;
00631 #endif
00632
00633 if (!fPathBase)
00634 {
00635 fPathBase = new QString(s);
00636 }
00637 else
00638 {
00639 *fPathBase = s;
00640 }
00641 }