00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
#define USE_QSOCKET
00021
00022
#include "networkscanner.h"
00023
00024
#include <qprogressbar.h>
00025
#include <kpushbutton.h>
00026
#include <qlayout.h>
00027
#include <qtimer.h>
00028
#include <qlabel.h>
00029
#include <qcombobox.h>
00030
#include <qlineedit.h>
00031
#include <qregexp.h>
00032
#include <qsocket.h>
00033
#include <klocale.h>
00034
#include <kextendedsocket.h>
00035
#include <kmessagebox.h>
00036
#include <knumvalidator.h>
00037
#include <kdebug.h>
00038
#include <unistd.h>
00039
00040
class NetworkScanner::NetworkScannerPrivate
00041 {
00042
public:
00043
int port;
00044
QString prefixaddress;
00045
int currentaddress;
00046
int timeout;
00047
bool scanning;
00048
QPtrList<NetworkScanner::SocketInfo> printers;
00049
00050
QProgressBar *bar;
00051 KPushButton *scan, *settings;
00052
QLabel *subnetlab;
00053
QTimer *timer;
00054
#ifdef USE_QSOCKET
00055
QSocket *socket;
00056
#else
00057
KExtendedSocket *socket;
00058
#endif
00059
00060 NetworkScannerPrivate(
int portvalue ) : port( portvalue )
00061 {
00062 prefixaddress = localPrefix();
00063 currentaddress = 1;
00064 timeout = 50;
00065 scanning =
false;
00066 printers.setAutoDelete(
true );
00067 }
00068
QString localPrefix();
00069
QString scanString();
00070 };
00071
00072
QString NetworkScanner::NetworkScannerPrivate::localPrefix()
00073 {
00074
char buf[256];
00075 buf[0] =
'\0';
00076
if (!gethostname(buf,
sizeof(buf)))
00077 buf[
sizeof(buf)-1] =
'\0';
00078
QPtrList<KAddressInfo> infos = KExtendedSocket::lookup(buf, QString::null);
00079 infos.
setAutoDelete(
true);
00080
if (infos.
count() > 0)
00081 {
00082
QString IPstr = infos.
first()->address()->nodeName();
00083
int p = IPstr.
findRev(
'.');
00084 IPstr.
truncate(p);
00085
return IPstr;
00086 }
00087
return QString::null;
00088 }
00089
00090
QString NetworkScanner::NetworkScannerPrivate::scanString()
00091 {
00092
QString s = prefixaddress +
".*";
00093
if ( port != -1 )
00094 s.
append(
":" ).append( QString::number( port ) );
00095
return s;
00096 }
00097
00098 NetworkScanner::NetworkScanner(
int port,
QWidget *parent,
const char *name )
00099 :
QWidget( parent, name )
00100 {
00101 d =
new NetworkScannerPrivate( port );
00102 d->bar =
new QProgressBar( 256,
this );
00103 d->settings =
new KPushButton( KGuiItem( i18n(
"&Settings..." ),
"configure" ),
this );
00104 d->scan =
new KPushButton( KGuiItem( i18n(
"Sc&an" ),
"viewmag" ),
this );
00105 d->timer =
new QTimer(
this );
00106
#ifdef USE_QSOCKET
00107
d->socket =
new QSocket(
this );
00108
#else
00109
d->socket =
new KExtendedSocket();
00110
#endif
00111
QLabel *label =
new QLabel( i18n(
"Network scan:" ),
this );
00112 d->subnetlab =
new QLabel( i18n(
"Subnet: %1" ).arg( d->scanString() ),
this );
00113
00114
QGridLayout *l0 =
new QGridLayout(
this, 4, 2, 0, 10 );
00115 l0->
addMultiCellWidget( label, 0, 0, 0, 1 );
00116 l0->
addMultiCellWidget( d->bar, 1, 1, 0, 1 );
00117 l0->
addMultiCellWidget( d->subnetlab, 2, 2, 0, 1 );
00118 l0->
addWidget( d->settings, 3, 0 );
00119 l0->
addWidget( d->scan, 3, 1 );
00120
00121 connect( d->timer, SIGNAL( timeout() ), SLOT( slotTimeout() ) );
00122 connect( d->settings, SIGNAL( clicked() ), SLOT( slotSettingsClicked() ) );
00123 connect( d->scan, SIGNAL( clicked() ), SLOT( slotScanClicked() ) );
00124
#ifdef USE_QSOCKET
00125
connect( d->socket, SIGNAL( connected() ), SLOT( slotConnectionSuccess() ) );
00126 connect( d->socket, SIGNAL( error(
int ) ), SLOT( slotConnectionFailed(
int ) ) );
00127
#else
00128
connect( d->socket, SIGNAL( connectionSuccess() ), SLOT( slotConnectionSuccess() ) );
00129 connect( d->socket, SIGNAL( connectionFailed(
int ) ), SLOT( slotConnectionFailed(
int ) ) );
00130
#endif
00131
}
00132
00133 NetworkScanner::~NetworkScanner()
00134 {
00135
#ifndef USE_QSOCKET
00136
delete d->socket;
00137
#endif
00138
delete d;
00139 }
00140
00141
void NetworkScanner::start()
00142 {
00143
if ( d->scanning )
00144
return;
00145
00146 d->printers.clear();
00147 emit scanStarted();
00148 d->settings->setEnabled(
false );
00149 d->scan->setGuiItem( KGuiItem( i18n(
"&Abort" ),
"stop" ) );
00150 d->currentaddress = -1;
00151 d->scanning =
true;
00152 next();
00153 }
00154
00155
void NetworkScanner::slotScanClicked()
00156 {
00157
if ( !d->scanning )
00158 {
00159
if ( d->localPrefix() == d->prefixaddress ||
00160 KMessageBox::warningContinueCancel( this->parentWidget(),
00161 i18n(
"You are about to scan a subnet (%1.*) that does not "
00162
"correspond to the current subnet of this computer (%2.*). Do you want "
00163
"to scan the specified subnet anyway?" ).arg( d->prefixaddress ).arg( d->localPrefix() ),
00164 QString::null, KGuiItem( i18n(
"&Scan" ),
"viewmag" ),
"askForScan" ) == KMessageBox::Continue )
00165 start();
00166 }
00167
else
00168 {
00169
#ifdef USE_QSOCKET
00170
d->socket->close();
00171
#else
00172
d->socket->cancelAsyncConnect();
00173
#endif
00174
finish();
00175 }
00176 }
00177
00178
void NetworkScanner::finish()
00179 {
00180
if ( !d->scanning )
00181
return;
00182
00183 d->settings->setEnabled(
true );
00184 d->scan->setGuiItem( KGuiItem( i18n(
"Sc&an" ),
"viewmag" ) );
00185 d->bar->reset();
00186 d->scanning =
false;
00187 emit scanFinished();
00188 }
00189
00190
void NetworkScanner::slotSettingsClicked()
00191 {
00192 NetworkScannerConfig dlg(
this );
00193 dlg.exec();
00194 }
00195
00196
void NetworkScanner::slotNext()
00197 {
00198
if ( !d->scanning )
00199
return;
00200
00201 d->timer->stop();
00202
#ifdef USE_QSOCKET
00203
d->socket->connectToHost( d->prefixaddress +
"." + QString::number( d->currentaddress ), d->port );
00204 kdDebug() <<
"Address: " << d->socket->peerName() <<
", Port: " << d->socket->peerPort() << endl;
00205
#else
00206
d->socket->setAddress( d->prefixaddress +
"." + QString::number( d->currentaddress ), d->port );
00207 d->socket->startAsyncLookup();
00208 kdDebug() <<
"Address: " << d->socket->host() <<
", Port: " << d->socket->port() << endl;
00209
#endif
00210
d->timer->start( d->timeout,
true );
00211 }
00212
00213
void NetworkScanner::next()
00214 {
00215
00216 d->currentaddress++;
00217
if ( d->currentaddress >= 256 )
00218 finish();
00219
else
00220 {
00221 d->bar->setProgress( d->currentaddress );
00222
QTimer::singleShot( 0,
this, SLOT( slotNext() ) );
00223 }
00224 }
00225
00226
void NetworkScanner::slotTimeout()
00227 {
00228 kdDebug() <<
"Timeout" << endl;
00229
if ( !d->scanning )
00230
return;
00231
00232
#ifdef USE_QSOCKET
00233
d->socket->close();
00234
#else
00235
d->socket->cancelAsyncConnect();
00236
#endif
00237
next();
00238 }
00239
00240
void NetworkScanner::slotConnectionSuccess()
00241 {
00242 kdDebug() <<
"Success" << endl;
00243
#ifdef USE_QSOCKET
00244
KSocketAddress *addr = KExtendedSocket::peerAddress( d->socket->socket() );
00245
#else
00246
KSocketAddress *addr = const_cast<KSocketAddress*>( d->socket->peerAddress() );
00247
#endif
00248
kdDebug() <<
"Connection success: " << ( addr ? addr->pretty() :
QString(
"ERROR" ) ) << endl;
00249 kdDebug() <<
"Socket: " << d->socket->socket() << endl;
00250
if ( addr )
00251 {
00252 SocketInfo *info =
new SocketInfo;
00253
#ifdef USE_QSOCKET
00254
info->IP = d->socket->peerName();
00255
#else
00256
info->IP = d->socket->host();
00257
#endif
00258
info->Port = d->port;
00259
QString portname;
00260 KExtendedSocket::resolve( addr, info->Name, portname );
00261 d->printers.append( info );
00262 d->socket->close();
00263
delete addr;
00264 }
00265
else
00266 kdDebug() <<
"Unconnected socket, skipping" << endl;
00267 next();
00268 }
00269
00270
void NetworkScanner::slotConnectionFailed(
int )
00271 {
00272 kdDebug() <<
"Failure" << endl;
00273 next();
00274 }
00275
00276
const QPtrList<NetworkScanner::SocketInfo>* NetworkScanner::printerList()
00277 {
00278
return &( d->printers );
00279 }
00280
00281
int NetworkScanner::timeout()
const
00282
{
00283
return d->timeout;
00284 }
00285
00286
void NetworkScanner::setTimeout(
int to )
00287 {
00288 d->timeout = to;
00289 }
00290
00291
QString NetworkScanner::subnet()
const
00292
{
00293
return d->prefixaddress;
00294 }
00295
00296
void NetworkScanner::setSubnet(
const QString& sn )
00297 {
00298 d->prefixaddress = sn;
00299 d->subnetlab->setText( i18n(
"Subnet: %1" ).arg( d->scanString() ) );
00300 }
00301
00302
int NetworkScanner::port()
const
00303
{
00304
return d->port;
00305 }
00306
00307
void NetworkScanner::setPort(
int p )
00308 {
00309 d->port = p;
00310 d->subnetlab->setText( i18n(
"Subnet: %1" ).arg( d->scanString() ) );
00311 }
00312
00313
bool NetworkScanner::checkPrinter(
const QString& host,
int port )
00314 {
00315
00316
QPtrListIterator<NetworkScanner::SocketInfo> it( d->printers );
00317
for ( ; it.current(); ++it )
00318 {
00319
if ( port == it.current()->Port && ( host == it.current()->IP ||
00320 host == it.current()->Name ) )
00321
return true;
00322 }
00323
00324
00325 KExtendedSocket extsock( host, port );
00326 extsock.setBlockingMode(
false );
00327 extsock.setTimeout( 0, d->timeout * 1000 );
00328
return ( extsock.connect() == 0 );
00329 }
00330
00331 NetworkScannerConfig::NetworkScannerConfig(NetworkScanner *scanner,
const char *name)
00332 : KDialogBase(scanner, name, true,
QString::null, Ok|Cancel, Ok, true)
00333 {
00334 scanner_ = scanner;
00335
QWidget *dummy =
new QWidget(
this);
00336 setMainWidget(dummy);
00337 KIntValidator *val =
new KIntValidator(
this );
00338
QLabel *masklabel =
new QLabel(i18n(
"&Subnetwork:"),dummy);
00339
QLabel *portlabel =
new QLabel(i18n(
"&Port:"),dummy);
00340
QLabel *toutlabel =
new QLabel(i18n(
"&Timeout (ms):"),dummy);
00341
QLineEdit *mm =
new QLineEdit(dummy);
00342 mm->
setText(QString::fromLatin1(
".[0-255]"));
00343 mm->
setReadOnly(
true);
00344 mm->setFixedWidth(fontMetrics().width(mm->
text())+10);
00345
00346 mask_ =
new QLineEdit(dummy);
00347 mask_->setAlignment(Qt::AlignRight);
00348 port_ =
new QComboBox(
true,dummy);
00349
if ( port_->lineEdit() )
00350 port_->lineEdit()->setValidator( val );
00351 tout_ =
new QLineEdit(dummy);
00352 tout_->setValidator( val );
00353
00354 masklabel->
setBuddy(mask_);
00355 portlabel->
setBuddy(port_);
00356 toutlabel->
setBuddy(tout_);
00357
00358 mask_->setText(scanner_->subnet());
00359 port_->insertItem(
"631");
00360 port_->insertItem(
"9100");
00361 port_->insertItem(
"9101");
00362 port_->insertItem(
"9102");
00363 port_->setEditText(QString::number(scanner_->port()));
00364 tout_->setText(QString::number(scanner_->timeout()));
00365
00366
QGridLayout *main_ =
new QGridLayout(dummy, 3, 2, 0, 10);
00367
QHBoxLayout *lay1 =
new QHBoxLayout(0, 0, 5);
00368 main_->
addWidget(masklabel, 0, 0);
00369 main_->
addWidget(portlabel, 1, 0);
00370 main_->
addWidget(toutlabel, 2, 0);
00371 main_->
addLayout(lay1, 0, 1);
00372 main_->
addWidget(port_, 1, 1);
00373 main_->
addWidget(tout_, 2, 1);
00374 lay1->addWidget(mask_,1);
00375 lay1->addWidget(mm,0);
00376
00377 resize(250,130);
00378 setCaption(i18n(
"Scan Configuration"));
00379 }
00380
00381 NetworkScannerConfig::~NetworkScannerConfig()
00382 {
00383 }
00384
00385
void NetworkScannerConfig::slotOk()
00386 {
00387
QString msg;
00388
QRegExp re(
"(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})");
00389
if (!re.exactMatch(mask_->text()))
00390 msg = i18n(
"Wrong subnetwork specification.");
00391
else
00392 {
00393
for (
int i=1; i<=3; i++)
00394
if (re.cap(i).toInt() >= 255)
00395 {
00396 msg = i18n(
"Wrong subnetwork specification.");
00397
break;
00398 }
00399 }
00400
00401
bool ok(
false);
00402
int v = tout_->text().toInt(&ok);
00403
if (!ok || v <= 0)
00404 msg = i18n(
"Wrong timeout specification.");
00405 v = port_->currentText().toInt(&ok);
00406
if (!ok || v <= 0)
00407 msg = i18n(
"Wrong port specification.");
00408
if (!msg.
isEmpty())
00409 {
00410 KMessageBox::error(
this,msg);
00411
return;
00412 }
00413
00414 scanner_->setTimeout( tout_->text().toInt() );
00415 scanner_->setSubnet( mask_->text() );
00416 scanner_->setPort( port_->currentText().toInt() );
00417
00418 KDialogBase::slotOk();
00419 }
00420
00421
#include "networkscanner.moc"