kpilot

sysinfo-conduit.cc

Go to the documentation of this file.
00001 /* KPilot
00002 **
00003 ** Copyright (C) 2003 by Reinhold Kainhofer
00004 **
00005 */
00006 
00007 /*
00008 ** This program is free software; you can redistribute it and/or modify
00009 ** it under the terms of the GNU General Public License as published by
00010 ** the Free Software Foundation; either version 2 of the License, or
00011 ** (at your option) any later version.
00012 **
00013 ** This program is distributed in the hope that it will be useful,
00014 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00016 ** GNU General Public License for more details.
00017 **
00018 ** You should have received a copy of the GNU General Public License
00019 ** along with this program in a file called COPYING; if not, write to
00020 ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00021 ** MA 02110-1301, USA.
00022 */
00023 
00024 /*
00025 ** Bug reports and questions can be sent to kde-pim@kde.org.
00026 */
00027 
00028 #include "options.h"
00029 
00030 #include <pi-version.h>
00031 
00032 #include <qtimer.h>
00033 #include <qdir.h>
00034 #include <qfileinfo.h>
00035 #include <qregexp.h>
00036 #include <kconfig.h>
00037 #include <kdebug.h>
00038 
00039 #include <pilotSysInfo.h>
00040 #include <pilotUser.h>
00041 #include <pilotCard.h>
00042 #include <kpilotlink.h>
00043 #include <kstandarddirs.h>
00044 #include <pilotSerialDatabase.h>
00045 
00046 #include <sys/utsname.h>
00047 
00048 #include "sysinfo-factory.h"
00049 #include "sysinfo-conduit.moc"
00050 #include "sysinfoSettings.h"
00051 
00052 const QString SysInfoConduit::defaultpage = CSL1("KPilot System Information Page\n"
00053 "==============================\n"
00054 "(Kpilot was unable to find the correct template file, \n"
00055 "so this simple template was used.)\n\n"
00056 "<!--#ifhardware#\n"
00057 "-) Hardware Information\n"
00058 "     DeviceID:      #deviceid#\n"
00059 "     Device name:   #devicename#\n"
00060 "     Device model:  #devicemodel#\n"
00061 "     Manufacturer:  #manufacturer#\n"
00062 "     Connected via: #devicetype#\n"
00063 "#endifhardware#-->\n"
00064 "\n"
00065 "<!--#ifuser#\n"
00066 "-) User Information\n"
00067 "     Handheld User Name: #username#\n"
00068 "     Handheld Password:  #pw#\n"
00069 "     Handheld User ID:   #uid#\n"
00070 "     Viewer ID:          #viewerid#\n"
00071 "#endifuser#-->\n"
00072 "\n"
00073 "<!--#ifmemory#\n"
00074 "-) Memory Information\n"
00075 "     ROM:       #rom# kB total\n"
00076 "     Total RAM: #totalmem# kB total\n"
00077 "     Free RAM:  #freemem# kB free\n"
00078 "#endifmemory#-->\n"
00079 "\n"
00080 "<!--#ifstorage#\n"
00081 "-) Storage Information\n"
00082 "     Number of cards: #cards#\n"
00083 "     Memory on cards: #storagemem#\n"
00084 "#endifstorage#-->\n"
00085 "\n"
00086 "<!--#ifdblist#\n"
00087 "-) List of Databases on Handheld\n"
00088 "     Available Databases: #dblist(%1,)#\n"
00089 "#endifdblist#-->\n"
00090 "\n"
00091 "<!--#ifrecords#\n"
00092 "-) Number of addresses, to-dos, events, and memos\n"
00093 "     Addresses: #addresses# entries in Addressbook\n"
00094 "     Events:    #events# entries in Calendar\n"
00095 "     To-dos:    #todos# entries in To-do list\n"
00096 "     Memos:     #memos# memos\n"
00097 "#endifrecords#-->\n"
00098 "\n"
00099 "<!--#ifsync#\n"
00100 "-) Synchronization Information\n"
00101 "     Last sync attempt:      #lastsync#\n"
00102 "     Last successful sync:  #lastsuccsync#\n"
00103 "     Last sync with PC (ID): #lastsyncpc#\n"
00104 "#endifsync#-->\n"
00105 "\n"
00106 "<!--#ifpcversion#\n"
00107 "-) Version Information (Desktop)\n"
00108 "     Operating System:   #os#\n"
00109 "     Hostname:           #hostname#\n"
00110 "     Qt Version:         #qt#\n"
00111 "     KDE Version:        #kde#\n"
00112 "     KPilot Version:     #kpilot#\n"
00113 "     Pilot-Link Version: #pilotlink#\n"
00114 "#endifpcversion#-->\n"
00115 "\n"
00116 "<!--#ifpalmversion#\n"
00117 "-) Version Information (Handheld)\n"
00118 "     PalmOS: #palmos#\n"
00119 "#endifpalmversion#-->\n"
00120 "\n"
00121 "<!--#ifdebug#\n"
00122 "-) Debug Information\n"
00123 "     #debug#\n"
00124 "#endifdebug#-->\n"
00125 "\n"
00126 "------------------------------------------------------------\n"
00127 "Page created <!--#date#--> by the KPilot System Information conduit.\n"
00128 "");
00129 
00130 
00145 // Something to allow us to check what revision
00146 // the modules are that make up a binary distribution.
00147 
00148 extern "C"
00149 {
00150 
00151 unsigned long version_conduit_sysinfo = Pilot::PLUGIN_API;
00152 
00153 }
00154 
00155 
00156 
00157 SysInfoConduit::SysInfoConduit(KPilotLink * o,
00158     const char *n,
00159     const QStringList & a) :
00160     ConduitAction(o, n, a)
00161 {
00162     FUNCTIONSETUP;
00163     fConduitName=i18n("System Information");
00164 }
00165 
00166 
00167 
00168 SysInfoConduit::~SysInfoConduit()
00169 {
00170     FUNCTIONSETUP;
00171 }
00172 
00173 
00174 
00175 void SysInfoConduit::readConfig()
00176 {
00177     fOutputFile = SysinfoSettings::outputFile();
00178     fOutputType = (eOutputTypeEnum) SysinfoSettings::outputFormat();
00179     fTemplateFile = SysinfoSettings::templateFile();
00180     fHardwareInfo = SysinfoSettings::hardwareInfo();
00181     fUserInfo = SysinfoSettings::userInfo();
00182     fMemoryInfo = SysinfoSettings::memoryInfo();
00183     fStorageInfo = SysinfoSettings::storageInfo();
00184     fDBList = SysinfoSettings::databaseList();
00185     fRecordNumber = SysinfoSettings::recordNumbers();
00186     fSyncInfo = SysinfoSettings::syncInfo();
00187     fKDEVersion = SysinfoSettings::kDEVersion();
00188     fPalmOSVersion = SysinfoSettings::palmOSVersion();
00189     fDebugInfo = SysinfoSettings::debugInformation();
00190 }
00191 
00192 
00193 /* virtual */ bool SysInfoConduit::exec()
00194 {
00195     FUNCTIONSETUP;
00196 
00197     readConfig();
00198 
00199     QTimer::singleShot(0, this, SLOT(hardwareInfo()));
00200     return true;
00201 }
00202 
00203 void SysInfoConduit::hardwareInfo()
00204 {
00205     FUNCTIONSETUP;
00206     if (fHardwareInfo) {
00207         QString unknown = i18n("unknown");
00208 
00209         /* Retrieve values for
00210         * - #deviceid#
00211         * - #devicename#
00212         * - #devicemodel#
00213         * - #manufactorer#
00214         * - #devicetype#
00215         */
00216         KPilotSysInfo sysinfo = fHandle->getSysInfo();
00217         fValues[CSL1("deviceid")] = QString::fromLatin1(sysinfo.getProductID());
00218 
00219         const KPilotCard *device = fHandle->getCardInfo();
00220         if (device)
00221         {
00222             fValues[CSL1("devicename")] = QString::fromLatin1(device->getCardName());
00223             fValues[CSL1("devicemodel")] = unknown;  // TODO
00224             fValues[CSL1("manufacturer")] = QString::fromLatin1(device->getCardManufacturer());
00225         }
00226         else
00227         {
00228             fValues[CSL1("devicename")] = unknown;
00229             fValues[CSL1("devicemodel")] = unknown;
00230             fValues[CSL1("manufacturer")] = unknown;
00231         }
00232 
00233         fValues[CSL1("devicetype")] = unknown;
00234 
00235         KPILOT_DELETE(device);
00236         keepParts.append(CSL1("hardware"));
00237     } else removeParts.append(CSL1("hardware"));
00238     QTimer::singleShot(0, this, SLOT(userInfo()));
00239 }
00240 
00241 void SysInfoConduit::userInfo()
00242 {
00243     FUNCTIONSETUP;
00244     if (fUserInfo)
00245     {
00246         /* Retrieve values for
00247          * - #username#
00248          * - #uid#
00249          */
00250         KPilotUser user=fHandle->getPilotUser();
00251         fValues[CSL1("username")] = user.name();
00252         if (user.passwordLength()>0)
00253         {
00254             fValues[CSL1("pw")] = i18n("Password set");
00255         }
00256         else
00257         {
00258             fValues[CSL1("pw")] = i18n("No password set");
00259         }
00260         fValues[CSL1("uid")] = QString::number(user.data()->userID);
00261         fValues[CSL1("viewerid")] = QString::number(user.data()->viewerID);
00262         keepParts.append(CSL1("user"));
00263     }
00264     else
00265     {
00266         removeParts.append(CSL1("user"));
00267     }
00268     QTimer::singleShot(0, this, SLOT(memoryInfo()));
00269 }
00270 
00271 void SysInfoConduit::memoryInfo()
00272 {
00273     FUNCTIONSETUP;
00274     if (fMemoryInfo) {
00275         /* Retrieve values for
00276          * - #rom#
00277          * - #totalmem#
00278          * - #freemem#
00279          */
00280         const KPilotCard *device = fHandle->getCardInfo();
00281         if (device)
00282         {
00283             fValues[CSL1("rom")] =  QString::number(device->getRomSize()/1024);
00284             fValues[CSL1("totalmem")] =  QString::number(device->getRamSize()/1024);
00285             fValues[CSL1("freemem")] =  QString::number(device->getRamFree()/1024);
00286         }
00287         keepParts.append(CSL1("memory"));
00288     } else removeParts.append(CSL1("memory"));
00289     QTimer::singleShot(0, this, SLOT(storageInfo()));
00290 }
00291 
00292 void SysInfoConduit::storageInfo()
00293 {
00294     FUNCTIONSETUP;
00295     if (fStorageInfo) {
00296         /* Retrieve values for
00297          * - $cards$
00298          */
00299         const KPilotCard *device = fHandle->getCardInfo(1);
00300         if (device) {
00301             fValues[CSL1("cards")] = CSL1("%1 (%2, %3 kB of %3 kB free)")
00302                 .arg(QString::fromLatin1(device->getCardName()))
00303                 .arg(QString::fromLatin1(device->getCardManufacturer()))
00304                 .arg(device->getRamFree()/1024)
00305                 .arg(device->getRamSize()/1024);
00306             KPILOT_DELETE(device);
00307         } else {
00308             fValues[CSL1("cards")] = i18n("No Cards available via pilot-link");
00309         }
00310         keepParts.append(CSL1("storage"));
00311     } else removeParts.append(CSL1("storage"));
00312     QTimer::singleShot(0, this, SLOT(dbListInfo()));
00313 }
00314 
00315 void SysInfoConduit::dbListInfo()
00316 {
00317     FUNCTIONSETUP;
00318     if (fDBList) {
00319         /* Retrieve values for
00320          * - #dblist(structure)#
00321          */
00322         dblist=deviceLink()->getDBList();
00323         keepParts.append(CSL1("dblist"));
00324     } else removeParts.append(CSL1("dblist"));
00325     QTimer::singleShot(0, this, SLOT(recNumberInfo()));
00326 }
00327 
00328 void SysInfoConduit::recNumberInfo()
00329 {
00330     FUNCTIONSETUP;
00331     if (fRecordNumber) {
00332         /* Retrieve values for
00333          * - #addresses#
00334          * - #events#
00335          * - #todos#
00336          * - #memos#
00337          */
00338         PilotDatabase *fDatabase = 0L;
00339         QString ERROR = CSL1("ERROR");
00340         fValues[CSL1("addresses")] = ERROR;
00341         fValues[CSL1("events")] = ERROR;
00342         fValues[CSL1("todos")] = ERROR;
00343         fValues[CSL1("memos")] = ERROR;
00344         fDatabase = deviceLink()->database(CSL1("AddressDB"));
00345         if (fDatabase) {
00346             fValues[CSL1("addresses")] = QString::number(fDatabase->recordCount());
00347             KPILOT_DELETE(fDatabase);
00348         }
00349         fDatabase = deviceLink()->database(CSL1("DatebookDB"));
00350         if (fDatabase) {
00351             fValues[CSL1("events")] = QString::number(fDatabase->recordCount());
00352             KPILOT_DELETE(fDatabase);
00353         }
00354         fDatabase = deviceLink()->database(CSL1("ToDoDB"));
00355         if (fDatabase) {
00356             fValues[CSL1("todos")] = QString::number(fDatabase->recordCount());
00357             KPILOT_DELETE(fDatabase);
00358         }
00359         fDatabase = deviceLink()->database(CSL1("MemoDB"));
00360         if (fDatabase) {
00361             fValues[CSL1("memos")] = QString::number(fDatabase->recordCount());
00362             KPILOT_DELETE(fDatabase);
00363         }
00364         keepParts.append(CSL1("records"));
00365     } else removeParts.append(CSL1("records"));
00366     QTimer::singleShot(0, this, SLOT(syncInfo()));
00367 }
00368 
00369 void SysInfoConduit::syncInfo()
00370 {
00371     FUNCTIONSETUP;
00372     if (fSyncInfo) {
00373         /* Retrieve values for
00374          * - #lastsync#
00375          * - #lastsuccsync#
00376          * - #lastsyncpc#
00377          */
00378         KPilotUser user = deviceLink()->getPilotUser();
00379         time_t lastsync = user.getLastSyncDate();
00380         QDateTime qlastsync;
00381         qlastsync.setTime_t(lastsync);
00382         fValues[CSL1("lastsync")] = qlastsync.toString(Qt::LocalDate);
00383         lastsync = user.getLastSuccessfulSyncDate();
00384         qlastsync.setTime_t(lastsync);
00385         fValues[CSL1("lastsuccsync")] = qlastsync.toString(Qt::LocalDate);
00386         fValues[CSL1("lastsyncpc")] = QString::number(user.getLastSyncPC());
00387         keepParts.append(CSL1("sync"));
00388     } else removeParts.append(CSL1("sync"));
00389     QTimer::singleShot(0, this, SLOT(pcVersionInfo()));
00390 }
00391 
00392 void SysInfoConduit::pcVersionInfo()
00393 {
00394     FUNCTIONSETUP;
00395     if (fKDEVersion) {
00396         /* Retrieve values for
00397          * - #os#
00398          * - #qt#
00399          * - #kde#
00400          * - #kpilot#
00401          * - #pilotlink#
00402          */
00403         fValues[CSL1("kpilot")] = QString::fromLatin1(KPILOT_VERSION);
00404         fValues[CSL1("kde")] = i18n("unknown");
00405         fValues[CSL1("qt")] = i18n("unknown");
00406         fValues[CSL1("os")] = i18n("unknown");
00407         fValues[CSL1("hostname")] = i18n("unknown");
00408         struct utsname name;
00409         if (uname (&name) >= 0) {
00410             fValues[CSL1("os")] = CSL1("%1 %3, %5")
00411                 .arg(QString::fromLatin1(name.sysname))
00412                 .arg(QString::fromLatin1(name.release))
00413                 .arg(QString::fromLatin1(name.machine));
00414             fValues[CSL1("hostname")] = CSL1("%2").arg(QString::fromLatin1(name.nodename));
00415         }
00416 #ifdef KDE_VERSION_STRING
00417         fValues[CSL1("kde")] = QString::fromLatin1(KDE_VERSION_STRING);
00418 #endif
00419 #ifdef QT_VERSION_STR
00420         fValues[CSL1("qt")] = QString::fromLatin1(QT_VERSION_STR);
00421 #endif
00422         fValues[CSL1("pilotlink")] = CSL1("%1.%2.%3%4")
00423             .arg(PILOT_LINK_VERSION)
00424             .arg(PILOT_LINK_MAJOR)
00425             .arg(PILOT_LINK_MINOR)
00426 #ifdef PILOT_LINK_PATCH
00427             .arg(QString::fromLatin1(PILOT_LINK_PATCH));
00428 #else
00429             .arg(QString());
00430 #endif
00431         keepParts.append(CSL1("pcversion"));
00432     } else removeParts.append(CSL1("pcversion"));
00433     QTimer::singleShot(0, this, SLOT(palmVersionInfo()));
00434 }
00435 
00436 void SysInfoConduit::palmVersionInfo()
00437 {
00438     FUNCTIONSETUP;
00439     if (fPalmOSVersion) {
00440         /* Retrieve values for
00441          * - #palmos#
00442          */
00443 /*      fValues["palmos"] = QString("PalmOS %1.%2 (compat %3.%4)")
00444             .arg(fHandle->getSysInfo()->getMajorVersion())
00445             .arg(fHandle->getSysInfo()->getMinorVersion())
00446             .arg(fHandle->getSysInfo()->getCompatMajorVersion())
00447             .arg(fHandle->getSysInfo()->getCompatMinorVersion());*/
00448         KPilotSysInfo i = deviceLink()->getSysInfo();
00449         fValues[CSL1("palmos")] = CSL1("PalmOS %1.%2").arg(i.getMajorVersion()).arg(i.getMinorVersion());
00450 
00451         keepParts.append(CSL1("palmversion"));
00452     } else removeParts.append(CSL1("palmversion"));
00453     QTimer::singleShot(0, this, SLOT(debugInfo()));
00454 }
00455 
00456 void SysInfoConduit::debugInfo()
00457 {
00458     FUNCTIONSETUP;
00459     if (fDebugInfo) {
00460         /* Retrieve values for
00461          * - #debug#
00462          */
00463         fValues[CSL1("debug")] = i18n("No debug data");
00464         keepParts.append(CSL1("debug"));
00465     } else removeParts.append(CSL1("debug"));
00466     QTimer::singleShot(0, this, SLOT(writeFile()));
00467 }
00468 
00469 void SysInfoConduit::writeFile()
00470 {
00471     FUNCTIONSETUP;
00472 
00473     fValues[CSL1("date")] = QDateTime::currentDateTime().toString(Qt::LocalDate);
00474 
00475     QString output;
00476     // Open the template file
00477     QString templatefile;
00478     switch(fOutputType)
00479     {
00480         case eOutputText:
00481             templatefile=locate("data", CSL1("kpilot/sysinfoconduit/Template.txt"));
00482             break;
00483         case eOutputTemplate:
00484             templatefile=fTemplateFile;
00485             break;
00486         case eOutputHTML:
00487         default:
00488             templatefile=locate("data", CSL1("kpilot/sysinfoconduit/Template.html"));
00489             break;
00490     }
00491 
00492     // Read in the template, close the file
00493     bool loaded=false;
00494     if (!templatefile.isEmpty()){
00495 #ifdef DEBUG
00496         DEBUGKPILOT<<"Loading template file "<<templatefile<<endl;
00497 #endif
00498         QFile infile(templatefile);
00499         if (infile.open(IO_ReadOnly)) {
00500             QTextStream instream(&infile);
00501             output = instream.read();
00502             infile.close();
00503             loaded=true;
00504         }
00505     }
00506 
00507     if (!loaded)
00508     {
00509         WARNINGKPILOT << "Loading template file " << templatefile
00510             <<" failed. Using default template instead." << endl;
00511         output=defaultpage;
00512     }
00513 
00514     // Remove all parts not extracted
00515     for ( QStringList::Iterator it = removeParts.begin(); it != removeParts.end(); ++it ) {
00516         QRegExp re(CSL1("<!--#if%1#.*#endif%1#-->").arg(*it).arg(*it));
00517         re.setMinimal(true);
00518         output.remove(re);
00519     }
00520     for ( QStringList::Iterator it = keepParts.begin(); it != keepParts.end(); ++it ) {
00521         QRegExp re(CSL1("<!--#if%1#(.*)#endif%1#-->").arg(*it).arg(*it));
00522         re.setMinimal(true);
00523         output.replace(re, CSL1("\\1"));
00524     }
00525 
00526     // Do a loop through all keys in fValues
00527     QMap<QString,QString>::Iterator it;
00528     for ( it = fValues.begin(); it != fValues.end(); ++it ) {
00529         output.replace(CSL1("#%1#").arg(it.key()), it.data());
00530     }
00531 
00532     // Insert the list of databases
00533     QRegExp re(CSL1("#dblist\\[(.*)\\]#"));
00534     re.setMinimal(true);
00535     while (re.search(output)>=0){
00536         QString dbstring;
00537         QString subpatt=re.cap(1);
00538         for (KPilotLink::DBInfoList::ConstIterator i = dblist.begin(); i != dblist.end(); ++i ) {
00539             DBInfo dbi = *i;
00540             QString newpatt(subpatt);
00541             char tmpchr[5];
00542             ::memset(&tmpchr[0], 0, 5);
00543             /* Patterns for the dblist argument:
00544              * %0 .. Database name
00545              * %1 .. type
00546              * %2 .. creator
00547              * %3 .. index
00548              * %4 .. flags
00549              * %5 .. miscFlags
00550              * %6 .. version
00551              * %7 .. createDate
00552              * %8 .. modifyDate
00553              * %9 .. backupDate
00554              */
00555             newpatt.replace(CSL1("%0"), QString::fromLatin1(dbi.name));
00556             set_long(&tmpchr[0],dbi.type);
00557             newpatt.replace(CSL1("%1"), QString::fromLatin1(tmpchr));
00558             set_long(&tmpchr[0],dbi.creator);
00559             newpatt.replace(CSL1("%2"), QString::fromLatin1(tmpchr));
00560             newpatt.replace(CSL1("%3"), QString::number(dbi.index));
00561             newpatt.replace(CSL1("%4"), QString::number(dbi.flags));
00562             newpatt.replace(CSL1("%5"), QString::number(dbi.miscFlags));
00563             newpatt.replace(CSL1("%6"), QString::number(dbi.version));
00564             QDateTime tm;
00565             tm.setTime_t(dbi.createDate);
00566             newpatt.replace(CSL1("%7"), tm.toString(Qt::LocalDate));
00567             tm.setTime_t(dbi.modifyDate);
00568             newpatt.replace(CSL1("%8"), tm.toString(Qt::LocalDate));
00569             tm.setTime_t(dbi.backupDate);
00570             newpatt.replace(CSL1("%9"), tm.toString(Qt::LocalDate));
00571 
00572             dbstring.append(newpatt);
00573         }
00574         // Now, just replace the whole found pattern by the string we just constructed.
00575         output.replace(re.cap(0), dbstring);
00576     }
00577 
00578     // Write out the result
00579     QFile outfile(fOutputFile);
00580 #ifdef DEBUG
00581     DEBUGKPILOT << fname << ": Writing file <" << fOutputFile << ">" << endl;
00582 #endif
00583     if (fOutputFile.isEmpty() || (!outfile.open(IO_WriteOnly)) ) {
00584         QFileInfo fi(QDir::home(), CSL1("KPilotSysInfo.")+QFileInfo(templatefile).extension() );
00585         fOutputFile=fi.absFilePath();
00586         WARNINGKPILOT << "Unable to open output file, using " << fOutputFile << " instead." << endl;
00587         emit logMessage(i18n("Unable to open output file, using %1 instead.").arg(fOutputFile));
00588         outfile.setName(fOutputFile);
00589         if (!outfile.open(IO_WriteOnly)) {
00590             WARNINGKPILOT<< "Unable to open " << fOutputFile << endl;
00591             emit logError(i18n("Unable to open %1").arg(fOutputFile));
00592             QTimer::singleShot(0, this, SLOT(cleanup()));
00593             return;
00594         }
00595     }
00596 
00597     // Finally, write the actual text out to the file.
00598     QTextStream outstream(&outfile);
00599     outstream<<output;
00600     outfile.close();
00601 
00602     emit logMessage(i18n("Handheld system information written to the file %1").arg(fOutputFile));
00603     QTimer::singleShot(0, this, SLOT(cleanup()));
00604 }
00605 
00606 void SysInfoConduit::cleanup()
00607 {
00608     FUNCTIONSETUP;
00609     // Nothing to clean up so far (Do I have memory leaks somewhere?)
00610     emit syncDone(this);
00611 }