summaryrefslogtreecommitdiffstats
path: root/kdeprint/management/networkscanner.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kdeprint/management/networkscanner.cpp')
-rw-r--r--kdeprint/management/networkscanner.cpp421
1 files changed, 421 insertions, 0 deletions
diff --git a/kdeprint/management/networkscanner.cpp b/kdeprint/management/networkscanner.cpp
new file mode 100644
index 000000000..ae99c4fa4
--- /dev/null
+++ b/kdeprint/management/networkscanner.cpp
@@ -0,0 +1,421 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (c) 2001-2002 Michael Goffioul <kdeprint@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 <qprogressbar.h>
+#include <kpushbutton.h>
+#include <qlayout.h>
+#include <qtimer.h>
+#include <qlabel.h>
+#include <qcombobox.h>
+#include <qlineedit.h>
+#include <qregexp.h>
+#include <qsocket.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;
+ QString prefixaddress;
+ int currentaddress;
+ int timeout;
+ bool scanning;
+ QPtrList<NetworkScanner::SocketInfo> printers;
+
+ QProgressBar *bar;
+ KPushButton *scan, *settings;
+ QLabel *subnetlab;
+ QTimer *timer;
+#ifdef USE_QSOCKET
+ QSocket *socket;
+#else
+ KExtendedSocket *socket;
+#endif
+
+ NetworkScannerPrivate( int portvalue ) : port( portvalue )
+ {
+ prefixaddress = localPrefix();
+ currentaddress = 1;
+ timeout = 50;
+ scanning = false;
+ printers.setAutoDelete( true );
+ }
+ QString localPrefix();
+ QString scanString();
+};
+
+QString NetworkScanner::NetworkScannerPrivate::localPrefix()
+{
+ char buf[256];
+ buf[0] = '\0';
+ if (!gethostname(buf, sizeof(buf)))
+ buf[sizeof(buf)-1] = '\0';
+ QPtrList<KAddressInfo> infos = KExtendedSocket::lookup(buf, QString::null);
+ infos.setAutoDelete(true);
+ if (infos.count() > 0)
+ {
+ QString IPstr = infos.first()->address()->nodeName();
+ int p = IPstr.findRev('.');
+ IPstr.truncate(p);
+ return IPstr;
+ }
+ return QString::null;
+}
+
+QString NetworkScanner::NetworkScannerPrivate::scanString()
+{
+ QString s = prefixaddress + ".*";
+ if ( port != -1 )
+ s.append( ":" ).append( QString::number( port ) );
+ return s;
+}
+
+NetworkScanner::NetworkScanner( int port, QWidget *parent, const char *name )
+ : QWidget( parent, name )
+{
+ d = new NetworkScannerPrivate( port );
+ d->bar = new QProgressBar( 256, this );
+ d->settings = new KPushButton( KGuiItem( i18n( "&Settings" ), "configure" ), this );
+ d->scan = new KPushButton( KGuiItem( i18n( "Sc&an" ), "viewmag" ), this );
+ d->timer = new QTimer( this );
+#ifdef USE_QSOCKET
+ d->socket = new QSocket( this );
+#else
+ d->socket = new KExtendedSocket();
+#endif
+ QLabel *label = new QLabel( i18n( "Network scan:" ), this );
+ d->subnetlab = new QLabel( i18n( "Subnet: %1" ).arg( d->scanString() ), this );
+
+ QGridLayout *l0 = new QGridLayout( 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, SIGNAL( timeout() ), SLOT( slotTimeout() ) );
+ connect( d->settings, SIGNAL( clicked() ), SLOT( slotSettingsClicked() ) );
+ connect( d->scan, SIGNAL( clicked() ), SLOT( slotScanClicked() ) );
+#ifdef USE_QSOCKET
+ connect( d->socket, SIGNAL( connected() ), SLOT( slotConnectionSuccess() ) );
+ connect( d->socket, SIGNAL( error( int ) ), SLOT( slotConnectionFailed( int ) ) );
+#else
+ connect( d->socket, SIGNAL( connectionSuccess() ), SLOT( slotConnectionSuccess() ) );
+ connect( d->socket, SIGNAL( connectionFailed( int ) ), 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() ),
+ QString::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 + "." + QString::number( d->currentaddress ), d->port );
+ kdDebug() << "Address: " << d->socket->peerName() << ", Port: " << d->socket->peerPort() << endl;
+#else
+ d->socket->setAddress( d->prefixaddress + "." + QString::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 );
+ QTimer::singleShot( 0, this, 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() : QString( "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;
+ QString 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 QPtrList<NetworkScanner::SocketInfo>* NetworkScanner::printerList()
+{
+ return &( d->printers );
+}
+
+int NetworkScanner::timeout() const
+{
+ return d->timeout;
+}
+
+void NetworkScanner::setTimeout( int to )
+{
+ d->timeout = to;
+}
+
+QString NetworkScanner::subnet() const
+{
+ return d->prefixaddress;
+}
+
+void NetworkScanner::setSubnet( const QString& 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 QString& host, int port )
+{
+ // try first to find it in the SocketInfo list
+ QPtrListIterator<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, QString::null, Ok|Cancel, Ok, true)
+{
+ scanner_ = scanner;
+ QWidget *dummy = new QWidget(this);
+ setMainWidget(dummy);
+ KIntValidator *val = new KIntValidator( this );
+ QLabel *masklabel = new QLabel(i18n("&Subnetwork:"),dummy);
+ QLabel *portlabel = new QLabel(i18n("&Port:"),dummy);
+ QLabel *toutlabel = new QLabel(i18n("&Timeout (ms):"),dummy);
+ QLineEdit *mm = new QLineEdit(dummy);
+ mm->setText(QString::fromLatin1(".[0-255]"));
+ mm->setReadOnly(true);
+ mm->setFixedWidth(fontMetrics().width(mm->text())+10);
+
+ mask_ = new QLineEdit(dummy);
+ mask_->setAlignment(Qt::AlignRight);
+ port_ = new QComboBox(true,dummy);
+ if ( port_->lineEdit() )
+ port_->lineEdit()->setValidator( val );
+ tout_ = new QLineEdit(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(QString::number(scanner_->port()));
+ tout_->setText(QString::number(scanner_->timeout()));
+
+ QGridLayout *main_ = new QGridLayout(dummy, 3, 2, 0, 10);
+ QHBoxLayout *lay1 = new QHBoxLayout(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()
+{
+ QString msg;
+ QRegExp 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"