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 <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.