kcmpureftpd

  Main Page   Compound List   File List   Compound Members
Main Page   Compound List   File List   Compound Members  

kcmpureftpdstat.cpp

00001 /***************************************************************************
00002                           kcmpureftpdstat.cpp  -  PureFTPd Statistics
00003                              -------------------
00004     begin                : Thu Jan 2 2002
00005     copyright            : (C) 2002,2003 by Claudiu Costin
00006     email                : claudiuc@kde.org
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 General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 
00019 #include <qclipboard.h>
00020 #include <qwhatsthis.h>
00021 #include <qcstring.h>
00022 #include <qstringlist.h>
00023 #include <qfile.h>
00024 #include <qfileinfo.h>
00025 #include <qtextstream.h>
00026 #include <qdom.h>
00027 #include <qregexp.h>
00028 #include <qlayout.h>
00029 #include <qbuttongroup.h>
00030 
00031 #include <klocale.h>
00032 #include <kcursor.h>
00033 #include <kseparator.h>
00034 #include <kstddirs.h>
00035 #include <kmessagebox.h>
00036 #include <kfiledialog.h>
00037 #include <kiconloader.h>
00038 #include <kapplication.h>
00039 
00040 #include "kcmpureftpdstat.moc"
00041 
00042 KPureftpdStat::KPureftpdStat(QWidget *parent, const char *name)
00043         : KCModule(parent, name), infoProcess(0), logProcess(0)  {
00044 
00045   pureftpwhoExe=QString::null;
00046   logMaxNumLines=0;
00047   reachedMaxNumLines=false;
00048   deliberatedKill=false;
00049   isProcessingInfo=false;
00050   mFound=false;
00051 
00052   config = new KConfig("kcmpureftpdstatrc",false,false);
00053   infoTimer = new QTimer(this);
00054   connect(infoTimer,SIGNAL(timeout()),this,SLOT(startInfoProcess()));
00055     
00056   initView();
00057     
00058 
00059   // ensure changed() when user modify settings
00060   connect(rbInfoDefault,SIGNAL(toggled(bool)),this,SLOT(configChanged()));
00061   connect(rbInfoCustom,SIGNAL(toggled(bool)),this,SLOT(configChanged()));
00062   connect(rbLogFile,SIGNAL(toggled(bool)),this,SLOT(configChanged()));
00063   connect(rbLogCustom,SIGNAL(toggled(bool)),this,SLOT(configChanged()));
00064   connect(pureftpwhoDefault,SIGNAL(toggled(bool)),this,SLOT(configChanged()));
00065   connect(pureftpwhoPath,SIGNAL(textChanged(const QString &)),this,SLOT(configChanged(const QString &)));
00066   connect(logFileName,SIGNAL(textChanged(const QString &)),this,SLOT(configChanged(const QString &)));
00067   connect(infoCommand,SIGNAL(textChanged(const QString &)),this,SLOT(configChanged(const QString &)));
00068   connect(logCommand,SIGNAL(textChanged(const QString &)),this,SLOT(configChanged(const QString &)));
00069   connect(updateInterval,SIGNAL(valueChanged(int)),this,SLOT(configChanged(int)));
00070   connect(historyLines,SIGNAL(valueChanged(int)),this,SLOT(configChanged(int)));
00071 
00072   load();
00073 
00074   displayInfoMessage(InfoInit);
00075   displayLogMessage(LogInit);
00076 
00077   logProcess = new KShellProcess;
00078   connect(logProcess,SIGNAL(receivedStdout(KProcess *,char*, int)),this,SLOT(slotLogProcessRecvStdout(KProcess *,char*, int)));
00079   connect(logProcess,SIGNAL(receivedStderr(KProcess *,char*, int)),this,SLOT(slotLogProcessRecvStderr(KProcess *,char*, int)));
00080   connect(logProcess,SIGNAL(processExited(KProcess *)),this,SLOT(slotLogProcessExited(KProcess *)));
00081 
00082   infoProcess = new KShellProcess;
00083   connect(infoProcess,SIGNAL(receivedStdout(KProcess *,char *, int)),this,SLOT(slotInfoProcessRecvStdout(KProcess *, char*, int)));
00084   connect(infoProcess,SIGNAL(receivedStderr(KProcess *,char *, int)),this,SLOT(slotInfoProcessRecvStderr(KProcess *, char*, int)));
00085   connect(infoProcess,SIGNAL(processExited(KProcess *)),this,SLOT(slotInfoProcessExited(KProcess *)));
00086 }
00087 
00088 
00089 KPureftpdStat::~KPureftpdStat() {
00090   if (infoTimer->isActive()) {
00091     infoTimer->stop();
00092   }
00093   if (infoProcess->isRunning()) {
00094     stopInfoProcess();
00095   }
00096   if (logProcess->isRunning()) {
00097     stopLogProcess();
00098   }
00099 }
00100 
00101 void KPureftpdStat::initView() {
00102     
00103   QVBoxLayout *vbmain = new QVBoxLayout(this,0,0);
00104   tab = new QTabWidget(this);
00105   vbmain->addWidget(tab);
00106 
00107   // "Information" tab
00108   tabInfo = new QWidget(this);
00109   tab->addTab(tabInfo,i18n("Information"));
00110   QWhatsThis::add(tabInfo, i18n(
00111                       "<qml>Informations about current connections to your "
00112                       "<b>pure-ftpd</b> FTP server</qml>"
00113                   ));
00114   QVBoxLayout *vbox1 = new QVBoxLayout(tabInfo,5,5);
00115   QGroupBox *grpConn = new QGroupBox(i18n("FTP Connections"),tabInfo);
00116   QVBoxLayout *vbox11 = new QVBoxLayout(grpConn,5,5);
00117   vbox11->addSpacing(grpConn->fontMetrics().height());
00118   connList = new KListView(grpConn);
00119 
00120   connList->addColumn(i18n("Username"),-1);
00121   connList->addColumn(i18n("State"),-1);
00122   connList->addColumn(i18n("Time"),-1);
00123   connList->addColumn(i18n("Percentage"),-1);
00124   connList->addColumn(i18n("File"),-1);
00125   connList->setMaximumHeight(10*connList->fontMetrics().height());
00126   connList->setAllColumnsShowFocus(true);
00127   connList->setShowSortIndicator(true);
00128   connList->setColumnAlignment(2,Qt::AlignRight);
00129   connList->setColumnAlignment(3,Qt::AlignRight);
00130   vbox11->addWidget(connList);
00131 
00132   QGroupBox *grpConnInfo = new QGroupBox(i18n("Extended Informations"),tabInfo);
00133   QVBoxLayout *vbox12 = new QVBoxLayout(grpConnInfo,5,5);
00134   vbox12->addSpacing(grpConnInfo->fontMetrics().height());
00135   txtExtInfo = new QTextView(grpConnInfo);
00136   vbox12->addWidget(txtExtInfo);
00137 
00138   infoUpdate = new KPushButton(i18n("Continuos &Update"),tabInfo);
00139   infoUpdate->setToggleButton(true);
00140 
00141   grpInfoMessage = new QGroupBox(i18n(" Message "),tabInfo);
00142   grpInfoMessage->setMinimumHeight(8*grpInfoMessage->fontMetrics().height());
00143   QGridLayout *gbox13 = new QGridLayout(grpInfoMessage,2,2,5);
00144   mesgInfoIcon = new QLabel(grpInfoMessage);
00145   mesgInfoIcon->setMargin(10);
00146   mesgInfoText = new QLabel(grpInfoMessage);
00147   mesgInfoText->setAlignment(Qt::AlignLeft | Qt::AlignTop);
00148 
00149   gbox13->addRowSpacing(0,grpInfoMessage->fontMetrics().height());
00150   gbox13->setColStretch(1,10);
00151   gbox13->setRowStretch(1,10);
00152   gbox13->addWidget(mesgInfoIcon,1,0,Qt::AlignCenter);
00153   gbox13->addWidget(mesgInfoText,1,1);
00154 
00155   vbox1->addWidget(grpConn);
00156   vbox1->addSpacing(5);
00157   vbox1->addWidget(grpConnInfo);
00158   vbox1->addSpacing(5);
00159   vbox1->addWidget(infoUpdate,0,Qt::AlignRight);
00160   vbox1->addSpacing(5);
00161   vbox1->addWidget(grpInfoMessage);
00162   vbox1->addStretch();
00163 
00164   connect(infoUpdate,SIGNAL(clicked()),this,SLOT(slotInfoProcessToggleUpdate()));
00165   connect(connList,SIGNAL(clicked(QListViewItem*)),this,SLOT(slotShowExtendedInfo(QListViewItem*)));
00166 
00167 
00168   // "Log" tab
00169   tabLog = new QWidget(this);
00170   tab->addTab(tabLog,i18n("Log"));
00171   QWhatsThis::add(tabLog, i18n(
00172                       "<qml>Show <b>pure-ftpd</b> server log file activity "
00173                       "in real time. Also you can search in log view "
00174                       "for some special keywords using usual search "
00175                       "options.</qml>"
00176                   ));
00177   QVBoxLayout *vbox2 = new QVBoxLayout(tabLog,5,5);
00178   QLabel *txtLogOutput = new QLabel(i18n("Log Output:"),tabLog);
00179   logOutput = new QMultiLineEdit(tabLog);
00180   logOutput->setReadOnly(true);
00181   logOutput->setMinimumHeight(15*logOutput->fontMetrics().height());
00182   logOutput->setFont(KGlobalSettings::fixedFont());
00183   logOutput->setWordWrap(QTextEdit::NoWrap);
00184   KCursor::setAutoHideCursor(logOutput,true);
00185 
00186   logUpdate = new KPushButton(i18n("Continuos &Update"),tabLog);
00187   logUpdate->setToggleButton(true);
00188   logSave   = new KPushButton(i18n("&Save..."),tabLog);
00189   logCopy   = new KPushButton(i18n("&Copy to Clipboard"),tabLog);
00190   logClear  = new KPushButton(i18n("Cl&ear"),tabLog);
00191 
00192   QHBoxLayout *hbox21 = new QHBoxLayout();
00193   hbox21->addWidget(logSave);
00194   hbox21->addSpacing(5);
00195   hbox21->addWidget(logCopy);
00196   hbox21->addSpacing(5);
00197   hbox21->addWidget(logClear);
00198   hbox21->addStretch();
00199   hbox21->addWidget(logUpdate);
00200 
00201 
00202   KSeparator *sep = new KSeparator(KSeparator::HLine,tabLog);
00203 
00204   caseSensitive = new QCheckBox(i18n("Case &sensitive"),tabLog);
00205   wholeWords = new QCheckBox(i18n("&Whole words only"),tabLog);
00206   findBackwards = new QCheckBox(i18n("Find &backwards"),tabLog);
00207   logSearch = new KPushButton(i18n("&Search"),tabLog);
00208   logResetSearch = new KPushButton(i18n("&Reset Search"),tabLog);
00209   QLabel *txtSearch = new QLabel(i18n("Sea&rch for:"),tabLog);
00210   editSearch = new KLineEdit(tabLog);
00211   txtSearch->setBuddy(editSearch);
00212 
00213   QGridLayout *gbox22 = new QGridLayout();
00214   gbox22->addWidget(txtSearch,1,1,Qt::AlignRight);
00215   gbox22->addWidget(editSearch,1,2);
00216   gbox22->addWidget(logSearch,1,3,Qt::AlignLeft);
00217   gbox22->addWidget(logResetSearch,2,3,Qt::AlignLeft);
00218   gbox22->addMultiCellWidget(caseSensitive,2,2,1,2);
00219   gbox22->addWidget(logResetSearch,2,3,Qt::AlignRight);
00220   gbox22->addMultiCellWidget(wholeWords,3,3,1,2);
00221   gbox22->addMultiCellWidget(findBackwards,4,4,1,2);
00222 
00223   grpLogMessage = new QGroupBox(i18n(" Message "),tabLog);
00224   grpLogMessage->setMinimumHeight(8*grpLogMessage->fontMetrics().height());
00225   QGridLayout *gbox23 = new QGridLayout(grpLogMessage,2,2,5);
00226   mesgLogIcon = new QLabel(grpLogMessage);
00227   mesgLogIcon->setMargin(10);
00228   mesgLogText = new QLabel(grpLogMessage);
00229   mesgLogText->setAlignment(Qt::AlignLeft | Qt::AlignTop);
00230 
00231   gbox23->addRowSpacing(0,grpLogMessage->fontMetrics().height());
00232   gbox23->setColStretch(1,10);
00233   gbox23->setRowStretch(1,10);
00234   gbox23->addWidget(mesgLogIcon,1,0,Qt::AlignCenter);
00235   gbox23->addWidget(mesgLogText,1,1);
00236 
00237 
00238   vbox2->addWidget(txtLogOutput);
00239   vbox2->addWidget(logOutput);
00240   vbox2->addSpacing(5);
00241   vbox2->addLayout(hbox21);
00242   vbox2->addSpacing(5);
00243   vbox2->addWidget(grpLogMessage);
00244   vbox2->addSpacing(5);
00245   vbox2->addWidget(sep);
00246   vbox2->addSpacing(5);
00247   vbox2->addLayout(gbox22);
00248   vbox2->addStretch();
00249 
00250   connect(logUpdate,SIGNAL(toggled(bool)),this,SLOT(slotLogProcessToggleUpdate(bool)));
00251   connect(logSave,SIGNAL(clicked()),this,SLOT(slotLogSave()));
00252   connect(logCopy,SIGNAL(clicked()),this,SLOT(slotLogCopy()));
00253   connect(logClear,SIGNAL(clicked()),this,SLOT(slotLogClear()));
00254   connect(logSearch,SIGNAL(clicked()),this,SLOT(slotLogSearch()));
00255   connect(logResetSearch,SIGNAL(clicked()),this,SLOT(slotLogResetSearch()));
00256 
00257 
00258 
00259   // "Configuration" tab
00260   tabConfig = new QWidget(this);
00261   tab->addTab(tabConfig,i18n("Configuration"));
00262   QWhatsThis::add(tabConfig, i18n(
00263                       "<qml>Here you can configure parameteres for "
00264                       "Pureftpd Statistics KDE module. You may want to "
00265                       "modify default values if you have unsual configuration "
00266                       "or your machine is powerfull enough.</qml>"
00267                   ));
00268   QVBoxLayout *vbox3 = new QVBoxLayout(tabConfig,5,5);
00269   QButtonGroup *grpInfoConf = new QButtonGroup(i18n(" FTP Sessions Display Settings "),tabConfig);
00270   QGridLayout *gbox31 = new QGridLayout(grpInfoConf,7,3,5);
00271 
00272   QLabel *txtUpdateInterval = new QLabel(i18n("&Update interval:"),grpInfoConf);
00273   updateInterval = new KIntNumInput(grpInfoConf);
00274   updateInterval->setRange(1,10000,1,false);
00275   updateInterval->setSuffix(i18n("seconds"," sec"));
00276   txtUpdateInterval->setBuddy(updateInterval);
00277   QLabel *txtInfoChoose = new QLabel(i18n("Choose information source:"),grpInfoConf);
00278   rbInfoDefault = new QRadioButton(i18n("Run pure-ftp&who"),grpInfoConf);
00279   pureftpwhoDefault = new QCheckBox(i18n("Use s&etting from \"PureFTPd Configuration\" module"), grpInfoConf);
00280   txtPureftpwhoPath = new QLabel(i18n("Pure-ftpwho Path:"),grpInfoConf);
00281   pureftpwhoPath = new KURLRequester("",grpInfoConf);
00282   txtPureftpwhoPath->setBuddy(pureftpwhoPath);
00283 #if KDE_VERSION > 300
00284   pureftpwhoPath->setMode(KFile::File);
00285 #endif
00286   rbInfoCustom = new QRadioButton(i18n("&Run custom command"),grpInfoConf);
00287   txtInfoCommand = new QLabel(i18n("Command Line:"),grpInfoConf);
00288   infoCommand = new KLineEdit(grpInfoConf);
00289   txtInfoCommand->setBuddy(infoCommand);
00290 
00291   gbox31->addRowSpacing(0,grpInfoConf->fontMetrics().height());
00292   gbox31->addColSpacing(0,20);
00293   gbox31->addMultiCellWidget(txtUpdateInterval,1,1,0,1,Qt::AlignLeft);
00294   gbox31->addWidget(updateInterval,1,2,Qt::AlignLeft);
00295   gbox31->addMultiCellWidget(txtInfoChoose,2,2,0,2);
00296   gbox31->addMultiCellWidget(rbInfoDefault,3,3,0,2);
00297   gbox31->addMultiCellWidget(pureftpwhoDefault,4,4,1,2);
00298   gbox31->addWidget(txtPureftpwhoPath,5,1);
00299   gbox31->addWidget(pureftpwhoPath,5,2);
00300   gbox31->addMultiCellWidget(rbInfoCustom,6,6,0,2);
00301   gbox31->addWidget(txtInfoCommand,7,1);    
00302   gbox31->addWidget(infoCommand,7,2);    
00303 
00304   QButtonGroup *grpLogConf = new QButtonGroup(i18n(" Log Display Settings "),tabConfig);
00305   QGridLayout *gbox32 = new QGridLayout(grpLogConf,7,3,5);
00306 
00307   QLabel *txtHistoryLines = new QLabel(i18n("&Number of &history lines:"),grpLogConf);
00308   historyLines = new KIntNumInput(grpLogConf);
00309   historyLines->setRange(1,30000,1,false);
00310   txtHistoryLines->setBuddy(historyLines);
00311   QLabel *txtLogChoose = new QLabel(i18n("Choose logging method:"),grpLogConf);
00312   rbLogFile = new QRadioButton(i18n("D&isplay log file"),grpLogConf);
00313   txtLogFileName = new QLabel(i18n("Log Filename:"),grpLogConf);
00314   logFileName = new KURLRequester("",grpLogConf);
00315 #if KDE_VERSION > 300
00316   logFileName->setMode(KFile::File);
00317 #endif
00318   txtLogFileName->setBuddy(logFileName);
00319   rbLogCustom = new QRadioButton(i18n("Run cu&stom command"),grpLogConf);
00320   txtLogCommand = new QLabel(i18n("Log Command:"),grpLogConf);    
00321   logCommand = new KLineEdit(grpLogConf);
00322   txtLogCommand->setBuddy(logCommand);
00323 
00324   gbox32->addRowSpacing(0,grpLogConf->fontMetrics().height());
00325   gbox32->addColSpacing(0,20);
00326   gbox32->addMultiCellWidget(txtHistoryLines,1,1,0,1);
00327   gbox32->addWidget(historyLines,1,2,Qt::AlignLeft);
00328   gbox32->addMultiCellWidget(txtLogChoose,2,2,0,2);
00329   gbox32->addMultiCellWidget(rbLogFile,3,3,0,2);
00330   gbox32->addWidget(txtLogFileName,4,1);
00331   gbox32->addWidget(logFileName,4,2);
00332   gbox32->addMultiCellWidget(rbLogCustom,5,5,0,2);
00333   gbox32->addWidget(txtLogCommand,6,1);
00334   gbox32->addWidget(logCommand,6,2);
00335 
00336   rbInfoDefault->setChecked(true);
00337   pureftpwhoDefault->setChecked(true);
00338   txtPureftpwhoPath->setEnabled(false);
00339   pureftpwhoPath->setEnabled(false);
00340   txtInfoCommand->setEnabled(false);
00341   infoCommand->setEnabled(false);
00342   rbLogFile->setChecked(true);
00343   txtLogCommand->setEnabled(false);
00344   logCommand->setEnabled(false);
00345 
00346   vbox3->addWidget(grpInfoConf);
00347   vbox3->addSpacing(5);
00348   vbox3->addWidget(grpLogConf);
00349   vbox3->addStretch();
00350 
00351   connect(updateInterval,SIGNAL(valueChanged(int)),this,SLOT(slotChangedInterval(int)));
00352   connect(rbInfoDefault,SIGNAL(toggled(bool)),this,SLOT(slotInfoConfDefault(bool)));
00353   connect(rbLogFile,SIGNAL(toggled(bool)),this,SLOT(slotLogConfDefault(bool)));
00354   connect(pureftpwhoDefault,SIGNAL(toggled(bool)),this,SLOT(slotInfoConfUseDefault(bool)));
00355 }
00356 
00357 
00358 void KPureftpdStat::displayInfoMessage(InfoMessage t) {
00359   switch (t) {
00360     case InfoInit:
00361       mesgInfoIcon->setPixmap(KApplication::kApplication()->iconLoader()->loadIcon(
00362         "messagebox_info",KIcon::NoGroup,KIcon::SizeMedium,KIcon::DefaultState,0,true));
00363     break;    
00364     case InfoExecCommandKill:
00365     case InfoExecRunning:
00366     case InfoWarning:
00367       mesgInfoIcon->setPixmap(KApplication::kApplication()->iconLoader()->loadIcon(
00368         "messagebox_warning",KIcon::NoGroup,KIcon::SizeMedium,KIcon::DefaultState,0,true));
00369     break;
00370     case InfoExecCommandError:
00371       mesgInfoIcon->setPixmap(KApplication::kApplication()->iconLoader()->loadIcon(
00372         "messagebox_critical",KIcon::NoGroup,KIcon::SizeMedium,KIcon::DefaultState,0,true));
00373     break;
00374     case InfoClear:
00375     default:
00376       mesgInfoIcon->setPixmap(QPixmap());
00377   }
00378 
00379   switch (t) {
00380     case InfoClear:
00381       mesgInfoText->setText("");
00382     break;
00383     case InfoInit:
00384       mesgInfoText->setText(i18n(
00385             "<qml>Press <b>Continuos Update</b> button to view "
00386             "FTP connections to your PureFTPd server. Depress the "
00387             "button to freeze view on current state.</qml>"
00388             ));
00389     break;
00390     case InfoWarning:
00391     break;
00392     case InfoExecRunning:
00393       mesgInfoText->setText(i18n(
00394             "<qml>The process for FTP connection displaying "
00395             "have been locked, timed out or took to long to process. Please "
00396             "try to increase the update interval or ask your system administrator "
00397             "to investigate the issue.</qml>"
00398             ));
00399     break;
00400     case InfoExecCommandError:
00401       mesgInfoText->setText(i18n(
00402             "<qml>There was an error executing FTP info grabbing command. "
00403             "Check if this error is temporary or permanent, then "
00404             "contact your system administrator.</qml>"
00405             ));
00406     break;
00407     case InfoExecCommandKill:
00408       mesgInfoText->setText(i18n(
00409             "<qml>The info grabbing process has been forced to stop "
00410             "because there's more time needed for FTP sessions processing "
00411             "than time interval between updates.</qml>"
00412             ));
00413     break;
00414     default:
00415       kdWarning() << __FUNCTION__  << "(): unknown message display type t=" << t << endl;
00416   }
00417 }
00418 
00419 void KPureftpdStat::displayLogMessage(LogMessage t) {
00420   switch (t) {
00421     case LogInit:
00422     case LogFull:
00423       mesgLogIcon->setPixmap(KApplication::kApplication()->iconLoader()->loadIcon(
00424         "messagebox_info",KIcon::NoGroup,KIcon::SizeMedium,KIcon::DefaultState,0,true));
00425     break;    
00426     case LogWriteError:
00427     case LogExecTerminated:
00428       mesgLogIcon->setPixmap(KApplication::kApplication()->iconLoader()->loadIcon(
00429         "messagebox_warning",KIcon::NoGroup,KIcon::SizeMedium,KIcon::DefaultState,0,true));
00430     break;
00431     case LogExecTailError:
00432     case LogExecCommandError:
00433       mesgLogIcon->setPixmap(KApplication::kApplication()->iconLoader()->loadIcon(
00434         "messagebox_critical",KIcon::NoGroup,KIcon::SizeMedium,KIcon::DefaultState,0,true));
00435     break;
00436     case LogClear:
00437     default:
00438       mesgLogIcon->setPixmap(QPixmap());
00439   }
00440 
00441   switch (t) {
00442     case LogClear:
00443       mesgLogText->setText("");
00444     break;
00445     case LogInit:
00446       mesgLogText->setText(i18n(
00447             "<qml>Press <b>Continuos Update</b> button to view "
00448             "PureFTPd server log file in real-time. Depress the "
00449             "button to freeze view on current state.</qml>"
00450             ));
00451     break;
00452     case LogWriteError:
00453       mesgLogText->setText(i18n(
00454           "<qt>You don't have permission to write the log "
00455           "file here or some serious write error "
00456           "happened.<p>Please verify and try again.</qt>"));
00457     break;
00458     case LogExecTailError:
00459       mesgLogText->setText(i18n(
00460             "<qt>There was an error executing UNIX <b>tail</b> "
00461             "process. Please verify if you have permissions executing "
00462             "it and if it's accessible from environment variable "
00463             "<tt>PATH</tt>.</qt>"));
00464     break;
00465     case LogExecCommandError:
00466       mesgLogText->setText(i18n(
00467             "<qt>There was an error running command line "
00468             "for log reading. Please verify if you have "
00469             "all necessary permissions or if there's an error "
00470             "in command line.</qt>"));
00471     break;
00472     case LogExecTerminated:
00473       mesgLogText->setText(i18n(
00474             "<qt>The UNIX process for reading log file "
00475             "has terminated or has been killed. Check "
00476             "the logging command line.</qt>"));
00477     break;
00478     case LogFull:
00479       mesgLogText->setText(i18n(
00480             "<qt>The maximum number of logged lines "
00481             "has been reached. Please press <b>Clear</b> "
00482             "button to be able to start logging again. "
00483             "If you want more lines logged increase the "
00484             "\"Number of history lines\" counter in "
00485             "<b>Configuration</b> tab.</qt>"));
00486     break;
00487     default:
00488       kdWarning() << __FUNCTION__  << "(): unknown message display type t=" << t << endl;
00489   }
00490 }
00491 
00492 
00493 //----------------------  SLOTS  ---------------------//
00494 void KPureftpdStat::configChanged() {
00495     emit changed(true);
00496 }
00497 
00498 void KPureftpdStat::configChanged(const QString &text) {
00499     QString dummy=text;
00500     configChanged();
00501 }
00502 
00503 void KPureftpdStat::configChanged(int number) {
00504     int dummy;
00505     dummy=number;
00506     configChanged();
00507 }
00508 
00509 // "Log" tab
00510 void KPureftpdStat::slotLogSearch() {
00511   int dummy = (!findBackwards->isChecked()) ? 0 : INT_MAX;
00512   if (!mFound) {
00513     mFound=!logOutput->find(editSearch->text(),caseSensitive->isChecked(),wholeWords->isChecked(),
00514                            !findBackwards->isChecked());
00515   } else {
00516     mFound=!logOutput->find(editSearch->text(),caseSensitive->isChecked(),wholeWords->isChecked(),
00517                            !findBackwards->isChecked(),&dummy,&dummy);
00518   }
00519 }
00520 
00521 void KPureftpdStat::slotLogResetSearch() {
00522   mFound=false;
00523   logOutput->setCursorPosition(0,0,false);
00524 }
00525 
00526 
00527 void KPureftpdStat::slotLogSave() {
00528   displayLogMessage(LogClear);
00529   
00530   KURL urlName = KFileDialog::getSaveURL(startDir+"/"+fileName,
00531                 i18n("*.log|Log Files\n"
00532                      "*.txt|Text Files\n"
00533                      "*|All Files"),0,
00534                 i18n("Save Log Output"));
00535   if (!urlName.isEmpty()) {
00536     startDir = urlName.directory(true,true);
00537     fileName = urlName.filename();
00538     if (!fileName.isEmpty()) {
00539       QFile f(startDir+"/"+fileName);
00540       if (f.open(IO_WriteOnly)) {
00541         QTextStream t(&f);
00542         t << logOutput->text();
00543         f.close();
00544       } else {
00545         displayLogMessage(LogWriteError);
00546       }
00547     }
00548   }
00549 
00550   config->setGroup("Log Tab");
00551   config->writeEntry("Log Saving Directory",startDir);
00552   config->writeEntry("Log FileName",fileName);
00553   config->sync();
00554 }
00555 
00556 void KPureftpdStat::slotLogCopy() {
00557   displayLogMessage(LogClear);
00558   QApplication::clipboard()->setText(logOutput->text());
00559 }
00560 
00561 void KPureftpdStat::slotLogClear() {
00562   displayLogMessage(LogClear);
00563   logOutput->clear();
00564   logUpdate->setEnabled(true);
00565 }
00566 
00567 
00568 void KPureftpdStat::slotLogProcessToggleUpdate(bool toggled) {
00569   if (toggled) {
00570     displayLogMessage(LogClear);
00571     startLogProcess();
00572   } else {
00573     stopLogProcess();
00574     logOutput->append(i18n("---- Stopped ----"));
00575   }
00576 }
00577 
00578 
00579 void KPureftpdStat::startLogProcess()
00580 {
00581   if (logProcess->isRunning()) {
00582     kdWarning() << __FUNCTION__ << "(): the log process is already running" << endl;
00583     return;
00584   }
00585 
00586   tmpStdout=QString::null;
00587   tmpStderr=QString::null;
00588   logProcess->clearArguments();
00589   if (rbLogFile->isChecked()) {
00590     *logProcess << "tail" << " -n 1 -f " << KShellProcess::quote(logFileName->url());
00591   } else {
00592     *logProcess << logCommand->text().stripWhiteSpace();
00593   }
00594 
00595   bool started=logProcess->start(KProcess::NotifyOnExit,KProcess::AllOutput);
00596 
00597   if (started) {
00598     reachedMaxNumLines=false;
00599     logMaxNumLines=historyLines->value();
00600   } else {
00601     if (rbLogFile->isChecked()) {
00602       displayLogMessage(LogExecTailError);
00603     } else {
00604       displayLogMessage(LogExecCommandError);
00605     }
00606     logUpdate->setOn(false);
00607   }
00608 }
00609 
00610 
00611 void KPureftpdStat::stopLogProcess()
00612 {
00613   int countdown=2000;
00614   
00615   logProcess->closeStdout();
00616   logProcess->closeStderr();
00617   if (logProcess->isRunning()) {
00618     logProcess->kill(SIGKILL);
00619     while (countdown && logProcess->isRunning()) {
00620       kapp->processEvents();
00621       usleep(200000);
00622       countdown--;
00623     }
00624     if (countdown==0) {
00625       kdWarning() << __FUNCTION__ << "(): The logging process has not exited! pid=" << logProcess->pid() << endl;
00626     }
00627   }
00628 }
00629 
00630 
00631 void KPureftpdStat::slotLogProcessRecvStdout(KProcess *p, char *buf, int len) {
00632   KProcess *dummy;
00633   dummy=p;
00634 
00635   QString m_buf = tmpStdout + QString::fromLatin1(buf,len);
00636   int pos = m_buf.findRev("\n");
00637   if (pos == (int) m_buf.length()-1) {
00638     logOutput->append(m_buf.left(pos));
00639     tmpStdout=QString::null;
00640   } else if (pos == -1) {
00641     tmpStdout=m_buf;
00642   } else {
00643     logOutput->append(m_buf.left(pos));
00644     tmpStdout=m_buf.mid(pos+1);
00645   }
00646 
00647   if (logOutput->numLines()>=logMaxNumLines) {
00648     reachedMaxNumLines=true;
00649     // flush the line buffer
00650     if (pos == -1) {
00651       logOutput->append(tmpStdout);
00652     }
00653     displayLogMessage(LogFull);
00654     logUpdate->setEnabled(false);
00655     logUpdate->setOn(false);
00656     return;
00657   }
00658 }
00659 
00660 void KPureftpdStat::slotLogProcessRecvStderr(KProcess *p, char *buf, int len) {
00661   KProcess *dummy;
00662   dummy=p;
00663 
00664   QString m_buf = tmpStderr+QString::fromLatin1(buf,len);
00665   int pos  =  m_buf.findRev("\n");
00666   if (pos == (int) (m_buf.length()-1)) {
00667     logOutput->append(m_buf.left(pos));
00668     tmpStderr=QString::null;
00669   } else if (pos == -1) {
00670     tmpStderr=m_buf;
00671   } else {
00672     logOutput->append(m_buf.left(pos));
00673     tmpStderr=m_buf.mid(pos+1);
00674   }
00675   
00676   if (logOutput->numLines()>=logMaxNumLines) {
00677     reachedMaxNumLines=true;
00678     // flush the line buffer
00679     if (pos == -1) {
00680       logOutput->append(tmpStderr);
00681     }
00682     displayLogMessage(LogFull);
00683     logUpdate->setEnabled(false);
00684     logUpdate->setOn(false);
00685     return;
00686   }
00687 }
00688 
00689 void KPureftpdStat::slotLogProcessExited(KProcess *p) {
00690   if (!reachedMaxNumLines) {
00691     if (p->normalExit() && ! p->exitStatus()) {
00692       displayLogMessage(LogExecTerminated);
00693     } else {
00694       if (logUpdate->isOn()) {
00695         displayLogMessage(LogExecCommandError);
00696       }
00697     }
00698   }
00699   if (logUpdate->isOn()) {
00700     logUpdate->setOn(false);
00701   }
00702 }
00703 
00704 
00705 // "Info" tab
00706 void KPureftpdStat::slotInfoProcessToggleUpdate() {
00707   if (infoUpdate->isOn()) {
00708     txtExtInfo->setText("");
00709     ftpSessionMap.clear();
00710     ftpGuiMap.clear();
00711     connList->clear();
00712     txtExtInfo->setPaper(QBrush(qApp->palette().active().base()));
00713     displayInfoMessage(InfoClear);
00714     pureftpwhoExe=pureftpwhoPath->url();
00715     startInfoProcess();
00716     infoTimer->start(1000*updateInterval->value());
00717   } else {
00718     deliberatedKill=true;
00719     infoTimer->stop();
00720     stopInfoProcess();
00721   }
00722 }
00723 
00724 void KPureftpdStat::startInfoProcess() {
00725   if (isProcessingInfo) {
00726       displayInfoMessage(InfoExecRunning);
00727   } else {
00728     isProcessingInfo=true;
00729     infoProcess->clearArguments();
00730     if (rbInfoDefault->isChecked()) {
00731       if (pureftpwhoDefault->isChecked()) {
00732         *infoProcess << pureftpwhoDefaultPath << "-x";
00733       } else {
00734         *infoProcess << pureftpwhoExe << "-x";
00735       }
00736     } else {
00737       *infoProcess << infoCommand->text().stripWhiteSpace();
00738     }
00739 
00740     bool started = infoProcess->start(KProcess::NotifyOnExit,KProcess::AllOutput);
00741 
00742     if (started) {
00743       deliberatedKill=false;
00744       infoOutput = QString::null;
00745     } else {
00746       infoUpdate->setOn(false);
00747       displayInfoMessage(InfoExecCommandError);
00748     }
00749   }
00750 }
00751 
00752 void KPureftpdStat::stopInfoProcess() {
00753   int countdown=2000;
00754   
00755   infoProcess->closeStdout();
00756   infoProcess->closeStderr();
00757   if (infoProcess->isRunning()) {
00758     infoProcess->kill(SIGKILL);
00759     while (countdown && infoProcess->isRunning()) {
00760       kapp->processEvents();
00761       usleep(200000);
00762       countdown--;
00763     }
00764     if (countdown==0) {
00765       kdWarning() << __FUNCTION__ << "(): The info process has not exited! pid=" << infoProcess->pid() << endl;
00766     }
00767   }
00768 }
00769 
00770 
00771 void KPureftpdStat::slotInfoProcessRecvStdout(KProcess *p, char *buf, int len) {
00772   KProcess *dummy_p;
00773   int dummy_len;
00774 
00775   dummy_p=p;
00776   dummy_len=len;
00777   infoOutput.append(buf);
00778 }
00779 
00780 void KPureftpdStat::slotInfoProcessRecvStderr(KProcess *p, char *buf, int len) {
00781   KProcess *dummy_p;
00782   int dummy_len;
00783   char *dummy_buf;
00784   
00785   dummy_p=p;
00786   dummy_len=len;
00787   dummy_buf=buf;
00788 
00789   // nothing usable do with STDERR for the moment 
00790 }
00791 
00792 void KPureftpdStat::slotInfoProcessExited(KProcess *p) {
00793   KProcess *dummy;
00794   dummy=p;
00795 
00796   if (infoProcess->normalExit()) {
00797     // infoProcess terminated its execution
00798     if (infoProcess->exitStatus()) {
00799       // terminated with some error
00800       displayInfoMessage(InfoExecCommandError);
00801       if (infoTimer->isActive()) {
00802         infoTimer->stop();
00803       }
00804       infoUpdate->setOn(false);
00805     } else {
00806       // terminated OK, so process the received data
00807       processInfoOutput();
00808     }
00809   } else {
00810     // infoProcess was killed
00811     if (! deliberatedKill) {
00812       displayInfoMessage(InfoExecCommandKill);
00813     }
00814   }
00815   isProcessingInfo=false;
00816 }
00817 
00818 QString KPureftpdStat::prettyByte(unsigned long long m_byte) {
00819   QString ext;
00820 
00821   if (m_byte==1) return i18n("1 Byte");
00822   if (m_byte==0) return i18n("0 Bytes");
00823   if (m_byte >= 1024) {
00824       double m_kbyte = m_byte / 1024.0;
00825       if (m_kbyte >= 1024) {
00826         double m_mbyte = m_kbyte / 1024.0;
00827         if (m_mbyte >= 1024) {
00828           double m_gbyte = m_mbyte / 1024.0;
00829           QString s_gbyte;
00830           s_gbyte.sprintf("%4.2f",m_gbyte);
00831           return i18n("%1 GBytes").arg(s_gbyte);
00832         } else {
00833           QString s_mbyte;
00834           s_mbyte.sprintf("%4.2f",m_mbyte);
00835           return i18n("%1 MBytes").arg(s_mbyte);
00836         }
00837       } else {
00838         QString s_kbyte;
00839         s_kbyte.sprintf("%4.2f",m_kbyte);
00840         return i18n("%1 KBytes").arg(s_kbyte);
00841       }
00842   } else {
00843     return i18n("%1 Bytes").arg((unsigned long)m_byte);
00844   }
00845   return QString::null;
00846 }
00847 
00848 void KPureftpdStat::slotShowExtendedInfo(QListViewItem *item) {
00849   if (!item) return;
00850   
00851   FTPSessionItem f;
00852   bool itemFound=false;
00853   
00854   for (FtpGuiMap::Iterator it=ftpGuiMap.begin(); it!=ftpGuiMap.end(); ++it) {
00855     if (*it == item) {
00856       f=ftpSessionMap[it.key()];
00857       itemFound=true;
00858       break;
00859     }
00860   }
00861   
00862   if (!itemFound) {
00863     kdWarning() << __FUNCTION__ << "(): clicked QListViewItem was not found in ftpGuiMap! ptr=" << item << endl;
00864     return;
00865   }
00866   
00867   txtExtInfo->setPaper(QBrush(kapp->palette().active().base()));
00868   switch (f.state()) {
00869     case FTPSessionItem::Idle:
00870       txtExtInfo->setText(i18n(
00871           "<qml><b>Local Host:</b> %1:%2<br>"
00872           "<b>Remote Host:</b> %3<br>"
00873           "</qml>"
00874           ).arg(f.localhost()).arg(f.port()).arg(f.host()));
00875     break;
00876     case FTPSessionItem::Error:
00877       txtExtInfo->setText(i18n(
00878           "<qml>There is an FTP error on this connection. In short "
00879           "time connection should close.</qml>"
00880           ));
00881     break;
00882     case FTPSessionItem::Download:
00883     case FTPSessionItem::Upload:
00884       txtExtInfo->setText(i18n(
00885           "<qml><b>File:</b> %1<br>"
00886           "<b>Local Host:</b> %2:%3 &nbsp; <b>Remote Host:</b> %4<br>"
00887           "<b>Current Size:</b> %5 of %6 (resumed at %7)<br>"
00888           "<b>Bandwidth:</b> %8/s<br>"
00889           "</qml>"
00890           ).arg(f.file()).arg(f.localhost()).arg(f.port()).arg(f.host())
00891            .arg(prettyByte(f.current_size())).arg(prettyByte(f.total_size()))
00892            .arg(prettyByte(f.resume())).arg(prettyByte(f.bandwidth())));
00893     break;
00894     case FTPSessionItem::Unknown:
00895       txtExtInfo->setText(i18n(
00896           "<qml>Unknown FTP session state. There may be incompatibility "
00897           "between <b>pure-ftpd</b> and this application.</qml>"
00898           ));
00899     break;
00900     default:
00901       kdWarning() << __FUNCTION__ << "(): Unknown FTP session state=" << f.state() << endl;
00902   }
00903 
00904 }
00905 
00906 
00907 void KPureftpdStat::processInfoOutput() {
00908   FtpSessionMap tmp_ftpSessionMap;
00909   FTPSessionItem::Status attr_state;
00910   pid_t attr_pid;
00911   int attr_percentage;
00912   unsigned long attr_time, attr_bandwidth;
00913   unsigned long long attr_resume, attr_current_size, attr_total_size;
00914   QString tmp, attr_account, attr_file, attr_host, attr_localhost, attr_port;
00915   QDomDocument doc;
00916   KListViewItem *item;
00917 
00918 
00919   doc.setContent(infoOutput);
00920   QDomElement docElem0 = doc.documentElement();
00921   QDomNode n = docElem0.firstChild();
00922 
00923   while (!n.isNull()) {
00924     QDomElement docElem = n.toElement();
00925     if (!docElem.isNull()) {
00926       tmp = docElem.attribute("state","");
00927       if (tmp == "IDLE") {
00928         attr_state = FTPSessionItem::Idle;
00929       } else if (tmp == "DOWNLOAD" || tmp == " DL ") {
00930         attr_state = FTPSessionItem::Download;
00931       } else if (tmp == "UPLOAD" || tmp == " UL ") {
00932         attr_state = FTPSessionItem::Upload;
00933       } else if (tmp == "ERROR" || tmp == "ERR!") {
00934         attr_state = FTPSessionItem::Error;
00935       } else {
00936         attr_state = FTPSessionItem::Unknown;
00937       }
00938       attr_account      = docElem.attribute("account","");
00939       attr_file         = docElem.attribute("file","");
00940       attr_host         = docElem.attribute("host","");
00941       attr_localhost    = docElem.attribute("localhost","");
00942       attr_port         = docElem.attribute("localport","");
00943       tmp               = docElem.attribute("resume","0");
00944       attr_resume       = tmp.toULong();
00945       tmp               = docElem.attribute("current_size","0");
00946       attr_current_size = tmp.toULong();
00947       tmp               = docElem.attribute("total_size","0");
00948       attr_total_size   = tmp.toULong();
00949       tmp               = docElem.attribute("time","0");
00950       attr_time         = tmp.toULong();
00951       tmp               = docElem.attribute("bandwidth","0");
00952       attr_bandwidth    = tmp.toULong();
00953       tmp               = docElem.attribute("percentage","0");
00954       attr_percentage   = tmp.toULong();
00955       tmp               = docElem.attribute("pid","0");
00956       attr_pid          = tmp.toInt();
00957       FTPSessionItem ftpItem(attr_percentage, attr_pid, attr_state,
00958                              attr_time, attr_bandwidth,
00959                              attr_resume, attr_current_size, attr_total_size,
00960                              attr_account, attr_file, attr_host,
00961                              attr_localhost, attr_port);
00962       tmp_ftpSessionMap[attr_pid]=ftpItem;
00963     }
00964     n = n.nextSibling();
00965   }
00966 
00967   // first, remove the items which are no longer
00968   FtpSessionMap::Iterator it=ftpSessionMap.begin();
00969   while (it != ftpSessionMap.end()) {
00970     if (!tmp_ftpSessionMap.contains(it.key())) {
00971       delete ftpGuiMap[it.key()];
00972       ftpGuiMap.remove(it.key());
00973       ftpSessionMap.remove(it);
00974       it=ftpSessionMap.begin();
00975     } else {
00976       ++it;
00977     }
00978   }
00979 
00980   // second, add the new elements & update the current ones
00981   for (FtpSessionMap::Iterator it=tmp_ftpSessionMap.begin(); it!=tmp_ftpSessionMap.end(); ++it) {
00982     QString tmp_state;
00983     switch ((*it).state()) {
00984       case FTPSessionItem::Idle:
00985         tmp_state = i18n("ftp state","Idle");
00986       break;
00987       case FTPSessionItem::Download:
00988         tmp_state = i18n("ftp state","Download");
00989       break;
00990       case FTPSessionItem::Upload:
00991         tmp_state = i18n("ftp state","Upload");
00992       break;
00993       case FTPSessionItem::Error:
00994         tmp_state = i18n("ftp state","Error");
00995       break;
00996       default:
00997         tmp_state = i18n("ftp state","Unknown");
00998     }
00999     long int total_sec = (*it).time();
01000     int m_hour =  (int) total_sec / 3600;
01001     int m_min  = (int) (total_sec - m_hour * 3600) / 60;
01002     int m_sec  = total_sec % 60;
01003     QString m_time;
01004     m_time.sprintf("%d:%02d:%02d",m_hour,m_min,m_sec);
01005 
01006     if (!ftpSessionMap.contains(it.key())) {
01007       // add new element
01008       item = new KListViewItem(connList,(*it).account(),tmp_state,m_time,QString::number((*it).percentage())+"%",(*it).file());
01009       ftpGuiMap[it.key()]=item;
01010     } else {
01011       // update the old one with current data
01012       ftpGuiMap[it.key()]->setText(0,(*it).account());
01013       ftpGuiMap[it.key()]->setText(1,tmp_state);
01014       ftpGuiMap[it.key()]->setText(2,m_time);
01015       ftpGuiMap[it.key()]->setText(3,QString::number((*it).percentage())+"%");
01016       ftpGuiMap[it.key()]->setText(4,(*it).file());
01017     }
01018     ftpSessionMap[it.key()]=tmp_ftpSessionMap[it.key()];
01019   }  
01020 
01021   bool ftpSessionIsActive=false;
01022   for (FtpGuiMap::Iterator it=ftpGuiMap.begin(); it!=ftpGuiMap.end(); ++it) {
01023     if (connList->isSelected(*it)) {
01024       slotShowExtendedInfo(*it);
01025       ftpSessionIsActive=true;
01026     }
01027   }
01028   if (ftpSessionIsActive) {
01029     txtExtInfo->setPaper(QBrush(kapp->palette().active().base()));
01030   } else {
01031     txtExtInfo->setPaper(QBrush(kapp->palette().active().background()));
01032   }
01033 }
01034 
01035 
01036 void KPureftpdStat::slotChangedInterval(int interval) {
01037   if (infoTimer->isActive()) {
01038     infoTimer->changeInterval(1000*interval);
01039   }
01040 }
01041 
01042 
01043 // "Configuration" tab
01044 void KPureftpdStat::slotInfoConfDefault(bool b) {
01045   pureftpwhoDefault->setEnabled(b);
01046   pureftpwhoPath->setEnabled(b && !pureftpwhoDefault->isChecked());
01047   txtPureftpwhoPath->setEnabled(b && !pureftpwhoDefault->isChecked());
01048   txtInfoCommand->setEnabled(!b);
01049   infoCommand->setEnabled(!b);
01050 }
01051 
01052 void KPureftpdStat::slotInfoConfUseDefault(bool b) {
01053   txtPureftpwhoPath->setEnabled(!b);
01054   pureftpwhoPath->setEnabled(!b);
01055 }
01056 
01057 void KPureftpdStat::slotLogConfDefault(bool b) {
01058   logFileName->setEnabled(b);
01059   txtLogFileName->setEnabled(b);
01060   logCommand->setEnabled(!b);
01061   txtLogCommand->setEnabled(!b);
01062 }
01063 
01064 
01065 
01066 // KCMModule usual stuff
01067 
01068 void KPureftpdStat::load() {
01069   config->setGroup("Find");
01070   caseSensitive->setChecked(config->readBoolEntry("Case Sensitive",false));
01071   wholeWords->setChecked(config->readBoolEntry("Whole Words",false));
01072   findBackwards->setChecked(config->readBoolEntry("Find Backwards",false));
01073   editSearch->setText(config->readEntry("Search String",QString::null));
01074 
01075   config->setGroup("Log Tab");
01076   startDir = config->readEntry("Log Saving Directory",QDir::currentDirPath());
01077   fileName = config->readEntry("Log Filename","pureftpd.log");
01078 
01079   config->setGroup("Options");
01080   updateInterval->setValue(config->readUnsignedNumEntry("Info Update Interval",3));
01081   infoTimer->changeInterval(1000*updateInterval->value());
01082   infoTimer->stop();
01083   
01084   historyLines->setValue(config->readUnsignedNumEntry("History Log Lines",500));
01085   logFileName->setURL(config->readEntry("Log FileName","/var/log/pureftpd.log"));
01086   pureftpwhoPath->setURL(config->readEntry("Pureftpwho Path","/usr/local/sbin/pure-ftpwho"));
01087   infoCommand->setText(config->readEntry("Custom Info Command",QString::null));
01088   logCommand->setText(config->readEntry("Custom Log Command",QString::null));
01089   pureftpwhoDefault->setChecked(config->readBoolEntry("Use Default Pureftpwho",true));
01090   rbInfoDefault->setChecked(config->readBoolEntry("Use Pureftpwho",true));
01091   rbInfoCustom->setChecked(!config->readBoolEntry("Use Pureftpwho",true));
01092   rbLogFile->setChecked(config->readBoolEntry("Use Log File",true));
01093   rbLogCustom->setChecked(!config->readBoolEntry("Use Log File",true));
01094   
01095   KConfig *tmp_config = new KConfig("kcmpureftpdrc",true,false);
01096   tmp_config->setGroup("Options");
01097   pureftpwhoDefaultPath=tmp_config->readEntry("Pureftpwho Path","/usr/local/sbin/pure-ftpwho");
01098   delete tmp_config;
01099   
01100   emit changed(false);
01101 }
01102 
01103 void KPureftpdStat::save() {
01104   config->setGroup("Find");
01105   config->writeEntry("Case Sensitive",caseSensitive->isChecked());
01106   config->writeEntry("Whole Words",wholeWords->isChecked());
01107   config->writeEntry("Find Backwards",findBackwards->isChecked());
01108   config->writeEntry("Search String",editSearch->text());
01109 
01110   config->setGroup("Options");
01111   config->writeEntry("Info Update Interval",updateInterval->value());
01112   config->writeEntry("History Log Lines",historyLines->value());
01113   config->writeEntry("Log FileName",logFileName->url());
01114   config->writeEntry("Pureftpwho Path",pureftpwhoPath->url());
01115   config->writeEntry("Custom Info Command",infoCommand->text());
01116   config->writeEntry("Custom Log Command",logCommand->text());
01117   config->writeEntry("Use Default Pureftpwho",pureftpwhoDefault->isChecked());
01118   config->writeEntry("Use Pureftpwho",rbInfoDefault->isChecked());
01119   config->writeEntry("Use Log File",rbLogFile->isChecked());
01120 
01121   config->sync();
01122   emit changed(false);
01123 }
01124 
01125 
01126 void KPureftpdStat::defaults() {
01127     load();
01128     emit changed(false);
01129 }
01130 
01131 int KPureftpdStat::buttons() {
01132     return KCModule::Default | KCModule::Apply | KCModule::Help;
01133 }
01134 
01135 QString KPureftpdStat::quickHelp() const {
01136     return i18n("<h1>PureFTPd Statistics</h1> <p>This module allow you to track statistics "
01137                 "from <b>pure-ftpd</b> FTP server. You can see real time information about "
01138                 "FTP connection on your FTP server as well you may follow information written "
01139                 "to syslog by the server. <p>To obtain this high "
01140                 "quality server go to <a href=\"http://www.pureftpd.org/\">http://www.pureftpd.org/</a>.</p>"
01141                );
01142 }
01143 
01144 const KAboutData *KPureftpdStat::aboutData() const {
01145     KAboutData *myAboutData = new KAboutData(
01146                                   "kcmpureftpdstat", I18N_NOOP("KCM PureFtpd Statistics"),
01147                                   VERSION, I18N_NOOP("KControl module for PureFtpd Statistics"),
01148                                   KAboutData::License_GPL, "(c) 2002, 2003 Claudiu Costin",0,
01149                                   "http://www.ro.kde.org/kcmpureftpd/",
01150                                   "claudiuc@kde.org");
01151     myAboutData->addAuthor("Claudiu Costin",I18N_NOOP("Original author"),"claudiuc@kde.org");
01152     myAboutData->addCredit("Iuliana Costin",
01153                            I18N_NOOP("My lovely wife who allowed me to spend countless hours in "
01154                                      "front of computer."),QString::null);
01155     myAboutData->addCredit("Frank Denis",
01156                            I18N_NOOP("Pureftpd FTP server author. "
01157                                      "Many thanks for such great piece of code."),
01158                                      "j@pureftpd.org");
01159     return myAboutData;
01160 }
01161 
01162 extern "C" {
01163     KCModule *create_pureftpdstat(QWidget *parent, const char *name) {
01164         QString dummy=name;
01165         KGlobal::locale()->insertCatalogue("kcmpureftpd");
01166         return new KPureftpdStat(parent,"kcmpureftpdstat");
01167     };
01168 
01169     void init_pureftpdstat() {
01170         kapp->startServiceByDesktopName("kcmpureftpdstat");
01171     };
01172 }
01173 
01174 
Generated on Thu Jul 24 01:57:13 2003 by doxygen 1.2.15.