diff options
Diffstat (limited to 'tdeprint/management/networkscanner.cpp')
-rw-r--r-- | tdeprint/management/networkscanner.cpp | 421 |
1 files changed, 421 insertions, 0 deletions
diff --git a/tdeprint/management/networkscanner.cpp b/tdeprint/management/networkscanner.cpp new file mode 100644 index 000000000..a52e66018 --- /dev/null +++ b/tdeprint/management/networkscanner.cpp @@ -0,0 +1,421 @@ +/* + * This file is part of the KDE libraries + * Copyright (c) 2001-2002 Michael Goffioul <tdeprint@swing.be> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License version 2 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +#define USE_QSOCKET + +#include "networkscanner.h" + +#include <tqprogressbar.h> +#include <kpushbutton.h> +#include <tqlayout.h> +#include <tqtimer.h> +#include <tqlabel.h> +#include <tqcombobox.h> +#include <tqlineedit.h> +#include <tqregexp.h> +#include <tqsocket.h> +#include <klocale.h> +#include <kextendedsocket.h> +#include <kmessagebox.h> +#include <knumvalidator.h> +#include <kdebug.h> +#include <unistd.h> + +class NetworkScanner::NetworkScannerPrivate +{ +public: + int port; + TQString prefixaddress; + int currentaddress; + int timeout; + bool scanning; + TQPtrList<NetworkScanner::SocketInfo> printers; + + TQProgressBar *bar; + KPushButton *scan, *settings; + TQLabel *subnetlab; + TQTimer *timer; +#ifdef USE_QSOCKET + TQSocket *socket; +#else + KExtendedSocket *socket; +#endif + + NetworkScannerPrivate( int portvalue ) : port( portvalue ) + { + prefixaddress = localPrefix(); + currentaddress = 1; + timeout = 50; + scanning = false; + printers.setAutoDelete( true ); + } + TQString localPrefix(); + TQString scanString(); +}; + +TQString NetworkScanner::NetworkScannerPrivate::localPrefix() +{ + char buf[256]; + buf[0] = '\0'; + if (!gethostname(buf, sizeof(buf))) + buf[sizeof(buf)-1] = '\0'; + TQPtrList<KAddressInfo> infos = KExtendedSocket::lookup(buf, TQString::null); + infos.setAutoDelete(true); + if (infos.count() > 0) + { + TQString IPstr = infos.first()->address()->nodeName(); + int p = IPstr.findRev('.'); + IPstr.truncate(p); + return IPstr; + } + return TQString::null; +} + +TQString NetworkScanner::NetworkScannerPrivate::scanString() +{ + TQString s = prefixaddress + ".*"; + if ( port != -1 ) + s.append( ":" ).append( TQString::number( port ) ); + return s; +} + +NetworkScanner::NetworkScanner( int port, TQWidget *parent, const char *name ) + : TQWidget( parent, name ) +{ + d = new NetworkScannerPrivate( port ); + d->bar = new TQProgressBar( 256, this ); + d->settings = new KPushButton( KGuiItem( i18n( "&Settings" ), "configure" ), this ); + d->scan = new KPushButton( KGuiItem( i18n( "Sc&an" ), "viewmag" ), this ); + d->timer = new TQTimer( this ); +#ifdef USE_QSOCKET + d->socket = new TQSocket( TQT_TQOBJECT(this) ); +#else + d->socket = new KExtendedSocket(); +#endif + TQLabel *label = new TQLabel( i18n( "Network scan:" ), this ); + d->subnetlab = new TQLabel( i18n( "Subnet: %1" ).arg( d->scanString() ), this ); + + TQGridLayout *l0 = new TQGridLayout( this, 4, 2, 0, 10 ); + l0->addMultiCellWidget( label, 0, 0, 0, 1 ); + l0->addMultiCellWidget( d->bar, 1, 1, 0, 1 ); + l0->addMultiCellWidget( d->subnetlab, 2, 2, 0, 1 ); + l0->addWidget( d->settings, 3, 0 ); + l0->addWidget( d->scan, 3, 1 ); + + connect( d->timer, TQT_SIGNAL( timeout() ), TQT_SLOT( slotTimeout() ) ); + connect( d->settings, TQT_SIGNAL( clicked() ), TQT_SLOT( slotSettingsClicked() ) ); + connect( d->scan, TQT_SIGNAL( clicked() ), TQT_SLOT( slotScanClicked() ) ); +#ifdef USE_QSOCKET + connect( d->socket, TQT_SIGNAL( connected() ), TQT_SLOT( slotConnectionSuccess() ) ); + connect( d->socket, TQT_SIGNAL( error( int ) ), TQT_SLOT( slotConnectionFailed( int ) ) ); +#else + connect( d->socket, TQT_SIGNAL( connectionSuccess() ), TQT_SLOT( slotConnectionSuccess() ) ); + connect( d->socket, TQT_SIGNAL( connectionFailed( int ) ), TQT_SLOT( slotConnectionFailed( int ) ) ); +#endif +} + +NetworkScanner::~NetworkScanner() +{ +#ifndef USE_QSOCKET + delete d->socket; +#endif + delete d; +} + +void NetworkScanner::start() +{ + if ( d->scanning ) + return; + + d->printers.clear(); + emit scanStarted(); + d->settings->setEnabled( false ); + d->scan->setGuiItem( KGuiItem( i18n( "&Abort" ), "stop" ) ); + d->currentaddress = -1; + d->scanning = true; + next(); +} + +void NetworkScanner::slotScanClicked() +{ + if ( !d->scanning ) + { + if ( d->localPrefix() == d->prefixaddress || + KMessageBox::warningContinueCancel( this->parentWidget(), + i18n( "You are about to scan a subnet (%1.*) that does not " + "correspond to the current subnet of this computer (%2.*). Do you want " + "to scan the specified subnet anyway?" ).arg( d->prefixaddress ).arg( d->localPrefix() ), + TQString::null, KGuiItem( i18n( "&Scan" ), "viewmag" ), "askForScan" ) == KMessageBox::Continue ) + start(); + } + else + { +#ifdef USE_QSOCKET + d->socket->close(); +#else + d->socket->cancelAsyncConnect(); +#endif + finish(); + } +} + +void NetworkScanner::finish() +{ + if ( !d->scanning ) + return; + + d->settings->setEnabled( true ); + d->scan->setGuiItem( KGuiItem( i18n( "Sc&an" ), "viewmag" ) ); + d->bar->reset(); + d->scanning = false; + emit scanFinished(); +} + +void NetworkScanner::slotSettingsClicked() +{ + NetworkScannerConfig dlg( this ); + dlg.exec(); +} + +void NetworkScanner::slotNext() +{ + if ( !d->scanning ) + return; + + d->timer->stop(); +#ifdef USE_QSOCKET + d->socket->connectToHost( d->prefixaddress + "." + TQString::number( d->currentaddress ), d->port ); + kdDebug() << "Address: " << d->socket->peerName() << ", Port: " << d->socket->peerPort() << endl; +#else + d->socket->setAddress( d->prefixaddress + "." + TQString::number( d->currentaddress ), d->port ); + d->socket->startAsyncLookup(); + kdDebug() << "Address: " << d->socket->host() << ", Port: " << d->socket->port() << endl; +#endif + d->timer->start( d->timeout, true ); +} + +void NetworkScanner::next() +{ + //kdDebug() << "Next" << endl; + d->currentaddress++; + if ( d->currentaddress >= 256 ) + finish(); + else + { + d->bar->setProgress( d->currentaddress ); + TQTimer::singleShot( 0, this, TQT_SLOT( slotNext() ) ); + } +} + +void NetworkScanner::slotTimeout() +{ + kdDebug() << "Timeout" << endl; + if ( !d->scanning ) + return; + +#ifdef USE_QSOCKET + d->socket->close(); +#else + d->socket->cancelAsyncConnect(); +#endif + next(); +} + +void NetworkScanner::slotConnectionSuccess() +{ + kdDebug() << "Success" << endl; +#ifdef USE_QSOCKET + KSocketAddress *addr = KExtendedSocket::peerAddress( d->socket->socket() ); +#else + KSocketAddress *addr = const_cast<KSocketAddress*>( d->socket->peerAddress() ); +#endif + kdDebug() << "Connection success: " << ( addr ? addr->pretty() : TQString( "ERROR" ) ) << endl; + kdDebug() << "Socket: " << d->socket->socket() << endl; + if ( addr ) + { + SocketInfo *info = new SocketInfo; +#ifdef USE_QSOCKET + info->IP = d->socket->peerName(); +#else + info->IP = d->socket->host(); +#endif + info->Port = d->port; + TQString portname; + KExtendedSocket::resolve( addr, info->Name, portname ); + d->printers.append( info ); + d->socket->close(); + delete addr; + } + else + kdDebug() << "Unconnected socket, skipping" << endl; + next(); +} + +void NetworkScanner::slotConnectionFailed( int ) +{ + kdDebug() << "Failure" << endl; + next(); +} + +const TQPtrList<NetworkScanner::SocketInfo>* NetworkScanner::printerList() +{ + return &( d->printers ); +} + +int NetworkScanner::timeout() const +{ + return d->timeout; +} + +void NetworkScanner::setTimeout( int to ) +{ + d->timeout = to; +} + +TQString NetworkScanner::subnet() const +{ + return d->prefixaddress; +} + +void NetworkScanner::setSubnet( const TQString& sn ) +{ + d->prefixaddress = sn; + d->subnetlab->setText( i18n( "Subnet: %1" ).arg( d->scanString() ) ); +} + +int NetworkScanner::port() const +{ + return d->port; +} + +void NetworkScanner::setPort( int p ) +{ + d->port = p; + d->subnetlab->setText( i18n( "Subnet: %1" ).arg( d->scanString() ) ); +} + +bool NetworkScanner::checkPrinter( const TQString& host, int port ) +{ + // try first to find it in the SocketInfo list + TQPtrListIterator<NetworkScanner::SocketInfo> it( d->printers ); + for ( ; it.current(); ++it ) + { + if ( port == it.current()->Port && ( host == it.current()->IP || + host == it.current()->Name ) ) + return true; + } + + // not found in SocketInfo list, try to establish connection + KExtendedSocket extsock( host, port ); + extsock.setBlockingMode( false ); + extsock.setTimeout( 0, d->timeout * 1000 ); + return ( extsock.connect() == 0 ); +} + +NetworkScannerConfig::NetworkScannerConfig(NetworkScanner *scanner, const char *name) + : KDialogBase(scanner, name, true, TQString::null, Ok|Cancel, Ok, true) +{ + scanner_ = scanner; + TQWidget *dummy = new TQWidget(this); + setMainWidget(dummy); + KIntValidator *val = new KIntValidator( this ); + TQLabel *masklabel = new TQLabel(i18n("&Subnetwork:"),dummy); + TQLabel *portlabel = new TQLabel(i18n("&Port:"),dummy); + TQLabel *toutlabel = new TQLabel(i18n("&Timeout (ms):"),dummy); + TQLineEdit *mm = new TQLineEdit(dummy); + mm->setText(TQString::tqfromLatin1(".[0-255]")); + mm->setReadOnly(true); + mm->setFixedWidth(fontMetrics().width(mm->text())+10); + + mask_ = new TQLineEdit(dummy); + mask_->tqsetAlignment(Qt::AlignRight); + port_ = new TQComboBox(true,dummy); + if ( port_->lineEdit() ) + port_->lineEdit()->setValidator( val ); + tout_ = new TQLineEdit(dummy); + tout_->setValidator( val ); + + masklabel->setBuddy(mask_); + portlabel->setBuddy(port_); + toutlabel->setBuddy(tout_); + + mask_->setText(scanner_->subnet()); + port_->insertItem("631"); + port_->insertItem("9100"); + port_->insertItem("9101"); + port_->insertItem("9102"); + port_->setEditText(TQString::number(scanner_->port())); + tout_->setText(TQString::number(scanner_->timeout())); + + TQGridLayout *main_ = new TQGridLayout(dummy, 3, 2, 0, 10); + TQHBoxLayout *lay1 = new TQHBoxLayout(0, 0, 5); + main_->addWidget(masklabel, 0, 0); + main_->addWidget(portlabel, 1, 0); + main_->addWidget(toutlabel, 2, 0); + main_->addLayout(lay1, 0, 1); + main_->addWidget(port_, 1, 1); + main_->addWidget(tout_, 2, 1); + lay1->addWidget(mask_,1); + lay1->addWidget(mm,0); + + resize(250,130); + setCaption(i18n("Scan Configuration")); +} + +NetworkScannerConfig::~NetworkScannerConfig() +{ +} + +void NetworkScannerConfig::slotOk() +{ + TQString msg; + TQRegExp re("(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})"); + if (!re.exactMatch(mask_->text())) + msg = i18n("Wrong subnetwork specification."); + else + { + for (int i=1; i<=3; i++) + if (re.cap(i).toInt() >= 255) + { + msg = i18n("Wrong subnetwork specification."); + break; + } + } + + bool ok(false); + int v = tout_->text().toInt(&ok); + if (!ok || v <= 0) + msg = i18n("Wrong timeout specification."); + v = port_->currentText().toInt(&ok); + if (!ok || v <= 0) + msg = i18n("Wrong port specification."); + if (!msg.isEmpty()) + { + KMessageBox::error(this,msg); + return; + } + + scanner_->setTimeout( tout_->text().toInt() ); + scanner_->setSubnet( mask_->text() ); + scanner_->setPort( port_->currentText().toInt() ); + + KDialogBase::slotOk(); +} + +#include "networkscanner.moc" |