diff options
Diffstat (limited to 'kpilot/lib/pilotSerialDatabase.cc')
-rw-r--r-- | kpilot/lib/pilotSerialDatabase.cc | 432 |
1 files changed, 432 insertions, 0 deletions
diff --git a/kpilot/lib/pilotSerialDatabase.cc b/kpilot/lib/pilotSerialDatabase.cc new file mode 100644 index 000000000..a38898d1d --- /dev/null +++ b/kpilot/lib/pilotSerialDatabase.cc @@ -0,0 +1,432 @@ +/* KPilot +** +** Copyright (C) 1998-2001 by Dan Pilone +** Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com> +** +** Databases approached through DLP / Pilot-link look different, +** so this file defines an API for them. +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU Lesser General Public License as published by +** the Free Software Foundation; either version 2.1 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public License +** along with this program in a file called COPYING; if not, write to +** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +** MA 02110-1301, USA. +*/ + +/* +** Bug reports and questions can be sent to kde-pim@kde.org +*/ +#include "options.h" + +#include <time.h> +#include <iostream> + +#include <pi-dlp.h> + +#include <qfile.h> + +#include <klocale.h> +#include <kdebug.h> +#include <kglobal.h> + +#include "pilotRecord.h" +#include "pilotSerialDatabase.h" +#include "kpilotdevicelink.h" + +PilotSerialDatabase::PilotSerialDatabase(KPilotDeviceLink *l, + const QString &dbName) : + PilotDatabase(dbName), + fDBName( dbName ), + fDBHandle(-1), + fDBSocket(l->pilotSocket()) +{ + FUNCTIONSETUP; + openDatabase(); +} + +PilotSerialDatabase::PilotSerialDatabase( KPilotDeviceLink *l, const DBInfo *info ) : + PilotDatabase( info ? Pilot::fromPilot( info->name ) : QString::null ), + fDBName( QString::null ), + fDBHandle( -1 ), + fDBSocket( l->pilotSocket() ) +{ + // Rather unclear why both the base class and this one have separate names. + fDBName = name(); + setDBOpen(false); + if (fDBName.isEmpty() || !info) + { + WARNINGKPILOT << "Bad database name requested." << endl; + return; + } + + int db; + if (dlp_OpenDB(fDBSocket, 0, dlpOpenReadWrite, info->name, &db) < 0) + { + WARNINGKPILOT << "Cannot open database on handheld." << endl; + return; + } + setDBHandle(db); + setDBOpen(true); +} + +PilotSerialDatabase::~PilotSerialDatabase() +{ + FUNCTIONSETUP; + closeDatabase(); +} + +QString PilotSerialDatabase::dbPathName() const +{ + QString s = CSL1("Pilot:"); + s.append(fDBName); + return s; +} + +// Reads the application block info +int PilotSerialDatabase::readAppBlock(unsigned char *buffer, int maxLen) +{ + FUNCTIONSETUP; + if (!isOpen()) + { + WARNINGKPILOT << "DB not open" << endl; + return -1; + } + pi_buffer_t *buf = pi_buffer_new(maxLen); + int r = dlp_ReadAppBlock(fDBSocket, getDBHandle(), 0 /* offset */, maxLen, buf); + if (r>=0) + { + memcpy(buffer, buf->data, KMAX(maxLen, r)); + } + pi_buffer_free(buf); + return r; +} + +// Writes the application block info. +int PilotSerialDatabase::writeAppBlock(unsigned char *buffer, int len) +{ + FUNCTIONSETUP; + if (!isOpen()) + { + WARNINGKPILOT << "DB not open" << endl; + return -1; + } + return dlp_WriteAppBlock(fDBSocket, getDBHandle(), buffer, len); +} + + // returns the number of records in the database +unsigned int PilotSerialDatabase::recordCount() const +{ + int idlen; + // dlp_ReadOpenDBInfo returns the number of bytes read and sets idlen to the # of recs + if (isOpen() && dlp_ReadOpenDBInfo(fDBSocket, getDBHandle(), &idlen)>0) + { + return idlen; + } + else + { + return 0; + } +} + + +// Returns a QValueList of all record ids in the database. +QValueList<recordid_t> PilotSerialDatabase::idList() +{ + QValueList<recordid_t> idlist; + int idlen=recordCount(); + if (idlen<=0) return idlist; + + recordid_t *idarr=new recordid_t[idlen]; + int idlenread; + int r = dlp_ReadRecordIDList (fDBSocket, getDBHandle(), 0, 0, idlen, idarr, &idlenread); + + if ( (r<0) || (idlenread<1) ) + { + WARNINGKPILOT << "Failed to read ID list from database." << endl; + return idlist; + } + + // now create the QValue list from the idarr: + for (idlen=0; idlen<idlenread; idlen++) + { + idlist.append(idarr[idlen]); + } + delete[] idarr; + return idlist; +} + + +// Reads a record from database by id, returns record length +PilotRecord *PilotSerialDatabase::readRecordById(recordid_t id) +{ + FUNCTIONSETUPL(3); + int index, attr, category; + + if (!isOpen()) + { + WARNINGKPILOT << "DB not open" << endl; + return 0L; + } + if (id>0xFFFFFF) + { + WARNINGKPILOT << "Encountered an invalid record id " + << id << endl; + return 0L; + } + pi_buffer_t *b = pi_buffer_new(InitialBufferSize); + if (dlp_ReadRecordById(fDBSocket,getDBHandle(),id,b,&index,&attr,&category) >= 0) + { + return new PilotRecord(b, attr, category, id); + } + return 0L; +} + +// Reads a record from database, returns the record length +PilotRecord *PilotSerialDatabase::readRecordByIndex(int index) +{ + FUNCTIONSETUPL(3); + + if (!isOpen()) + { + WARNINGKPILOT << "DB not open" << endl; + return 0L; + } + + int attr, category; + recordid_t id; + PilotRecord *rec = 0L; + + pi_buffer_t *b = pi_buffer_new(InitialBufferSize); + if (dlp_ReadRecordByIndex(fDBSocket, getDBHandle(), index, + b, &id, &attr, &category) >= 0) + { + rec = new PilotRecord(b, attr, category, id); + } + + + return rec; +} + +// Reads the next record from database in category 'category' +PilotRecord *PilotSerialDatabase::readNextRecInCategory(int category) +{ + FUNCTIONSETUP; + int index, attr; + recordid_t id; + + if (!isOpen()) + { + WARNINGKPILOT << "DB not open" << endl; + return 0L; + } + pi_buffer_t *b = pi_buffer_new(InitialBufferSize); + if (dlp_ReadNextRecInCategory(fDBSocket, getDBHandle(), + category,b,&id,&index,&attr) >= 0) + return new PilotRecord(b, attr, category, id); + return 0L; +} + +// Reads the next record from database that has the dirty flag set. +PilotRecord *PilotSerialDatabase::readNextModifiedRec(int *ind) +{ + FUNCTIONSETUP; + int index, attr, category; + recordid_t id; + + if (!isOpen()) + { + WARNINGKPILOT << "DB not open" << endl; + return 0L; + } + pi_buffer_t *b = pi_buffer_new(InitialBufferSize); + if (dlp_ReadNextModifiedRec(fDBSocket, getDBHandle(), b, &id, &index, &attr, &category) >= 0) + { + if (ind) *ind=index; + return new PilotRecord(b, attr, category, id); + } + return 0L; +} + +// Writes a new record to database (if 'id' == 0 or id>0xFFFFFF, one will be assigned and returned in 'newid') +recordid_t PilotSerialDatabase::writeRecord(PilotRecord * newRecord) +{ + FUNCTIONSETUP; + recordid_t newid; + int success; + + if (!isOpen()) + { + WARNINGKPILOT << "DB not open" << endl; + return 0; + } + // Do some sanity checking to prevent invalid UniqueIDs from being written + // to the handheld (RecordIDs are only 3 bytes!!!). Under normal conditions + // this check should never yield true, so write out an error to indicate + // someone messed up full time... + if (newRecord->id()>0xFFFFFF) + { + WARNINGKPILOT << "Encountered an invalid record id " + << newRecord->id() << ", resetting it to zero." << endl; + newRecord->setID(0); + } + success = + dlp_WriteRecord(fDBSocket, getDBHandle(), + newRecord->attributes(), newRecord->id(), + newRecord->category(), newRecord->data(), + newRecord->size(), &newid); + if ( (newRecord->id() != newid) && (newid!=0) ) + newRecord->setID(newid); + return newid; +} + +// Deletes a record with the given recordid_t from the database, or all records, if all is set to true. The recordid_t will be ignored in this case +int PilotSerialDatabase::deleteRecord(recordid_t id, bool all) +{ + FUNCTIONSETUP; + if (!isOpen()) + { + WARNINGKPILOT <<"DB not open"<<endl; + return -1; + } + return dlp_DeleteRecord(fDBSocket, getDBHandle(), all?1:0, id); +} + + +// Resets all records in the database to not dirty. +int PilotSerialDatabase::resetSyncFlags() +{ + FUNCTIONSETUP; + if (!isOpen()) + { + WARNINGKPILOT << "DB not open" << endl; + return -1; + } + return dlp_ResetSyncFlags(fDBSocket, getDBHandle()); +} + +// Resets next record index to beginning +int PilotSerialDatabase::resetDBIndex() +{ + FUNCTIONSETUP; + if (!isOpen()) + { + WARNINGKPILOT << "DB not open" << endl; + return -1; + } + return dlp_ResetDBIndex(fDBSocket, getDBHandle()); +} + +// Purges all Archived/Deleted records from Palm Pilot database +int PilotSerialDatabase::cleanup() +{ + FUNCTIONSETUP; + if (!isOpen()) + { + WARNINGKPILOT << "DB not open" << endl; + return -1; + } + return dlp_CleanUpDatabase(fDBSocket, getDBHandle()); +} + +void PilotSerialDatabase::openDatabase() +{ + FUNCTIONSETUP; + int db; + + setDBOpen(false); + + QString s = getDBName(); + if (s.isEmpty()) + { + WARNINGKPILOT << "Bad DB name, " << s << " string given." << endl; + return; + } + + QCString encodedName = QFile::encodeName(s); + if (encodedName.isEmpty()) + { + WARNINGKPILOT << "Bad DB name, " + << (encodedName.isNull() ? "null" : "empty") + << " string given." + << endl; + return; + } + + char encodedNameBuffer[PATH_MAX]; + strlcpy(encodedNameBuffer,(const char *)encodedName,PATH_MAX); + + DEBUGKPILOT << fname << ": opening database: [" + << encodedNameBuffer << "]" << endl; + + if (dlp_OpenDB(fDBSocket, 0, dlpOpenReadWrite, + encodedNameBuffer, &db) < 0) + { + WARNINGKPILOT << "Cannot open database on handheld." << endl; + return; + } + setDBHandle(db); + setDBOpen(true); +} + +bool PilotSerialDatabase::createDatabase(long creator, long type, int cardno, int flags, int version) +{ + FUNCTIONSETUP; + int db; + + // if the database is already open, we cannot create it again. How about completely resetting it? (i.e. deleting it and the createing it again) + if (isOpen()) return true; + // The latin1 seems ok, database names are latin1. + int res=dlp_CreateDB(fDBSocket, + creator, type, cardno, flags, version, + Pilot::toPilot(getDBName()), &db); + if (res<0) { + WARNINGKPILOT << "Cannot create database " << getDBName() << " on the handheld" << endl; + return false; + } + // TODO: Do I have to open it explicitly??? + setDBHandle(db); + setDBOpen(true); + return true; +} + +void PilotSerialDatabase::closeDatabase() +{ + FUNCTIONSETUP; + if (!isOpen() ) + { + return; + } + + DEBUGKPILOT << fname << ": Closing DB handle #" << getDBHandle() << endl; + dlp_CloseDB(fDBSocket, getDBHandle()); + DEBUGKPILOT << fname << ": after closing" << endl; + setDBOpen(false); +} + +int PilotSerialDatabase::deleteDatabase() +{ + FUNCTIONSETUP; + + if (isOpen()) closeDatabase(); + + return dlp_DeleteDB(fDBSocket, 0, Pilot::toPilot(fDBName)); +} + + + +/* virtual */ PilotDatabase::DBType PilotSerialDatabase::dbType() const +{ + return eSerialDB; +} + |