kpilot/lib

pilotSerialDatabase.cc

00001 /* KPilot
00002 **
00003 ** Copyright (C) 1998-2001 by Dan Pilone
00004 ** Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
00005 **
00006 ** Databases approached through DLP / Pilot-link look different,
00007 ** so this file defines an API for them.
00008 */
00009 
00010 /*
00011 ** This program is free software; you can redistribute it and/or modify
00012 ** it under the terms of the GNU Lesser General Public License as published by
00013 ** the Free Software Foundation; either version 2.1 of the License, or
00014 ** (at your option) any later version.
00015 **
00016 ** This program is distributed in the hope that it will be useful,
00017 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00019 ** GNU Lesser General Public License for more details.
00020 **
00021 ** You should have received a copy of the GNU Lesser General Public License
00022 ** along with this program in a file called COPYING; if not, write to
00023 ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00024 ** MA 02110-1301, USA.
00025 */
00026 
00027 /*
00028 ** Bug reports and questions can be sent to kde-pim@kde.org
00029 */
00030 #include <config.h>
00031 #include "options.h"
00032 #include "fakes.h"
00033 
00034 #include <time.h>
00035 #include <iostream>
00036 
00037 #include <pi-dlp.h>
00038 
00039 #include <qfile.h>
00040 
00041 #include <klocale.h>
00042 #include <kdebug.h>
00043 #include <kglobal.h>
00044 
00045 #include "pilotRecord.h"
00046 #include "pilotSerialDatabase.h"
00047 #include "kpilotdevicelink.h"
00048 
00049 PilotSerialDatabase::PilotSerialDatabase(KPilotDeviceLink *l,
00050     const QString &dbName) :
00051     PilotDatabase(dbName),
00052     fDBName(QString::null),
00053     fDBHandle(-1),
00054     fDBSocket(l->pilotSocket())
00055 {
00056     FUNCTIONSETUP;
00057     fDBName = dbName;
00058 
00059     openDatabase();
00060 
00061 }
00062 
00063 PilotSerialDatabase::~PilotSerialDatabase()
00064 {
00065     FUNCTIONSETUP;
00066     closeDatabase();
00067 }
00068 
00069 QString PilotSerialDatabase::dbPathName() const
00070 {
00071     QString s = CSL1("Pilot:");
00072     s.append(fDBName);
00073     return s;
00074 }
00075 
00076 // Reads the application block info
00077 int PilotSerialDatabase::readAppBlock(unsigned char *buffer, int maxLen)
00078 {
00079     FUNCTIONSETUP;
00080     if (!isOpen())
00081     {
00082         kdError() << k_funcinfo << ": DB not open" << endl;
00083         return -1;
00084     }
00085     pi_buffer_t *buf = pi_buffer_new(maxLen);
00086     int r = dlp_ReadAppBlock(fDBSocket, getDBHandle(), 0 /* offset */, maxLen, buf);
00087     if (r>=0)
00088     {
00089         memcpy(buffer, buf->data, KMAX(maxLen, r));
00090     }
00091     pi_buffer_free(buf);
00092     return r;
00093 }
00094 
00095 // Writes the application block info.
00096 int PilotSerialDatabase::writeAppBlock(unsigned char *buffer, int len)
00097 {
00098     FUNCTIONSETUP;
00099     if (!isOpen())
00100     {
00101         kdError() << k_funcinfo << ": DB not open" << endl;
00102         return -1;
00103     }
00104     return dlp_WriteAppBlock(fDBSocket, getDBHandle(), buffer, len);
00105 }
00106 
00107     // returns the number of records in the database
00108 int PilotSerialDatabase::recordCount()
00109 {
00110     int idlen;
00111     // dlp_ReadOpenDBInfo returns the number of bytes read and sets idlen to the # of recs
00112     if (isOpen() && dlp_ReadOpenDBInfo(fDBSocket, getDBHandle(), &idlen)>0)
00113     {
00114         return idlen;
00115     }
00116     else return -1;
00117 }
00118 
00119 
00120 // Returns a QValueList of all record ids in the database.
00121 QValueList<recordid_t> PilotSerialDatabase::idList()
00122 {
00123     QValueList<recordid_t> idlist;
00124     int idlen=recordCount();
00125     if (idlen<=0) return idlist;
00126 
00127     recordid_t *idarr=new recordid_t[idlen];
00128     int idlenread;
00129     int r = dlp_ReadRecordIDList (fDBSocket, getDBHandle(), 0, 0, idlen, idarr, &idlenread);
00130 
00131     if ( (r<0) || (idlenread<1) )
00132     {
00133         kdWarning() << k_funcinfo << ": Failed to read ID list from database." << endl;
00134         return idlist;
00135     }
00136 
00137     // now create the QValue list from the idarr:
00138     for (idlen=0; idlen<idlenread; idlen++)
00139     {
00140         idlist.append(idarr[idlen]);
00141     }
00142     delete[] idarr;
00143     return idlist;
00144 }
00145 
00146 
00147 // Reads a record from database by id, returns record length
00148 PilotRecord *PilotSerialDatabase::readRecordById(recordid_t id)
00149 {
00150     FUNCTIONSETUPL(3);
00151     int index, attr, category;
00152 
00153     if (!isOpen())
00154     {
00155         kdError() << k_funcinfo << ": DB not open" << endl;
00156         return 0L;
00157     }
00158     if (id>0xFFFFFF)
00159     {
00160         kdError() << k_funcinfo <<  " Encountered an invalid record id "
00161             <<id<<endl;;
00162         return 0L;
00163     }
00164     pi_buffer_t *b = pi_buffer_new(InitialBufferSize);
00165     if (dlp_ReadRecordById(fDBSocket,getDBHandle(),id,b,&index,&attr,&category) >= 0)
00166     {
00167         return new PilotRecord(b, attr, category, id);
00168     }
00169     return 0L;
00170 }
00171 
00172 // Reads a record from database, returns the record length
00173 PilotRecord *PilotSerialDatabase::readRecordByIndex(int index)
00174 {
00175     FUNCTIONSETUPL(3);
00176 
00177     if (!isOpen())
00178     {
00179         kdError() << k_funcinfo << ": DB not open" << endl;
00180         return 0L;
00181     }
00182 
00183     int attr, category;
00184     recordid_t id;
00185     PilotRecord *rec = 0L;
00186 
00187     pi_buffer_t *b = pi_buffer_new(InitialBufferSize);
00188     if (dlp_ReadRecordByIndex(fDBSocket, getDBHandle(), index,
00189         b, &id, &attr, &category) >= 0)
00190     {
00191         rec = new PilotRecord(b, attr, category, id);
00192     }
00193 
00194 
00195     return rec;
00196 }
00197 
00198 // Reads the next record from database in category 'category'
00199 PilotRecord *PilotSerialDatabase::readNextRecInCategory(int category)
00200 {
00201     FUNCTIONSETUP;
00202     int index, attr;
00203     recordid_t id;
00204 
00205     if (!isOpen())
00206     {
00207         kdError() << k_funcinfo << ": DB not open" << endl;
00208         return 0L;
00209     }
00210     pi_buffer_t *b = pi_buffer_new(InitialBufferSize);
00211     if (dlp_ReadNextRecInCategory(fDBSocket, getDBHandle(),
00212         category,b,&id,&index,&attr) >= 0)
00213         return new PilotRecord(b, attr, category, id);
00214     return 0L;
00215 }
00216 
00217 // Reads the next record from database that has the dirty flag set.
00218 PilotRecord *PilotSerialDatabase::readNextModifiedRec(int *ind)
00219 {
00220     FUNCTIONSETUP;
00221     int index, attr, category;
00222     recordid_t id;
00223 
00224     if (!isOpen())
00225     {
00226         kdError() << k_funcinfo << ": DB not open" << endl;
00227         return 0L;
00228     }
00229     pi_buffer_t *b = pi_buffer_new(InitialBufferSize);
00230     if (dlp_ReadNextModifiedRec(fDBSocket, getDBHandle(), b, &id, &index, &attr, &category) >= 0)
00231     {
00232         if (ind) *ind=index;
00233         return new PilotRecord(b, attr, category, id);
00234     }
00235     return 0L;
00236 }
00237 
00238 // Writes a new record to database (if 'id' == 0 or id>0xFFFFFF, one will be assigned and returned in 'newid')
00239 recordid_t PilotSerialDatabase::writeRecord(PilotRecord * newRecord)
00240 {
00241     FUNCTIONSETUP;
00242     recordid_t newid;
00243     int success;
00244 
00245     if (!isOpen())
00246     {
00247         kdError() << k_funcinfo << ": DB not open" << endl;
00248         return 0;
00249     }
00250     // Do some sanity checking to prevent invalid UniqueIDs from being written
00251     // to the handheld (RecordIDs are only 3 bytes!!!). Under normal conditions
00252     // this check should never yield true, so write out an error to indicate
00253     // someone messed up full time...
00254     if (newRecord->id()>0xFFFFFF)
00255     {
00256         kdError() << k_funcinfo << "Encountered an invalid record id "
00257             <<newRecord->id()<<", resetting it to zero.";
00258         newRecord->setID(0);
00259     }
00260     success =
00261         dlp_WriteRecord(fDBSocket, getDBHandle(),
00262         newRecord->attributes(), newRecord->id(),
00263         newRecord->category(), newRecord->data(),
00264         newRecord->size(), &newid);
00265     if ( (newRecord->id() != newid) && (newid!=0) )
00266         newRecord->setID(newid);
00267     return newid;
00268 }
00269 
00270 // 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
00271 int PilotSerialDatabase::deleteRecord(recordid_t id, bool all)
00272 {
00273     FUNCTIONSETUP;
00274     if (!isOpen())
00275     {
00276         kdError() << k_funcinfo <<": DB not open"<<endl;
00277         return -1;
00278     }
00279     return dlp_DeleteRecord(fDBSocket, getDBHandle(), all?1:0, id);
00280 }
00281 
00282 
00283 // Resets all records in the database to not dirty.
00284 int PilotSerialDatabase::resetSyncFlags()
00285 {
00286     FUNCTIONSETUP;
00287     if (!isOpen())
00288     {
00289         kdError() << k_funcinfo << ": DB not open" << endl;
00290         return -1;
00291     }
00292     return dlp_ResetSyncFlags(fDBSocket, getDBHandle());
00293 }
00294 
00295 // Resets next record index to beginning
00296 int PilotSerialDatabase::resetDBIndex()
00297 {
00298     FUNCTIONSETUP;
00299     if (!isOpen())
00300     {
00301         kdError() << k_funcinfo << ": DB not open" << endl;
00302         return -1;
00303     }
00304     return dlp_ResetDBIndex(fDBSocket, getDBHandle());
00305 }
00306 
00307 // Purges all Archived/Deleted records from Palm Pilot database
00308 int PilotSerialDatabase::cleanup()
00309 {
00310     FUNCTIONSETUP;
00311     if (!isOpen())
00312     {
00313         kdError() << k_funcinfo << ": DB not open" << endl;
00314         return -1;
00315     }
00316     return dlp_CleanUpDatabase(fDBSocket, getDBHandle());
00317 }
00318 
00319 void PilotSerialDatabase::openDatabase()
00320 {
00321     FUNCTIONSETUP;
00322     int db;
00323 
00324     setDBOpen(false);
00325 
00326     QString s = getDBName();
00327     if (s.isEmpty())
00328     {
00329         kdError() << k_funcinfo << ": Bad DB name, "
00330             << (s.isNull() ? "null" : "empty")
00331             << " string given."
00332             << endl;
00333         return;
00334     }
00335 
00336     QCString encodedName = QFile::encodeName(s);
00337     if (encodedName.isEmpty())
00338     {
00339         kdError() << k_funcinfo << ": Bad DB name, "
00340             << (encodedName.isNull() ? "null" : "empty")
00341             << " string given."
00342             << endl;
00343         return;
00344     }
00345 
00346     char encodedNameBuffer[PATH_MAX];
00347     strlcpy(encodedNameBuffer,(const char *)encodedName,PATH_MAX);
00348 
00349     if (dlp_OpenDB(fDBSocket, 0, dlpOpenReadWrite,
00350         encodedNameBuffer, &db) < 0)
00351     {
00352         kdError() << k_funcinfo
00353             << i18n("Cannot open database")
00354             << i18n("Pilot database error") << endl;
00355         return;
00356     }
00357     setDBHandle(db);
00358     setDBOpen(true);
00359 }
00360 
00361 bool PilotSerialDatabase::createDatabase(long creator, long type, int cardno, int flags, int version)
00362 {
00363     FUNCTIONSETUP;
00364     int db;
00365 
00366     // 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)
00367     if (isOpen()) return true;
00368     // The latin1 seems ok, database names are latin1.
00369     int res=dlp_CreateDB(fDBSocket,
00370         creator, type, cardno, flags, version,
00371         Pilot::toPilot(getDBName()), &db);
00372     if (res<0) {
00373         kdError() <<k_funcinfo
00374             << i18n("Cannot create database %1 on the handheld").arg(getDBName())<<endl;
00375         return false;
00376     }
00377     // TODO: Do I have to open it explicitly???
00378     setDBHandle(db);
00379     setDBOpen(true);
00380     return true;
00381 }
00382 
00383 void PilotSerialDatabase::closeDatabase()
00384 {
00385     FUNCTIONSETUP;
00386     if (!isOpen() ) return;
00387 
00388     dlp_CloseDB(fDBSocket, getDBHandle());
00389     setDBOpen(false);
00390 }
00391 
00392 int PilotSerialDatabase::deleteDatabase()
00393 {
00394     FUNCTIONSETUP;
00395 
00396     if (isOpen()) closeDatabase();
00397 
00398     return dlp_DeleteDB(fDBSocket, 0, Pilot::toPilot(fDBName));
00399 }
00400 
00401 
00402 
00403 /* virtual */ PilotDatabase::DBType PilotSerialDatabase::dbType() const
00404 {
00405     return eSerialDB;
00406 }
00407 
KDE Home | KDE Accessibility Home | Description of Access Keys