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 #include "options.h"
00031
00032
00033
00034 #include <sys/stat.h>
00035 #include <sys/types.h>
00036 #include <stdio.h>
00037 #include <unistd.h>
00038 #include <fcntl.h>
00039 #include <errno.h>
00040
00041 #include <iostream>
00042
00043 #include <pi-source.h>
00044 #include <pi-socket.h>
00045 #include <pi-dlp.h>
00046 #include <pi-file.h>
00047 #include <pi-buffer.h>
00048
00049 #include <qdir.h>
00050 #include <qtimer.h>
00051 #include <qdatetime.h>
00052 #include <qsocketnotifier.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 "pilotUser.h"
00062 #include "pilotSysInfo.h"
00063 #include "pilotCard.h"
00064 #include "pilotSerialDatabase.h"
00065 #include "pilotLocalDatabase.h"
00066
00067 #include "kpilotlink.moc"
00068 #include "kpilotdevicelink.moc"
00069 #include "kpilotlocallink.moc"
00070
00075 class TickleThread : public QThread
00076 {
00077 public:
00078 TickleThread(KPilotLink *d, bool *done, int timeout) :
00079 QThread(),
00080 fHandle(d),
00081 fDone(done),
00082 fTimeout(timeout)
00083 { };
00084 virtual ~TickleThread();
00085
00086 virtual void run();
00087
00088 static const int ChecksPerSecond = 5;
00089 static const int SecondsPerTickle = 5;
00090 static const unsigned int TickleTimeoutEvent = 1066;
00091
00092 private:
00093 KPilotLink *fHandle;
00094 bool *fDone;
00095 int fTimeout;
00096 } ;
00097
00098 TickleThread::~TickleThread()
00099 {
00100 }
00101
00102 void TickleThread::run()
00103 {
00104 FUNCTIONSETUP;
00105 int subseconds = ChecksPerSecond;
00106 int ticktock = SecondsPerTickle;
00107 int timeout = fTimeout;
00108 DEBUGLIBRARY << fname << ": Running for "
00109 << timeout << " seconds." << endl;
00110 DEBUGLIBRARY << fname << ": Done @" << (void *) fDone << endl;
00111
00112 while (!(*fDone))
00113 {
00114 QThread::msleep(1000/ChecksPerSecond);
00115 if (!(--subseconds))
00116 {
00117 if (timeout)
00118 {
00119 if (!(--timeout))
00120 {
00121 QApplication::postEvent(fHandle, new QEvent(static_cast<QEvent::Type>(TickleTimeoutEvent)));
00122 break;
00123 }
00124 }
00125 subseconds=ChecksPerSecond;
00126 if (!(--ticktock))
00127 {
00128 ticktock=SecondsPerTickle;
00129 fHandle->tickle();
00130 }
00131 }
00132 }
00133 }
00134
00135
00136
00137
00138
00139
00140
00141
00142 KPilotLink::KPilotLink( QObject *parent, const char *name ) :
00143 QObject( parent, name ),
00144 fPilotPath(QString::null),
00145 fPilotUser(0L),
00146 fPilotSysInfo(0L),
00147 fTickleDone(true),
00148 fTickleThread(0L)
00149
00150 {
00151 FUNCTIONSETUP;
00152
00153 fPilotUser = new KPilotUser();
00154 strncpy( fPilotUser->pilotUser()->username, "Henk Westbroek",
00155 sizeof(fPilotUser->pilotUser()->username)-1);
00156 fPilotUser->setLastSuccessfulSyncDate( 1139171019 );
00157
00158 fPilotSysInfo = new KPilotSysInfo();
00159 memset(fPilotSysInfo->sysInfo()->prodID, 0,
00160 sizeof(fPilotSysInfo->sysInfo()->prodID));
00161 strncpy(fPilotSysInfo->sysInfo()->prodID, "LocalLink",
00162 sizeof(fPilotSysInfo->sysInfo()->prodID)-1);
00163 fPilotSysInfo->sysInfo()->prodIDLength =
00164 strlen(fPilotSysInfo->sysInfo()->prodID);
00165 }
00166
00167 KPilotLink::~KPilotLink()
00168 {
00169 FUNCTIONSETUP;
00170 KPILOT_DELETE(fPilotUser);
00171 KPILOT_DELETE(fPilotSysInfo);
00172 }
00173
00174 bool KPilotLink::event(QEvent *e)
00175 {
00176 if (e->type() == TickleThread::TickleTimeoutEvent)
00177 {
00178 stopTickle();
00179 emit timeout();
00180 return true;
00181 }
00182 else return QObject::event(e);
00183 }
00184
00185
00186
00187
00188 void KPilotLink::startTickle(unsigned int timeout)
00189 {
00190 FUNCTIONSETUP;
00191
00192 Q_ASSERT(fTickleDone);
00193
00194
00195
00196
00197
00198
00199 if (fTickleDone && fTickleThread)
00200 {
00201 fTickleThread->wait();
00202 KPILOT_DELETE(fTickleThread);
00203 }
00204
00205 DEBUGLIBRARY << fname << ": Done @" << (void *) (&fTickleDone) << endl;
00206
00207 fTickleDone = false;
00208 fTickleThread = new TickleThread(this,&fTickleDone,timeout);
00209 fTickleThread->start();
00210 }
00211
00212 void KPilotLink::stopTickle()
00213 {
00214 FUNCTIONSETUP;
00215 fTickleDone = true;
00216 if (fTickleThread)
00217 {
00218 fTickleThread->wait();
00219 KPILOT_DELETE(fTickleThread);
00220 }
00221 }
00222
00223 unsigned int KPilotLink::installFiles(const QStringList & l, const bool deleteFiles)
00224 {
00225 FUNCTIONSETUP;
00226
00227 QStringList::ConstIterator i,e;
00228 unsigned int k = 0;
00229 unsigned int n = 0;
00230 unsigned int total = l.count();
00231
00232 for (i = l.begin(), e = l.end(); i != e; ++i)
00233 {
00234 emit logProgress(QString::null,
00235 (int) ((100.0 / total) * (float) n));
00236
00237 if (installFile(*i, deleteFiles))
00238 k++;
00239 n++;
00240 }
00241 emit logProgress(QString::null, 100);
00242
00243 return k;
00244 }
00245
00246 void KPilotLink::addSyncLogEntry(const QString & entry, bool log)
00247 {
00248 FUNCTIONSETUP;
00249 if (entry.isEmpty()) return;
00250
00251 addSyncLogEntryImpl(entry);
00252 if (log)
00253 {
00254 emit logMessage(entry);
00255 }
00256 }
00257
00258
00259 int KPilotLink::openConduit()
00260 {
00261 return 0;
00262 }
00263
00264 int KPilotLink::pilotSocket() const
00265 {
00266 return -1;
00267 }
00268
00269
00270
00271
00272
00273 class KPilotDeviceLink::KPilotDeviceLinkPrivate
00274 {
00275 public:
00276 static KPilotDeviceLinkPrivate*self()
00277 {
00278 if (!mThis) mThis = new KPilotDeviceLinkPrivate();
00279 return mThis;
00280 }
00281
00282 bool canBind( const QString &device )
00283 {
00284 showList();
00285 return !mBoundDevices.contains( device );
00286 }
00287
00288 void bindDevice( const QString &device )
00289 {
00290 mBoundDevices.append( device );
00291 showList();
00292 }
00293
00294 void unbindDevice( const QString &device )
00295 {
00296 mBoundDevices.remove( device );
00297 showList();
00298 }
00299
00300 protected:
00301 KPilotDeviceLinkPrivate() {}
00302 ~KPilotDeviceLinkPrivate() {}
00303
00304 QStringList mBoundDevices;
00305 static KPilotDeviceLinkPrivate*mThis;
00306
00307 private:
00308 inline void showList() const
00309 {
00310 if ( !(mBoundDevices.count() > 0) ) return;
00311 FUNCTIONSETUPL(3);
00312 DEBUGLIBRARY << fname << ": Bound devices: "
00313 << ((mBoundDevices.count() > 0) ? mBoundDevices.join(CSL1(", ")) : CSL1("<none>")) << endl;
00314 }
00315 } ;
00316
00317 KPilotDeviceLink::KPilotDeviceLinkPrivate *KPilotDeviceLink::KPilotDeviceLinkPrivate::mThis = 0L;
00318
00319
00320 KPilotDeviceLink::KPilotDeviceLink(QObject * parent, const char *name, const QString &tempDevice) :
00321 KPilotLink(parent, name),
00322 fLinkStatus(Init),
00323 fWorkaroundUSB(false),
00324 fWorkaroundUSBTimer(0L),
00325 fRetries(0),
00326 fOpenTimer(0L),
00327 fSocketNotifier(0L),
00328 fSocketNotifierActive(false),
00329 fPilotMasterSocket(-1),
00330 fCurrentPilotSocket(-1),
00331 fTempDevice(tempDevice)
00332 {
00333 FUNCTIONSETUP;
00334
00335 DEBUGLIBRARY << fname
00336 << ": Pilot-link version " << PILOT_LINK_NUMBER
00337 << endl;
00338
00339 messagesMask=0xffffffff;
00340
00341 }
00342
00343 KPilotDeviceLink::~KPilotDeviceLink()
00344 {
00345 FUNCTIONSETUP;
00346 close();
00347 KPILOT_DELETE(fWorkaroundUSBTimer);
00348 KPILOT_DELETE(fPilotSysInfo);
00349 KPILOT_DELETE(fPilotUser);
00350 }
00351
00352 bool KPilotDeviceLink::isConnected() const
00353 {
00354 return fLinkStatus == AcceptedDevice;
00355 }
00356
00357
00358 void KPilotDeviceLink::close()
00359 {
00360 FUNCTIONSETUP;
00361
00362 KPILOT_DELETE(fWorkaroundUSBTimer);
00363 KPILOT_DELETE(fOpenTimer);
00364 KPILOT_DELETE(fSocketNotifier);
00365 fSocketNotifierActive=false;
00366
00367 DEBUGLIBRARY << fname
00368 << ": Closing sockets "
00369 << fCurrentPilotSocket
00370 << " and "
00371 << fPilotMasterSocket
00372 << endl;
00373
00374 if (fCurrentPilotSocket != -1)
00375 {
00376 pi_close(fCurrentPilotSocket);
00377
00378
00379 ::close(fCurrentPilotSocket);
00380 }
00381 if (fPilotMasterSocket != -1)
00382 {
00383 pi_close(fPilotMasterSocket);
00384 ::close(fPilotMasterSocket);
00385 }
00386 KPilotDeviceLinkPrivate::self()->unbindDevice( fRealPilotPath );
00387 fPilotMasterSocket = (-1);
00388 fCurrentPilotSocket = (-1);
00389 }
00390
00391 void KPilotDeviceLink::reset(const QString & dP)
00392 {
00393 FUNCTIONSETUP;
00394
00395 fLinkStatus = Init;
00396 fRetries = 0;
00397
00398
00399
00400 close();
00401 fPilotPath = QString::null;
00402
00403 fPilotPath = dP;
00404 if (fPilotPath.isEmpty())
00405 fPilotPath = fTempDevice;
00406 if (fPilotPath.isEmpty())
00407 return;
00408
00409 reset();
00410 }
00411
00412 static inline void startOpenTimer(KPilotDeviceLink *dev, QTimer *&t)
00413 {
00414 if ( !t ){
00415 t = new QTimer(dev);
00416 QObject::connect(t, SIGNAL(timeout()),
00417 dev, SLOT(openDevice()));
00418 }
00419 t->start(1000, false);
00420 }
00421
00422 void KPilotDeviceLink::reset()
00423 {
00424 FUNCTIONSETUP;
00425
00426 messages=0;
00427 close();
00428
00429 checkDevice();
00430
00431
00432 startOpenTimer(this,fOpenTimer);
00433
00434 fLinkStatus = WaitingForDevice;
00435 }
00436
00437 void KPilotDeviceLink::checkDevice()
00438 {
00439
00440
00441
00442 QFileInfo fi(fPilotPath);
00443 if (fi.exists())
00444 {
00445
00446
00447 if (!(fi.isReadable() && fi.isWritable()))
00448 {
00449 emit logError(i18n("Pilot device %1 is not read-write.")
00450 .arg(fPilotPath));
00451 }
00452 }
00453 else
00454 {
00455
00456
00457
00458 emit logError(i18n("Pilot device %1 does not exist. "
00459 "Probably it is a USB device and will appear during a HotSync.")
00460 .arg(fPilotPath));
00461 messages |= (OpenMessage | OpenFailMessage);
00462 }
00463 }
00464
00465 void KPilotDeviceLink::setTempDevice( const QString &d )
00466 {
00467 fTempDevice = d;
00468 KPilotDeviceLinkPrivate::self()->bindDevice( fTempDevice );
00469 }
00470
00471 void KPilotDeviceLink::openDevice()
00472 {
00473 FUNCTIONSETUPL(2);
00474
00475
00476
00477
00478 if (fLinkStatus == WaitingForDevice)
00479 {
00480 fLinkStatus = FoundDevice;
00481 }
00482
00483 shouldPrint(OpenMessage,i18n("Trying to open device %1...")
00484 .arg(fPilotPath));
00485
00486 if (open())
00487 {
00488 emit logMessage(i18n("Device link ready."));
00489 }
00490 else if (open(fTempDevice))
00491 {
00492 emit logMessage(i18n("Device link ready."));
00493 }
00494 else
00495 {
00496 shouldPrint(OpenFailMessage,i18n("Could not open device: %1 "
00497 "(will retry)").
00498 arg(fPilotPath));
00499
00500 if (fLinkStatus != PilotLinkError)
00501 {
00502 startOpenTimer(this,fOpenTimer);
00503 }
00504 }
00505 }
00506
00507 bool KPilotDeviceLink::open(const QString &device)
00508 {
00509 FUNCTIONSETUPL(2);
00510
00511 int ret;
00512 int e = 0;
00513 QString msg;
00514
00515 if (fCurrentPilotSocket != -1)
00516 {
00517
00518 pi_close(fCurrentPilotSocket);
00519 ::close(fCurrentPilotSocket);
00520 }
00521 fCurrentPilotSocket = (-1);
00522
00523 if (device.isEmpty() && pilotPath().isEmpty())
00524 {
00525 kdWarning() << k_funcinfo
00526 << ": No point in trying empty device."
00527 << endl;
00528
00529 msg = i18n("The Pilot device is not configured yet.");
00530 e = 0;
00531 goto errInit;
00532 }
00533 fRealPilotPath = KStandardDirs::realFilePath( device.isEmpty() ? fPilotPath : device );
00534
00535 if ( !KPilotDeviceLinkPrivate::self()->canBind( fRealPilotPath ) ) {
00536 msg = i18n("Already listening on that device");
00537 e=0;
00538 kdWarning() << k_funcinfo << ": Pilot Path "
00539 << fRealPilotPath << " already connected." << endl;
00540 goto errInit;
00541 }
00542
00543
00544 if (fPilotMasterSocket == -1)
00545 {
00546 DEBUGLIBRARY << fname << ": Typing to open "
00547 << fRealPilotPath << endl;
00548
00549 fPilotMasterSocket = pi_socket(PI_AF_PILOT,
00550 PI_SOCK_STREAM, PI_PF_DLP);
00551
00552 if (fPilotMasterSocket < 0)
00553 {
00554 e = errno;
00555 msg = i18n("Cannot create socket for communicating "
00556 "with the Pilot");
00557 goto errInit;
00558 }
00559
00560 DEBUGLIBRARY << fname
00561 << ": Got master " << fPilotMasterSocket << endl;
00562
00563 fLinkStatus = CreatedSocket;
00564 }
00565
00566 Q_ASSERT(fLinkStatus == CreatedSocket);
00567
00568 DEBUGLIBRARY << fname << ": Binding to path "
00569 << fRealPilotPath << endl;
00570
00571 ret = pi_bind(fPilotMasterSocket, QFile::encodeName(fRealPilotPath));
00572
00573 if (ret >= 0)
00574 {
00575 fLinkStatus = DeviceOpen;
00576 if( fOpenTimer)
00577 fOpenTimer->stop();
00578
00579 KPilotDeviceLinkPrivate::self()->bindDevice( fRealPilotPath );
00580 fSocketNotifier = new QSocketNotifier(fPilotMasterSocket,
00581 QSocketNotifier::Read, this);
00582 QObject::connect(fSocketNotifier, SIGNAL(activated(int)),
00583 this, SLOT(acceptDevice()));
00584 fSocketNotifierActive=true;
00585
00586 if (fWorkaroundUSB)
00587 {
00588 DEBUGLIBRARY << fname << ": Adding Z31 workaround." << endl;
00589
00590
00591
00592
00593 fWorkaroundUSBTimer = new QTimer(this);
00594 connect(fWorkaroundUSBTimer,SIGNAL(timeout()),
00595 this,SLOT(workaroundUSB()));
00596 fWorkaroundUSBTimer->start(5000,true);
00597 }
00598
00599 return true;
00600 }
00601 else
00602 {
00603 DEBUGLIBRARY << fname
00604 << ": Tried " << fRealPilotPath << " and got "
00605 << strerror(errno) << endl;
00606
00607 if (fRetries < 5)
00608 {
00609 return false;
00610 }
00611 e = errno;
00612 msg = i18n("Cannot open Pilot port \"%1\". ");
00613 if (fOpenTimer )
00614 fOpenTimer->stop();
00615
00616
00617 }
00618
00619
00620
00621
00622
00623
00624
00625 errInit:
00626 close();
00627
00628 if (msg.find('%'))
00629 {
00630 if (fRealPilotPath.isEmpty())
00631 {
00632 if (fPilotPath.isEmpty())
00633 {
00634 msg = msg.arg(i18n("(empty)"));
00635 }
00636 else
00637 {
00638 msg = msg.arg(fPilotPath);
00639 }
00640 }
00641 else
00642 {
00643 msg = msg.arg(fRealPilotPath);
00644 }
00645 }
00646 switch (e)
00647 {
00648 case ENOENT:
00649 msg += i18n(" The port does not exist.");
00650 break;
00651 case ENODEV:
00652 msg += i18n(" These is no such device.");
00653 break;
00654 case EPERM:
00655 msg += i18n(" You do not have permission to open the "
00656 "Pilot device.");
00657 break;
00658 default:
00659 msg += i18n(" Check Pilot path and permissions.");
00660 }
00661
00662
00663
00664
00665
00666
00667 kdError() << k_funcinfo << ": " << msg << endl;
00668 if (e)
00669 {
00670 kdError() << k_funcinfo
00671 << ": (" << strerror(e) << ")" << endl;
00672 }
00673
00674 fLinkStatus = PilotLinkError;
00675 emit logError(msg);
00676 return false;
00677 }
00678
00679 void KPilotDeviceLink::acceptDevice()
00680 {
00681 FUNCTIONSETUP;
00682
00683 int ret;
00684
00685 if (!fSocketNotifierActive)
00686 {
00687 if (!fAcceptedCount)
00688 {
00689 kdWarning() << k_funcinfo << ": Accidentally in acceptDevice()"
00690 << endl;
00691 }
00692 fAcceptedCount++;
00693 if (fAcceptedCount>10)
00694 {
00695
00696 KPILOT_DELETE(fSocketNotifier);
00697 }
00698 return;
00699 }
00700
00701 if (fSocketNotifier)
00702 {
00703
00704 fSocketNotifierActive=false;
00705 }
00706
00707 DEBUGLIBRARY << fname
00708 << ": Found connection on device "<<pilotPath().latin1()<<endl;
00709 DEBUGLIBRARY << fname
00710 << ": Current status "
00711 << statusString()
00712 << " and master " << fPilotMasterSocket << endl;
00713
00714 ret = pi_listen(fPilotMasterSocket, 1);
00715 if (ret < 0)
00716 {
00717 char *s = strerror(errno);
00718
00719 kdWarning() << "pi_listen: " << s << endl;
00720
00721
00722
00723 emit logError(i18n("Cannot listen on Pilot socket (%1)").
00724 arg(QString::fromLocal8Bit(s)));
00725
00726 close();
00727 return;
00728 }
00729
00730 KPILOT_DELETE(fWorkaroundUSBTimer);
00731
00732 emit logProgress(QString::null,10);
00733
00734 fCurrentPilotSocket = pi_accept(fPilotMasterSocket, 0, 0);
00735 if (fCurrentPilotSocket < 0)
00736 {
00737 char *s = strerror(errno);
00738
00739 kdWarning() << "pi_accept: " << s << endl;
00740
00741 emit logError(i18n("Cannot accept Pilot (%1)")
00742 .arg(QString::fromLocal8Bit(s)));
00743
00744 fLinkStatus = PilotLinkError;
00745 close();
00746 return;
00747 }
00748
00749 if ((fLinkStatus != DeviceOpen) || (fPilotMasterSocket == -1))
00750 {
00751 fLinkStatus = PilotLinkError;
00752 kdError() << k_funcinfo
00753 << ": Already connected or unable to connect!"
00754 << endl;
00755 emit logError(i18n("Cannot accept Pilot (%1)")
00756 .arg(i18n("already connected")));
00757 close();
00758 return;
00759 }
00760
00761 emit logProgress(QString::null, 30);
00762
00763 KPILOT_DELETE(fPilotSysInfo);
00764 fPilotSysInfo = new KPilotSysInfo();
00765 if (dlp_ReadSysInfo(fCurrentPilotSocket, fPilotSysInfo->sysInfo()) < 0)
00766 {
00767 emit logError(i18n("Unable to read system information from Pilot"));
00768 fLinkStatus=PilotLinkError;
00769 return;
00770 }
00771 else
00772 {
00773 DEBUGLIBRARY << fname
00774 << ": RomVersion=" << fPilotSysInfo->getRomVersion()
00775 << " Locale=" << fPilotSysInfo->getLocale()
00776 << " Product=" << fPilotSysInfo->getProductID()
00777 << endl;
00778 }
00779
00780 emit logProgress(QString::null, 60);
00781 KPILOT_DELETE(fPilotUser);
00782 fPilotUser = new KPilotUser;
00783
00784
00785 DEBUGLIBRARY << fname << ": Reading user info @"
00786 << (void *) fPilotUser << endl;
00787 DEBUGLIBRARY << fname << ": Buffer @"
00788 << (void *) fPilotUser->pilotUser() << endl;
00789
00790 dlp_ReadUserInfo(fCurrentPilotSocket, fPilotUser->pilotUser());
00791
00792 const char *n = fPilotUser->getUserName();
00793 DEBUGLIBRARY << fname
00794 << ": Read user name "
00795 << ( (!n || !*n) ?
00796 "<empty>" :
00797 fPilotUser->getUserName() )
00798 << endl;
00799
00800 emit logProgress(i18n("Checking last PC..."), 90);
00801
00802
00803 if ((ret=dlp_OpenConduit(fCurrentPilotSocket)) < 0)
00804 {
00805 DEBUGLIBRARY << fname
00806 << ": dlp_OpenConduit returned " << ret << endl;
00807
00808 emit logError(i18n("Could not read user information from the Pilot. "
00809 "Perhaps you have a password set on the device?"));
00810 }
00811 fLinkStatus = AcceptedDevice;
00812
00813
00814 emit logProgress(QString::null, 100);
00815 emit deviceReady( this );
00816 }
00817
00818 void KPilotDeviceLink::workaroundUSB()
00819 {
00820 FUNCTIONSETUP;
00821
00822 Q_ASSERT((fLinkStatus == DeviceOpen) || (fLinkStatus == WorkaroundUSB));
00823 if (fLinkStatus == DeviceOpen)
00824 {
00825 reset();
00826 }
00827 fLinkStatus = WorkaroundUSB;
00828
00829 if (!QFile::exists(fRealPilotPath))
00830 {
00831
00832
00833 startOpenTimer(this,fOpenTimer);
00834 return;
00835 }
00836 if (fOpenTimer)
00837 {
00838 fOpenTimer->stop();
00839 }
00840 KPILOT_DELETE(fWorkaroundUSBTimer);
00841 QTimer::singleShot(1000,this,SLOT(workaroundUSB()));
00842 }
00843
00844 bool KPilotDeviceLink::tickle()
00845 {
00846
00847
00848 return pi_tickle(pilotSocket()) >= 0;
00849 }
00850
00851 void KPilotDeviceLink::addSyncLogEntryImpl( const QString &entry )
00852 {
00853 dlp_AddSyncLogEntry(fCurrentPilotSocket,
00854 const_cast<char *>((const char *)Pilot::toPilot(entry)));
00855 }
00856
00857 bool KPilotDeviceLink::installFile(const QString & f, const bool deleteFile)
00858 {
00859 FUNCTIONSETUP;
00860
00861 DEBUGLIBRARY << fname << ": Installing file " << f << endl;
00862
00863 if (!QFile::exists(f))
00864 return false;
00865
00866 char buffer[PATH_MAX];
00867 memset(buffer,0,PATH_MAX);
00868 strlcpy(buffer,QFile::encodeName(f),PATH_MAX);
00869 struct pi_file *pf =
00870 pi_file_open(buffer);
00871
00872 if (!f)
00873 {
00874 kdWarning() << k_funcinfo
00875 << ": Cannot open file " << f << endl;
00876 emit logError(i18n
00877 ("<qt>Cannot install the file "%1".</qt>").
00878 arg(f));
00879 return false;
00880 }
00881
00882 if (pi_file_install(pf, fCurrentPilotSocket, 0, 0L) < 0)
00883 {
00884 kdWarning() << k_funcinfo
00885 << ": Cannot pi_file_install " << f << endl;
00886 emit logError(i18n
00887 ("<qt>Cannot install the file "%1".</qt>").
00888 arg(f));
00889 return false;
00890 }
00891
00892 pi_file_close(pf);
00893 if (deleteFile) QFile::remove(f);
00894
00895 return true;
00896 }
00897
00898
00899 int KPilotDeviceLink::openConduit()
00900 {
00901 return dlp_OpenConduit(fCurrentPilotSocket);
00902 }
00903
00904 QString KPilotDeviceLink::statusString(LinkStatus l)
00905 {
00906 FUNCTIONSETUP;
00907 QString s = CSL1("KPilotDeviceLink=");
00908
00909 switch (l)
00910 {
00911 case Init:
00912 s.append(CSL1("Init"));
00913 break;
00914 case WaitingForDevice:
00915 s.append(CSL1("WaitingForDevice"));
00916 break;
00917 case FoundDevice:
00918 s.append(CSL1("FoundDevice"));
00919 break;
00920 case CreatedSocket:
00921 s.append(CSL1("CreatedSocket"));
00922 break;
00923 case DeviceOpen:
00924 s.append(CSL1("DeviceOpen"));
00925 break;
00926 case AcceptedDevice:
00927 s.append(CSL1("AcceptedDevice"));
00928 break;
00929 case SyncDone:
00930 s.append(CSL1("SyncDone"));
00931 break;
00932 case PilotLinkError:
00933 s.append(CSL1("PilotLinkError"));
00934 break;
00935 case WorkaroundUSB:
00936 s.append(CSL1("WorkaroundUSB"));
00937 break;
00938 }
00939
00940 return s;
00941 }
00942
00943 QString KPilotDeviceLink::statusString() const
00944 {
00945 return statusString( status() );
00946 }
00947
00948 void KPilotDeviceLink::endOfSync()
00949 {
00950 dlp_EndOfSync(pilotSocket(), 0);
00951 KPILOT_DELETE(fPilotSysInfo);
00952 KPILOT_DELETE(fPilotUser);
00953 }
00954
00955 void KPilotDeviceLink::finishSync()
00956 {
00957 FUNCTIONSETUP ;
00958
00959 getPilotUser().setLastSyncPC((unsigned long) gethostid());
00960 getPilotUser().setLastSyncDate(time(0));
00961
00962
00963 DEBUGLIBRARY << fname << ": Writing username " << getPilotUser().getUserName() << endl;
00964
00965 dlp_WriteUserInfo(pilotSocket(),getPilotUser().pilotUser());
00966 addSyncLogEntry(i18n("End of HotSync\n"));
00967 endOfSync();
00968 }
00969
00970 int KPilotDeviceLink::getNextDatabase(int index,struct DBInfo *dbinfo)
00971 {
00972 FUNCTIONSETUP;
00973
00974 pi_buffer_t buf = { 0,0,0 };
00975 int r = dlp_ReadDBList(pilotSocket(),0,dlpDBListRAM,index,&buf);
00976 if (r >= 0)
00977 {
00978 memcpy(dbinfo,buf.data,sizeof(struct DBInfo));
00979 }
00980 return r;
00981 }
00982
00983
00984 int KPilotDeviceLink::findDatabase(const char *name, struct DBInfo *dbinfo,
00985 int index, unsigned long type, unsigned long creator)
00986 {
00987 FUNCTIONSETUP;
00988 return dlp_FindDBInfo(pilotSocket(), 0, index,
00989 const_cast<char *>(name), type, creator, dbinfo);
00990 }
00991
00992 bool KPilotDeviceLink::retrieveDatabase(const QString &fullBackupName,
00993 DBInfo *info)
00994 {
00995 FUNCTIONSETUP;
00996
00997 DEBUGLIBRARY << fname << ": Writing DB <" << info->name << "> "
00998 << " to " << fullBackupName << endl;
00999
01000 struct pi_file *f;
01001 if (fullBackupName.isEmpty())
01002 {
01003
01004 return false;
01005 }
01006 QCString encodedName = QFile::encodeName(fullBackupName);
01007 char filenameBuf[PATH_MAX];
01008 memset(filenameBuf,0,PATH_MAX);
01009 strlcpy(filenameBuf,(const char *)encodedName,PATH_MAX);
01010 f = pi_file_create(filenameBuf,info);
01011
01012 if (f == 0)
01013 {
01014 kdWarning() << k_funcinfo
01015 << ": Failed, unable to create file" << endl;
01016 return false;
01017 }
01018
01019 if (pi_file_retrieve(f, pilotSocket(), 0, 0L) < 0)
01020 {
01021 kdWarning() << k_funcinfo
01022 << ": Failed, unable to back up database" << endl;
01023
01024 pi_file_close(f);
01025 return false;
01026 }
01027
01028 pi_file_close(f);
01029 return true;
01030 }
01031
01032
01033 DBInfoList KPilotDeviceLink::getDBList(int cardno, int flags)
01034 {
01035 bool cont=true;
01036 DBInfoList dbs;
01037 int index=0;
01038 while (cont)
01039 {
01040 pi_buffer_t buf = { 0,0,0 };
01041 pi_buffer_clear(&buf);
01042
01043 if (dlp_ReadDBList(pilotSocket(), cardno, flags | dlpDBListMultiple, index, &buf)<0)
01044 {
01045 cont=false;
01046 }
01047 else
01048 {
01049 DBInfo db_n;
01050 DBInfo *db_it = (DBInfo *)buf.data;
01051 int info_count = buf.used / sizeof(struct DBInfo);
01052
01053 while(info_count>0)
01054 {
01055 memcpy(&db_n,db_it,sizeof(struct DBInfo));
01056 ++db_it;
01057 info_count--;
01058 dbs.append(db_n);
01059 }
01060 index=db_n.index+1;
01061 }
01062 }
01063 return dbs;
01064 }
01065
01066 const KPilotCard *KPilotDeviceLink::getCardInfo(int card)
01067 {
01068 KPilotCard *cardinfo=new KPilotCard();
01069 if (dlp_ReadStorageInfo(pilotSocket(), card, cardinfo->cardInfo())<0)
01070 {
01071 kdWarning() << k_funcinfo << ": Could not get info for card "
01072 << card << endl;
01073
01074 KPILOT_DELETE(cardinfo);
01075 return 0L;
01076 };
01077 return cardinfo;
01078 }
01079
01080 const int KPilotDeviceLink::messagesType=
01081 (int)OpenFailMessage ;
01082
01083 void KPilotDeviceLink::shouldPrint(int m,const QString &s)
01084 {
01085 if (!(messages & m))
01086 {
01087 if (messagesType & m) { emit logError(s); }
01088 else { emit logMessage(s); }
01089 messages |= (m & messagesMask);
01090 }
01091 }
01092
01093 PilotDatabase *KPilotDeviceLink::database( const QString &name )
01094 {
01095 return new PilotSerialDatabase( this, name );
01096 }
01097
01098
01099 typedef QPair<QString, struct DBInfo> DatabaseDescriptor;
01100 typedef QValueList<DatabaseDescriptor> DatabaseDescriptorList;
01101
01102 class KPilotLocalLink::Private
01103 {
01104 public:
01105 DatabaseDescriptorList fDBs;
01106 } ;
01107
01108 unsigned int KPilotLocalLink::findAvailableDatabases( KPilotLocalLink::Private &info, const QString &path )
01109 {
01110 FUNCTIONSETUP;
01111
01112 info.fDBs.clear();
01113
01114 QDir d(path);
01115 if (!d.exists())
01116 {
01117
01118 return 0;
01119 }
01120
01121
01122 unsigned int counter = 0;
01123
01124 QStringList dbs = d.entryList( CSL1("*.pdb"), QDir::Files | QDir::NoSymLinks | QDir::Readable );
01125 for ( QStringList::ConstIterator i = dbs.begin(); i != dbs.end() ; ++i)
01126 {
01127 struct DBInfo dbi;
01128
01129
01130 QString dbname = (*i);
01131 dbname.remove(dbname.length()-4,4);
01132
01133 QString dbnamecheck = (*i).left((*i).findRev(CSL1(".pdb")));
01134 Q_ASSERT(dbname == dbnamecheck);
01135
01136 if (PilotLocalDatabase::infoFromFile( path + CSL1("/") + (*i), &dbi))
01137 {
01138 DEBUGLIBRARY << fname << ": Loaded "
01139 << dbname << endl;
01140 dbi.index = counter;
01141 info.fDBs.append( DatabaseDescriptor(dbname,dbi) );
01142 ++counter;
01143 }
01144 }
01145
01146 DEBUGLIBRARY << fname << ": Total " << info.fDBs.count()
01147 << " databases." << endl;
01148 return info.fDBs.count();
01149 }
01150
01151
01152 KPilotLocalLink::KPilotLocalLink( QObject *parent, const char *name ) :
01153 KPilotLink(parent,name),
01154 fReady(false),
01155 d( new Private )
01156 {
01157 FUNCTIONSETUP;
01158 }
01159
01160 KPilotLocalLink::~KPilotLocalLink()
01161 {
01162 FUNCTIONSETUP;
01163 KPILOT_DELETE(d);
01164 }
01165
01166 QString KPilotLocalLink::statusString() const
01167 {
01168 return fReady ? CSL1("Ready") : CSL1("Waiting") ;
01169 }
01170
01171 bool KPilotLocalLink::isConnected() const
01172 {
01173 return fReady;
01174 }
01175
01176 void KPilotLocalLink::reset( const QString &p )
01177 {
01178 FUNCTIONSETUP;
01179 fPath = p;
01180 reset();
01181 }
01182
01183 void KPilotLocalLink::reset()
01184 {
01185 FUNCTIONSETUP;
01186 QFileInfo info( fPath );
01187 fReady = !fPath.isEmpty() && info.exists() && info.isDir() ;
01188 if (fReady)
01189 {
01190 findAvailableDatabases(*d, fPath);
01191 QTimer::singleShot(500,this,SLOT(ready()));
01192 }
01193 else
01194 {
01195 kdWarning() << k_funcinfo << ": The local link path "
01196 << fPath
01197 << " does not exist or is not a direcotory. No sync will be done."
01198 << endl;
01199 }
01200 }
01201
01202 void KPilotLocalLink::close()
01203 {
01204 fReady = false;
01205 }
01206
01207 bool KPilotLocalLink::tickle()
01208 {
01209 return true;
01210 }
01211
01212 const KPilotCard *KPilotLocalLink::getCardInfo(int)
01213 {
01214 return 0;
01215 }
01216
01217 void KPilotLocalLink::endOfSync()
01218 {
01219 }
01220
01221 void KPilotLocalLink::finishSync()
01222 {
01223 }
01224
01225 int KPilotLocalLink::openConduit()
01226 {
01227 FUNCTIONSETUP;
01228 return 0;
01229 }
01230
01231
01232 int KPilotLocalLink::getNextDatabase( int index, struct DBInfo *info )
01233 {
01234 FUNCTIONSETUP;
01235
01236 if ( (index<0) || (index>=(int)d->fDBs.count()) )
01237 {
01238 kdWarning() << k_funcinfo << ": Index out of range." << endl;
01239 return -1;
01240 }
01241
01242 DatabaseDescriptor dd = d->fDBs[index];
01243
01244 DEBUGLIBRARY << fname << ": Getting database " << dd.first << endl;
01245
01246 if (info)
01247 {
01248 *info = dd.second;
01249 }
01250
01251 return index+1;
01252 }
01253
01254 int KPilotLocalLink::findDatabase(const char *name, struct DBInfo*info,
01255 int index, unsigned long type, unsigned long creator)
01256 {
01257 FUNCTIONSETUP;
01258
01259 if ( (index<0) || (index>=(int)d->fDBs.count()) )
01260 {
01261 kdWarning() << k_funcinfo << ": Index out of range." << endl;
01262 return -1;
01263 }
01264
01265 if (!name)
01266 {
01267 kdWarning() << k_funcinfo << ": NULL name." << endl;
01268 return -1;
01269 }
01270
01271 QString desiredName = Pilot::fromPilot(name);
01272 DEBUGLIBRARY << fname << ": Looking for DB " << desiredName << endl;
01273 for ( DatabaseDescriptorList::ConstIterator i = d->fDBs.at(index);
01274 i != d->fDBs.end(); ++i)
01275 {
01276 const DatabaseDescriptor &dd = *i;
01277 if (dd.first == desiredName)
01278 {
01279 if ( (!type || (type == dd.second.type)) &&
01280 (!creator || (creator == dd.second.creator)) )
01281 {
01282 if (info)
01283 {
01284 *info = dd.second;
01285 }
01286 return index;
01287 }
01288 }
01289
01290 ++index;
01291 }
01292
01293 return -1;
01294 }
01295
01296 void KPilotLocalLink::addSyncLogEntryImpl(QString const &s)
01297 {
01298 FUNCTIONSETUP;
01299 DEBUGLIBRARY << fname << ": " << s << endl ;
01300 }
01301
01302 bool KPilotLocalLink::installFile(QString const &path, bool deletefile)
01303 {
01304 FUNCTIONSETUP;
01305
01306 QFileInfo srcInfo(path);
01307 QString canonicalSrcPath = srcInfo.dir().canonicalPath() + CSL1("/") + srcInfo.fileName() ;
01308 QString canonicalDstPath = fPath + CSL1("/") + srcInfo.fileName();
01309
01310 if (canonicalSrcPath == canonicalDstPath)
01311 {
01312
01313 return true;
01314 }
01315
01316 KURL src = KURL::fromPathOrURL( canonicalSrcPath );
01317 KURL dst = KURL::fromPathOrURL( canonicalDstPath );
01318
01319 KIO::NetAccess::file_copy(src,dst,-1,true);
01320
01321 if (deletefile)
01322 {
01323 KIO::NetAccess::del(src, 0L);
01324 }
01325
01326 return true;
01327 }
01328
01329 bool KPilotLocalLink::retrieveDatabase( const QString &path, struct DBInfo *db )
01330 {
01331 FUNCTIONSETUP;
01332
01333 QString dbname = Pilot::fromPilot(db->name) + CSL1(".pdb") ;
01334 QString sourcefile = fPath + CSL1("/") + dbname ;
01335 QString destfile = path ;
01336
01337 DEBUGLIBRARY << fname << ": src=" << sourcefile << endl;
01338 DEBUGLIBRARY << fname << ": dst=" << destfile << endl;
01339
01340 QFile in( sourcefile );
01341 if ( !in.exists() )
01342 {
01343 kdWarning() << k_funcinfo<< ": Source file " << sourcefile << " doesn't exist." << endl;
01344 return false;
01345 }
01346 if ( !in.open( IO_ReadOnly | IO_Raw ) )
01347 {
01348 kdWarning() << k_funcinfo << ": Can't read source file " << sourcefile << endl;
01349 return false;
01350 }
01351
01352 QFile out( destfile );
01353 if ( !out.open( IO_WriteOnly | IO_Truncate | IO_Raw ) )
01354 {
01355 kdWarning() << k_funcinfo << ": Can't write destination file " << destfile << endl;
01356 return false;
01357 }
01358
01359 const Q_ULONG BUF_SIZ = 8192 ;
01360 char buf[BUF_SIZ];
01361 Q_LONG r;
01362
01363 while ( (r=in.readBlock(buf,BUF_SIZ))>0 )
01364 {
01365 out.writeBlock(buf,r);
01366 }
01367 out.flush();
01368 in.close();
01369
01370 return out.exists();
01371 }
01372
01373 DBInfoList KPilotLocalLink::getDBList( int, int )
01374 {
01375 FUNCTIONSETUP;
01376 DBInfoList l;
01377 for ( DatabaseDescriptorList::ConstIterator i=d->fDBs.begin();
01378 i != d->fDBs.end(); ++i)
01379 {
01380 l.append( (*i).second );
01381 }
01382 return l;
01383 }
01384
01385
01386 PilotDatabase *KPilotLocalLink::database( const QString &name )
01387 {
01388 FUNCTIONSETUP;
01389 return new PilotLocalDatabase( fPath, name );
01390 }
01391
01392
01393
01394 void KPilotLocalLink::ready()
01395 {
01396 if (fReady)
01397 {
01398 emit deviceReady(this);
01399 }
01400 }
01401