kpilot

kpilotlocallink.cc

Go to the documentation of this file.
00001 /* KPilot
00002 **
00003 ** Copyright (C) 1998-2001 by Dan Pilone
00004 ** Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
00005 ** Copyright (C) 2006-2007 Adriaan de Groot <groot@kde.org>
00006 ** Copyright (C) 2007 Jason 'vanRijn' Kasper <vR@movingparts.net>
00007 **
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 
00031 #include "options.h"
00032 
00033 
00034 
00035 #include <sys/stat.h>
00036 #include <sys/types.h>
00037 #include <stdio.h>
00038 #include <unistd.h>
00039 #include <fcntl.h>
00040 #include <errno.h>
00041 
00042 #include <iostream>
00043 
00044 #include <pi-source.h>
00045 #include <pi-socket.h>
00046 #include <pi-dlp.h>
00047 #include <pi-file.h>
00048 #include <pi-buffer.h>
00049 
00050 #include <qdir.h>
00051 #include <qtimer.h>
00052 #include <qdatetime.h>
00053 #include <qthread.h>
00054 
00055 #include <kconfig.h>
00056 #include <kmessagebox.h>
00057 #include <kstandarddirs.h>
00058 #include <kurl.h>
00059 #include <kio/netaccess.h>
00060 
00061 #include "pilotSerialDatabase.h"
00062 #include "pilotLocalDatabase.h"
00063 
00064 #include "kpilotlink.h"
00065 #include "kpilotlocallink.moc"
00066 
00067 
00068 typedef QPair<QString, struct DBInfo> DatabaseDescriptor;
00069 typedef QValueList<DatabaseDescriptor> DatabaseDescriptorList;
00070 
00071 class KPilotLocalLink::Private
00072 {
00073 public:
00074     DatabaseDescriptorList fDBs;
00075 } ;
00076 
00077 unsigned int KPilotLocalLink::findAvailableDatabases( KPilotLocalLink::Private &info, const QString &path )
00078 {
00079     FUNCTIONSETUP;
00080 
00081     info.fDBs.clear();
00082 
00083     QDir d(path);
00084     if (!d.exists())
00085     {
00086         // Perhaps return an error?
00087         return 0;
00088     }
00089 
00090     // Use this to fake indexes in the list of DBInfo structs
00091     unsigned int counter = 0;
00092 
00093     QStringList dbs = d.entryList( CSL1("*.pdb"), QDir::Files | QDir::NoSymLinks | QDir::Readable );
00094     for ( QStringList::ConstIterator i = dbs.begin(); i != dbs.end() ; ++i)
00095     {
00096         struct DBInfo dbi;
00097 
00098         // Remove the trailing 4 characters
00099         QString dbname = (*i);
00100         dbname.remove(dbname.length()-4,4);
00101 
00102         QString dbnamecheck = (*i).left((*i).findRev(CSL1(".pdb")));
00103         Q_ASSERT(dbname == dbnamecheck);
00104 
00105         if (PilotLocalDatabase::infoFromFile( path + CSL1("/") + (*i), &dbi))
00106         {
00107             DEBUGKPILOT << fname << ": Loaded "
00108                 << dbname << endl;
00109             dbi.index = counter;
00110             info.fDBs.append( DatabaseDescriptor(dbname,dbi) );
00111             ++counter;
00112         }
00113     }
00114 
00115     DEBUGKPILOT << fname << ": Total " << info.fDBs.count()
00116         << " databases." << endl;
00117     return info.fDBs.count();
00118 }
00119 
00120 
00121 KPilotLocalLink::KPilotLocalLink( QObject *parent, const char *name ) :
00122     KPilotLink(parent,name),
00123     fReady(false),
00124     d( new Private )
00125 {
00126     FUNCTIONSETUP;
00127 }
00128 
00129 KPilotLocalLink::~KPilotLocalLink()
00130 {
00131     FUNCTIONSETUP;
00132     KPILOT_DELETE(d);
00133 }
00134 
00135 /* virtual */ QString KPilotLocalLink::statusString() const
00136 {
00137     return fReady ? CSL1("Ready") : CSL1("Waiting") ;
00138 }
00139 
00140 /* virtual */ bool KPilotLocalLink::isConnected() const
00141 {
00142     return fReady;
00143 }
00144 
00145 /* virtual */ void KPilotLocalLink::reset( const QString &p )
00146 {
00147     FUNCTIONSETUP;
00148     fPath = p;
00149     reset();
00150 }
00151 
00152 /* virtual */ void KPilotLocalLink::reset()
00153 {
00154     FUNCTIONSETUP;
00155     QFileInfo info( fPath );
00156     fReady = !fPath.isEmpty() && info.exists() && info.isDir() ;
00157     if (fReady)
00158     {
00159         findAvailableDatabases(*d, fPath);
00160         QTimer::singleShot(500,this,SLOT(ready()));
00161     }
00162     else
00163     {
00164         WARNINGKPILOT << "The local link path <"
00165             << fPath
00166             << "> does not exist or is not a directory. No sync can be done."
00167             << endl;
00168     }
00169 }
00170 
00171 /* virtual */ void KPilotLocalLink::close()
00172 {
00173     fReady = false;
00174 }
00175 
00176 /* virtual */ bool KPilotLocalLink::tickle()
00177 {
00178     return true;
00179 }
00180 
00181 /* virtual */ const KPilotCard *KPilotLocalLink::getCardInfo(int)
00182 {
00183     return 0;
00184 }
00185 
00186 /* virtual */ void KPilotLocalLink::endSync( EndOfSyncFlags f )
00187 {
00188     Q_UNUSED(f);
00189     fReady = false;
00190 }
00191 
00192 /* virtual */ int KPilotLocalLink::openConduit()
00193 {
00194     FUNCTIONSETUP;
00195     return 0;
00196 }
00197 
00198 
00199 /* virtual */ int KPilotLocalLink::getNextDatabase( int index, struct DBInfo *info )
00200 {
00201     FUNCTIONSETUP;
00202 
00203     if ( (index<0) || (index>=(int)d->fDBs.count()) )
00204     {
00205         WARNINGKPILOT << "Index out of range." << endl;
00206         return -1;
00207     }
00208 
00209     DatabaseDescriptor dd = d->fDBs[index];
00210 
00211     DEBUGKPILOT << fname << ": Getting database " << dd.first << endl;
00212 
00213     if (info)
00214     {
00215         *info = dd.second;
00216     }
00217 
00218     return index+1;
00219 }
00220 
00221 /* virtual */ int KPilotLocalLink::findDatabase(const char *name, struct DBInfo*info,
00222         int index, unsigned long type, unsigned long creator)
00223 {
00224     FUNCTIONSETUP;
00225 
00226     if ( (index<0) || (index>=(int)d->fDBs.count()) )
00227     {
00228         WARNINGKPILOT << "Index out of range." << endl;
00229         return -1;
00230     }
00231 
00232     if (!name)
00233     {
00234         WARNINGKPILOT << "NULL name." << endl;
00235         return -1;
00236     }
00237 
00238     QString desiredName = Pilot::fromPilot(name);
00239     DEBUGKPILOT << fname << ": Looking for DB " << desiredName << endl;
00240     for ( DatabaseDescriptorList::ConstIterator i = d->fDBs.at(index);
00241         i != d->fDBs.end(); ++i)
00242     {
00243         const DatabaseDescriptor &dd = *i;
00244         if (dd.first == desiredName)
00245         {
00246             if ( (!type || (type == dd.second.type)) &&
00247                 (!creator || (creator == dd.second.creator)) )
00248             {
00249                 if (info)
00250                 {
00251                     *info = dd.second;
00252                 }
00253                 return index;
00254             }
00255         }
00256 
00257         ++index;
00258     }
00259 
00260     return -1;
00261 }
00262 
00263 /* virtual */ void KPilotLocalLink::addSyncLogEntryImpl(QString const &s)
00264 {
00265     FUNCTIONSETUP;
00266     DEBUGKPILOT << fname << ": " << s << endl ;
00267 }
00268 
00269 /* virtual */ bool KPilotLocalLink::installFile(QString const &path, bool deletefile)
00270 {
00271     FUNCTIONSETUP;
00272 
00273     QFileInfo srcInfo(path);
00274     QString canonicalSrcPath = srcInfo.dir().canonicalPath() + CSL1("/") + srcInfo.fileName() ;
00275     QString canonicalDstPath = fPath + CSL1("/") + srcInfo.fileName();
00276 
00277     if (canonicalSrcPath == canonicalDstPath)
00278     {
00279         // That's a cheap copy operation
00280         return true;
00281     }
00282 
00283     KURL src = KURL::fromPathOrURL( canonicalSrcPath );
00284     KURL dst = KURL::fromPathOrURL( canonicalDstPath );
00285 
00286     KIO::NetAccess::file_copy(src,dst,-1,true);
00287 
00288     if (deletefile)
00289     {
00290         KIO::NetAccess::del(src, 0L);
00291     }
00292 
00293     return true;
00294 }
00295 
00296 /* virtual */ bool KPilotLocalLink::retrieveDatabase( const QString &path, struct DBInfo *db )
00297 {
00298     FUNCTIONSETUP;
00299 
00300     QString dbname = Pilot::fromPilot(db->name) + CSL1(".pdb") ;
00301     QString sourcefile = fPath + CSL1("/") + dbname ;
00302     QString destfile = path ;
00303 
00304     DEBUGKPILOT << fname << ": src=" << sourcefile << endl;
00305     DEBUGKPILOT << fname << ": dst=" << destfile << endl;
00306 
00307     QFile in( sourcefile );
00308     if ( !in.exists() )
00309     {
00310         WARNINGKPILOT << "Source file " << sourcefile << " doesn't exist." << endl;
00311         return false;
00312     }
00313     if ( !in.open( IO_ReadOnly | IO_Raw ) )
00314     {
00315         WARNINGKPILOT << "Can't read source file " << sourcefile << endl;
00316         return false;
00317     }
00318 
00319     QFile out( destfile );
00320     if ( !out.open( IO_WriteOnly | IO_Truncate | IO_Raw ) )
00321     {
00322         WARNINGKPILOT << "Can't write destination file " << destfile << endl;
00323         return false;
00324     }
00325 
00326     const Q_ULONG BUF_SIZ = 8192 ;
00327     char buf[BUF_SIZ];
00328     Q_LONG r;
00329 
00330     while ( (r=in.readBlock(buf,BUF_SIZ))>0 )
00331     {
00332         out.writeBlock(buf,r);
00333     }
00334     out.flush();
00335     in.close();
00336 
00337     return out.exists();
00338 }
00339 
00340 KPilotLink::DBInfoList KPilotLocalLink::getDBList( int, int )
00341 {
00342     FUNCTIONSETUP;
00343     DBInfoList l;
00344     for ( DatabaseDescriptorList::ConstIterator i=d->fDBs.begin();
00345         i != d->fDBs.end(); ++i)
00346     {
00347         l.append( (*i).second );
00348     }
00349     return l;
00350 }
00351 
00352 
00353 /* virtual */ PilotDatabase *KPilotLocalLink::database( const QString &name )
00354 {
00355     FUNCTIONSETUP;
00356     return new PilotLocalDatabase( fPath, name );
00357 }
00358 
00359 
00360 
00361 /* slot */ void KPilotLocalLink::ready()
00362 {
00363     if (fReady)
00364     {
00365         emit deviceReady(this);
00366     }
00367 }
00368