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