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
00031 #include "options.h"
00032
00033
00034
00035
00036
00037
00038 #ifndef QDIR_H
00039 #include <qdir.h>
00040 #endif
00041
00042 #ifndef QMAP_H
00043 #include <qmap.h>
00044 #endif
00045
00046 #ifndef _KGLOBAL_H
00047 #include <kglobal.h>
00048 #endif
00049
00050 #ifndef _KSTDDIRS_H
00051 #include <kstddirs.h>
00052 #endif
00053
00054 #ifndef _KMESSAGEBOX_H
00055 #include <kmessagebox.h>
00056 #endif
00057
00058 #ifndef _KSIMPLECONFIG_H
00059 #include <ksimpleconfig.h>
00060 #endif
00061
00062 #ifndef _KCONFIG_H
00063 #include <kconfig.h>
00064 #endif
00065
00066 #ifndef _DCOPCLIENT_H
00067 #include <dcopclient.h>
00068 #endif
00069
00070 #ifndef _KDEBUG_H
00071 #include <kdebug.h>
00072 #endif
00073
00074
00075 #ifndef _KPILOT_CONDUITAPP_H
00076 #include "conduitApp.h"
00077 #endif
00078
00079 #ifndef _KPILOT_KPILOTCONFIG_H
00080 #include "kpilotConfig.h"
00081 #endif
00082
00083 #ifndef _KPILOT_KNOTES_CONDUIT_H
00084 #include "knotes-conduit.h"
00085 #endif
00086
00087 #ifndef _KPILOT_SETUPDIALOG_H
00088 #include "setupDialog.h"
00089 #endif
00090
00091 #ifndef _KPILOT_PILOTMEMO_H
00092 #include "pilotMemo.h"
00093 #endif
00094
00095
00096
00097 #ifndef _KPILOT_MD5WRAP_H
00098 #include "md5wrap.h"
00099 #endif
00100
00101
00102
00103
00104
00105
00106 static const char *knotes_conduit_id=
00107 "$Id: knotes-conduit.cc,v 1.20.6.6 2003/03/12 23:31:11 adridg Exp $";
00108
00109
00110
00111
00112
00113
00114
00115 int main(int argc, char* argv[])
00116 {
00117 ConduitApp a(argc,argv,"knotes",
00118 I18N_NOOP("KNotes Conduit"),
00119 KPILOT_VERSION);
00120
00121 a.addAuthor("Adriaan de Groot",
00122 "KNotes Conduit author",
00123 "adridg@sci.kun.nl");
00124
00125 KNotesConduit conduit(a.getMode());
00126 a.setConduit(&conduit);
00127 return a.exec(true );
00128 }
00129
00130
00131 NotesSettings::NotesSettings(const QString &configPath,
00132 const QString ¬esdir,
00133 KConfig& c) :
00134 cP(configPath)
00135 {
00136 FUNCTIONSETUP;
00137
00138 #ifdef DEBUG
00139 DEBUGCONDUIT << fname
00140 << ": Reading note from "
00141 << configPath
00142 << " in dir "
00143 << notesdir
00144 << endl;
00145 #endif
00146
00147 c.setGroup("KPilot");
00148 id = c.readNumEntry("pilotID",0);
00149 checksum = c.readEntry("checksum",QString::null);
00150 csValid = !(checksum.isNull());
00151
00152 c.setGroup("Data");
00153 nN = c.readEntry("name");
00154
00155 QString notedata(notesdir);
00156 notedata.append("/.");
00157 notedata.append(nN);
00158 notedata.append("_data");
00159 if (QFile::exists(notedata))
00160 {
00161 #ifdef DEBUG
00162 DEBUGCONDUIT << fname
00163 << ": Data for note in "
00164 << notedata
00165 << endl;
00166 #endif
00167 dP = notedata;
00168 }
00169 else
00170 {
00171 kdWarning() << __FUNCTION__
00172 << ": No data file for note?"
00173 << " (tried "
00174 << notedata << ")"
00175 << endl;
00176 }
00177 }
00178
00179 QString NotesSettings::computeCheckSum() const
00180 {
00181 FUNCTIONSETUP;
00182
00183 if (dP.isEmpty()) return 0;
00184
00185 QFile f(dP);
00186 if (!f.open(IO_ReadOnly))
00187 {
00188 kdWarning() << __FUNCTION__
00189 << ": Couldn't open file."
00190 << endl;
00191 return QString::null;
00192 }
00193
00194 unsigned char data[PilotMemo::MAX_MEMO_LEN];
00195 int r = f.readBlock((char *)data,(int) PilotMemo::MAX_MEMO_LEN);
00196 if (r<1)
00197 {
00198 kdWarning() << __FUNCTION__
00199 << ": Couldn't read notes file."
00200 << endl;
00201 return QString::null;
00202 }
00203
00204 QString s;
00205 MD5Context md5context;
00206 md5context.update(data,r);
00207 s=md5context.finalize();
00208
00209 return s;
00210 }
00211
00212 int NotesSettings::readNotesData(char *text)
00213 {
00214 FUNCTIONSETUP;
00215
00216
00217
00218
00219 QFile f(dataPath());
00220 int filesize = f.size();
00221
00222 if (filesize > PilotMemo::MAX_MEMO_LEN)
00223 {
00224 kdWarning() << __FUNCTION__
00225 << ": Notes file is too large ("
00226 << filesize
00227 << " bytes) -- truncated to "
00228 << (int) PilotMemo::MAX_MEMO_LEN
00229 << endl;
00230 filesize = PilotMemo::MAX_MEMO_LEN;
00231 }
00232
00233 if (!f.open(IO_ReadOnly))
00234 {
00235 kdWarning() << __FUNCTION__
00236 << ": Couldn't read notes file."
00237 << endl;
00238 return 0;
00239 }
00240
00241 memset(text,0,PilotMemo::MAX_MEMO_LEN+1);
00242 int len = f.readBlock(text,filesize);
00243
00244 #ifdef DEBUG
00245 DEBUGCONDUIT << fname
00246 << ": Read "
00247 << len
00248 << " bytes from note "
00249 << dataPath()
00250 << endl;
00251 #endif
00252
00253 return len;
00254 }
00255
00256 static NotesMap
00257 collectNotes()
00258 {
00259 FUNCTIONSETUP;
00260 NotesMap m;
00261
00262
00263
00264
00265 QString str_notedir = KGlobal::dirs()->
00266 saveLocation( "appdata", "notes/" );
00267
00268 #ifdef DEBUG
00269 {
00270 DEBUGCONDUIT << fname << ": Notes dir = " << str_notedir << endl;
00271 }
00272 #endif
00273
00274 QDir notedir( str_notedir );
00275 QStringList notes = notedir.entryList( QDir::Files, QDir::Name );
00276 QStringList::ConstIterator i;
00277
00278 for (i=notes.begin() ; i !=notes.end(); ++i)
00279 {
00280 QString notename,notedata ;
00281 KSimpleConfig *c = 0L;
00282 int version ;
00283
00284 #ifdef DEBUG
00285 {
00286 DEBUGCONDUIT << fname << ": Reading note " << *i << endl;
00287 }
00288 #endif
00289 c = new KSimpleConfig( notedir.absFilePath(*i));
00290
00291 c->setGroup("General");
00292 version = c->readNumEntry("version",1);
00293 if (version<2)
00294 {
00295 kdWarning() << __FUNCTION__
00296 << ": Skipping old-style KNote"
00297 << *i
00298 << endl;
00299 goto EndNote;
00300 }
00301
00302 {
00303 NotesSettings n(notedir.absFilePath(*i),
00304 notedir.absPath(),
00305 *c);
00306 m.insert(*i,n);
00307 }
00308
00309 EndNote:
00310 delete c;
00311 }
00312
00313 return m;
00314 }
00315
00316
00317 static NotesMap::Iterator *
00318 findID(NotesMap& m,unsigned long id)
00319 {
00320 FUNCTIONSETUP;
00321
00322 NotesMap::Iterator *i = new NotesMap::Iterator;
00323
00324 for ((*i)=m.begin(); (*i)!=m.end(); ++(*i))
00325 {
00326 const NotesSettings& r = (*(*i));
00327
00328 if (r.pilotID()==id)
00329 {
00330 #ifdef DEBUG
00331 {
00332 DEBUGCONDUIT << fname
00333 << ": Found ID "
00334 << id
00335 << " in note "
00336 << r.configPath()
00337 << endl;
00338 }
00339 #endif
00340 return i;
00341 }
00342 }
00343
00344 delete i;
00345
00346 #ifdef DEBUG
00347 {
00348 DEBUGCONDUIT << fname
00349 << ": ID "
00350 << id
00351 << " not found."
00352 << endl;
00353 }
00354 #endif
00355
00356 return 0L;
00357 }
00358
00359
00360
00361 KNotesConduit::KNotesConduit(eConduitMode mode) :
00362 BaseConduit(mode),
00363 fDeleteNoteForMemo(false)
00364 {
00365 FUNCTIONSETUP;
00366 #ifdef DEBUG
00367 DEBUGCONDUIT<<knotes_conduit_id<<endl;
00368 #endif
00369
00370 }
00371
00372 KNotesConduit::~KNotesConduit()
00373 {
00374 FUNCTIONSETUP;
00375
00376 }
00377
00378 void
00379 KNotesConduit::readConfig()
00380 {
00381 FUNCTIONSETUP;
00382
00383 KConfig& c = KPilotConfig::getConfig(KNotesOptions::KNotesGroup);
00384 getDebugLevel(c);
00385 fDeleteNoteForMemo = c.readBoolEntry("DeleteNoteForMemo",false);
00386 #ifdef DEBUG
00387 {
00388 DEBUGCONDUIT << fname
00389 << ": Settings "
00390 << "DeleteNoteForMemo="
00391 << fDeleteNoteForMemo
00392 << endl;
00393 }
00394 #endif
00395 }
00396
00397 void
00398 KNotesConduit::doSync()
00399 {
00400 FUNCTIONSETUP;
00401
00402 readConfig();
00403
00404 NotesMap m = collectNotes();
00405
00406
00407
00408
00409 int newCount = notesToPilot(m);
00410 int oldCount = pilotToNotes(m);
00411
00412 if (newCount || oldCount)
00413 {
00414 QString msg = i18n("Changed %1/%2 Memos/Notes")
00415 .arg(newCount)
00416 .arg(oldCount);
00417 addSyncLogMessage(msg);
00418
00419 #ifdef DEBUG
00420 DEBUGCONDUIT << fname
00421 << ": "
00422 << msg
00423 << endl;
00424 #endif
00425 }
00426
00427 DCOPClient *dcopptr = KApplication::kApplication()->dcopClient();
00428 if (!dcopptr)
00429 {
00430 kdWarning() << __FUNCTION__
00431 << ": Can't get DCOP client."
00432 << endl;
00433 return;
00434 }
00435
00436 QByteArray data;
00437 if (dcopptr -> send("knotes",
00438 "KNotesIface",
00439 "rereadNotesDir()",
00440 data))
00441 {
00442 kdWarning() << __FUNCTION__
00443 << ": Couldn't tell KNotes to re-read notes."
00444 << endl;
00445 }
00446 }
00447
00448
00449 bool KNotesConduit::addNewNote(NotesSettings& s)
00450 {
00451 FUNCTIONSETUP;
00452
00453
00454 char text[PilotMemo::MAX_MEMO_LEN+1];
00455 if (!s.readNotesData(text))
00456 {
00457 return false;
00458 }
00459
00460 PilotMemo *memo = new PilotMemo(text,0,0,0);
00461 PilotRecord *rec = memo->pack();
00462 unsigned long id = writeRecord(rec);
00463
00464 KSimpleConfig *c = new KSimpleConfig(s.configPath());
00465 c->setGroup("KPilot");
00466 c->writeEntry("pilotID",id);
00467 c->writeEntry("checksum",s.computeCheckSum());
00468
00469 s.setId(id);
00470
00471 delete c;
00472 delete rec;
00473 delete memo;
00474
00475 return true;
00476 }
00477
00478 bool KNotesConduit::changeNote(NotesSettings& s)
00479 {
00480 FUNCTIONSETUP;
00481
00482 char text[PilotMemo::MAX_MEMO_LEN+1];
00483 if (!s.readNotesData(text))
00484 {
00485 return false;
00486 }
00487
00488 return false;
00489 }
00490
00491
00492 int KNotesConduit::notesToPilot(NotesMap& m)
00493 {
00494 FUNCTIONSETUP;
00495 NotesMap::Iterator i;
00496 int count=0;
00497
00498 #ifdef DEBUG
00499 DEBUGCONDUIT << fname
00500 << ": Adding new memos to pilot"
00501 << endl;
00502 #endif
00503
00504
00505 for (i=m.begin(); i!=m.end(); ++i)
00506 {
00507 NotesSettings& s=(*i);
00508
00509 if (s.isNew())
00510 {
00511 addNewNote(s);
00512 count++;
00513 }
00514 if (s.isChanged())
00515 {
00516 changeNote(s);
00517 count++;
00518 }
00519 }
00520
00521 return count;
00522 }
00523
00524 bool KNotesConduit::newMemo(NotesMap& m,unsigned long id,PilotMemo *memo)
00525 {
00526 FUNCTIONSETUP;
00527
00528 QString noteName = memo->sensibleTitle();
00529
00530
00531
00532
00533 QString str_notedir = KGlobal::dirs()->
00534 saveLocation( "appdata", "notes/" );
00535
00536 #ifdef DEBUG
00537 {
00538 DEBUGCONDUIT << fname << ": Notes dir = " << str_notedir << endl;
00539 }
00540 #endif
00541
00542 QDir notedir( str_notedir );
00543
00544 if (notedir.exists(noteName))
00545 {
00546 noteName += QString::number(id);
00547 }
00548
00549 if (notedir.exists(noteName))
00550 {
00551 #ifdef DEBUG
00552 DEBUGCONDUIT << fname
00553 << ": Note " << noteName
00554 << " already exists!"
00555 << endl;
00556 #endif
00557 return false;
00558 }
00559
00560 QString dataName = "." + noteName + "_data" ;
00561 bool success = false;
00562 #ifdef DEBUG
00563 {
00564 DEBUGCONDUIT << fname
00565 << ": Creating note "
00566 << noteName
00567 << endl;
00568 }
00569 #endif
00570
00571 {
00572 QFile file(notedir.absFilePath(dataName));
00573 file.open(IO_WriteOnly | IO_Truncate);
00574 if (file.isOpen())
00575 {
00576 file.writeBlock(memo->text(),strlen(memo->text()));
00577 success = true;
00578 }
00579 file.close();
00580 }
00581
00582
00583 if (success)
00584 {
00585 KConfig *c = new KSimpleConfig( notedir.absFilePath(noteName));
00586
00587 c->setGroup("General");
00588 c->writeEntry("version",2);
00589 c->setGroup("KPilot");
00590 c->writeEntry("pilotID",id);
00591 c->setGroup("Data");
00592 c->writeEntry("name",noteName);
00593 c->sync();
00594
00595 delete c;
00596 }
00597
00598 if (success)
00599 {
00600 NotesSettings n(noteName,
00601 notedir.absFilePath(noteName),
00602 notedir.absFilePath(dataName),
00603 id);
00604 m.insert(noteName,n);
00605 }
00606
00607 return success;
00608 }
00609
00610 bool KNotesConduit::changeMemo(NotesMap& m,NotesMap::Iterator i,PilotMemo *memo)
00611 {
00612 FUNCTIONSETUP;
00613
00614
00615
00616
00617
00618
00619 (void) m;
00620 NotesSettings n = *i;
00621 #ifdef DEBUG
00622 {
00623 DEBUGCONDUIT << fname
00624 << ": Updating note "
00625 << n.configPath()
00626 << endl;
00627 }
00628 #endif
00629 QFile file(n.dataPath());
00630 file.open(IO_WriteOnly | IO_Truncate);
00631 if (file.isOpen())
00632 {
00633 file.writeBlock(memo->text(),strlen(memo->text()));
00634 #ifdef DEBUG
00635 {
00636 DEBUGCONDUIT << fname
00637 << ": Succesfully updated memo "
00638 << n.configPath()
00639 << endl;
00640 }
00641 #endif
00642
00643 return true;
00644 }
00645 else
00646 {
00647 return false;
00648 }
00649 }
00650
00651 bool KNotesConduit::deleteNote(NotesMap& m,NotesMap::Iterator *i,
00652 unsigned long id)
00653 {
00654 FUNCTIONSETUP;
00655
00656 if (!i)
00657 {
00658 #ifdef DEBUG
00659 {
00660 DEBUGCONDUIT << fname
00661 << ": Unknown Pilot memo "
00662 << id
00663 << " has been deleted."
00664 << endl;
00665 }
00666 #endif
00667 return false;
00668 }
00669
00670 #ifdef DEBUG
00671 {
00672 if (fDeleteNoteForMemo)
00673 {
00674 DEBUGCONDUIT << fname
00675 << ": Deleting pilot memo "
00676 << id
00677 << endl;
00678 }
00679 else
00680 {
00681 DEBUGCONDUIT << fname
00682 << ": Pilot memo "
00683 << id
00684 << " has been deleted, note remains."
00685 << endl;
00686 return false;
00687 }
00688 }
00689 #endif
00690
00691 NotesSettings n = *(*i);
00692
00693 #ifdef DEBUG
00694 {
00695 DEBUGCONDUIT << fname
00696 << ": Deleting note "
00697 << n.configPath()
00698 << endl;
00699 }
00700 #endif
00701
00702 QFile::remove(n.dataPath());
00703 QFile::remove(n.configPath());
00704
00705 m.remove(*i);
00706
00707 return true;
00708 }
00709
00710
00711 int KNotesConduit::pilotToNotes(NotesMap& m)
00712 {
00713 FUNCTIONSETUP;
00714
00715 PilotRecord *rec;
00716 int count=0;
00717 NotesMap::Iterator *i;
00718
00719 while ((rec=readNextModifiedRecord()))
00720 {
00721 unsigned long id = rec->getID();
00722 bool success;
00723
00724 success=false;
00725
00726 #ifdef DEBUG
00727 DEBUGCONDUIT << fname
00728 << ": Read Pilot record with ID "
00729 << id
00730 << endl;
00731 #endif
00732
00733 i = findID(m,id);
00734 if (rec->getAttrib() & dlpRecAttrDeleted)
00735 {
00736 success=deleteNote(m,i,id);
00737 }
00738 else
00739 {
00740 PilotMemo *memo = new PilotMemo(rec);
00741 if (i)
00742 {
00743 success=changeMemo(m,*i,memo);
00744 }
00745 else
00746 {
00747 success=newMemo(m,id,memo);
00748 }
00749 delete memo;
00750 }
00751 delete rec;
00752
00753 if (success)
00754 {
00755 count++;
00756 }
00757 }
00758
00759
00760 DCOPClient *dcopptr = KApplication::kApplication()->dcopClient();
00761 if (!dcopptr)
00762 {
00763 kdWarning() << __FUNCTION__
00764 << ": Can't get DCOP client."
00765 << endl;
00766 return count;
00767 }
00768
00769 QByteArray data;
00770 if (dcopptr -> send("knotes",
00771 "KNotesIface",
00772 "rereadNotesDir()",
00773 data))
00774 {
00775 #ifdef DEBUG
00776 DEBUGCONDUIT << fname
00777 << ": DCOP to KNotes successful."
00778 << endl;
00779 #endif
00780 }
00781 else
00782 {
00783 kdWarning() << __FUNCTION__
00784 << ": Couldn't tell KNotes about new notes."
00785 << endl;
00786 }
00787
00788 return count;
00789 }
00790
00791
00792
00793
00794
00795 QWidget*
00796 KNotesConduit::aboutAndSetup()
00797 {
00798 FUNCTIONSETUP;
00799
00800 return new KNotesOptions(0L);
00801 }
00802
00803 const char *
00804 KNotesConduit::dbInfo()
00805 {
00806 return "MemoDB";
00807 }
00808
00809
00810
00811 void
00812 KNotesConduit::doTest()
00813 {
00814 FUNCTIONSETUP;
00815 DCOPClient *dcopptr = KApplication::kApplication()->dcopClient();
00816 if (!dcopptr)
00817 {
00818 kdWarning() << __FUNCTION__
00819 << ": Can't get DCOP client."
00820 << endl;
00821 return;
00822 }
00823
00824 NotesMap m = collectNotes();
00825
00826
00827 NotesMap::Iterator i;
00828 for (i=m.begin(); i!=m.end(); ++i)
00829 {
00830 if ((*i).pilotID())
00831 {
00832 #ifdef DEBUG
00833 DEBUGCONDUIT << fname
00834 << ": Showing note "
00835 << (*i).name()
00836 << endl;
00837 #endif
00838
00839 QByteArray data;
00840 QDataStream arg(data,IO_WriteOnly);
00841 arg << (*i).name() ;
00842 if (dcopptr -> send("knotes",
00843 "KNotesIface",
00844 "showNote(QString)",
00845 data))
00846 {
00847 #ifdef DEBUG
00848 DEBUGCONDUIT << fname
00849 << ": DCOP send successful"
00850 << endl;
00851 #endif
00852 }
00853 else
00854 {
00855 kdWarning() << __FUNCTION__
00856 << ": DCOP send failed."
00857 << endl;
00858 }
00859 }
00860 else
00861 {
00862 #ifdef DEBUG
00863 DEBUGCONDUIT << fname
00864 << ": Note "
00865 << (*i).name()
00866 << " not in Pilot"
00867 << endl;
00868 #endif
00869 }
00870 #ifdef DEBUG
00871 DEBUGCONDUIT << fname
00872 << ": Checksum = "
00873 << (*i).computeCheckSum()
00874 << endl;
00875 #endif
00876 }
00877
00878 (void) knotes_conduit_id;
00879 }
00880