summaryrefslogtreecommitdiffstats
path: root/lanbrowsing
diff options
context:
space:
mode:
Diffstat (limited to 'lanbrowsing')
-rw-r--r--lanbrowsing/Makefile.am1
-rw-r--r--lanbrowsing/kcmlisa/Makefile.am18
-rw-r--r--lanbrowsing/kcmlisa/configure.in.in4
-rw-r--r--lanbrowsing/kcmlisa/findnic.cpp298
-rw-r--r--lanbrowsing/kcmlisa/findnic.h69
-rw-r--r--lanbrowsing/kcmlisa/kcmkiolan.cpp103
-rw-r--r--lanbrowsing/kcmlisa/kcmkiolan.desktop140
-rw-r--r--lanbrowsing/kcmlisa/kcmkiolan.h53
-rw-r--r--lanbrowsing/kcmlisa/kcmlisa.cpp394
-rw-r--r--lanbrowsing/kcmlisa/kcmlisa.desktop122
-rw-r--r--lanbrowsing/kcmlisa/kcmlisa.h79
-rw-r--r--lanbrowsing/kcmlisa/kcmreslisa.cpp250
-rw-r--r--lanbrowsing/kcmlisa/kcmreslisa.desktop123
-rw-r--r--lanbrowsing/kcmlisa/kcmreslisa.h67
-rw-r--r--lanbrowsing/kcmlisa/main.cpp49
-rw-r--r--lanbrowsing/kcmlisa/portsettingsbar.cpp51
-rw-r--r--lanbrowsing/kcmlisa/portsettingsbar.h45
-rw-r--r--lanbrowsing/kcmlisa/setupwizard.cpp569
-rw-r--r--lanbrowsing/kcmlisa/setupwizard.h103
-rw-r--r--lanbrowsing/kio_lan/AUTHORS2
-rw-r--r--lanbrowsing/kio_lan/Makefile.am31
-rw-r--r--lanbrowsing/kio_lan/README16
-rw-r--r--lanbrowsing/kio_lan/TODO3
-rw-r--r--lanbrowsing/kio_lan/kio_lan.cpp794
-rw-r--r--lanbrowsing/kio_lan/kio_lan.h87
-rw-r--r--lanbrowsing/kio_lan/lan.desktop81
-rw-r--r--lanbrowsing/kio_lan/lan.protocol15
-rw-r--r--lanbrowsing/kio_lan/lisa.desktop66
-rw-r--r--lanbrowsing/kio_lan/rlan.protocol15
-rw-r--r--lanbrowsing/lisa/AUTHORS2
-rw-r--r--lanbrowsing/lisa/COPYING347
-rw-r--r--lanbrowsing/lisa/ChangeLog8
-rw-r--r--lanbrowsing/lisa/INSTALL176
-rw-r--r--lanbrowsing/lisa/Makefile.am41
-rw-r--r--lanbrowsing/lisa/NEWS1
-rw-r--r--lanbrowsing/lisa/README419
-rw-r--r--lanbrowsing/lisa/addressvalidator.cpp228
-rw-r--r--lanbrowsing/lisa/addressvalidator.h55
-rw-r--r--lanbrowsing/lisa/client.cpp122
-rw-r--r--lanbrowsing/lisa/client.h45
-rw-r--r--lanbrowsing/lisa/configfile.cpp136
-rw-r--r--lanbrowsing/lisa/configfile.h33
-rw-r--r--lanbrowsing/lisa/ipaddress.cpp97
-rw-r--r--lanbrowsing/lisa/ipaddress.h55
-rw-r--r--lanbrowsing/lisa/lisadefines.h19
-rw-r--r--lanbrowsing/lisa/main.cpp290
-rw-r--r--lanbrowsing/lisa/mystring.cpp52
-rw-r--r--lanbrowsing/lisa/mystring.h42
-rw-r--r--lanbrowsing/lisa/netmanager.cpp1058
-rw-r--r--lanbrowsing/lisa/netmanager.h109
-rw-r--r--lanbrowsing/lisa/netscanner.cpp663
-rw-r--r--lanbrowsing/lisa/netscanner.h102
-rw-r--r--lanbrowsing/lisa/strictmain.cpp261
-rw-r--r--lanbrowsing/lisa/stringlist.cpp110
-rw-r--r--lanbrowsing/lisa/stringlist.h40
-rw-r--r--lanbrowsing/lisa/tcpnode.h29
56 files changed, 8188 insertions, 0 deletions
diff --git a/lanbrowsing/Makefile.am b/lanbrowsing/Makefile.am
new file mode 100644
index 00000000..4fc6aa8a
--- /dev/null
+++ b/lanbrowsing/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = lisa kcmlisa kio_lan
diff --git a/lanbrowsing/kcmlisa/Makefile.am b/lanbrowsing/kcmlisa/Makefile.am
new file mode 100644
index 00000000..cd9750e9
--- /dev/null
+++ b/lanbrowsing/kcmlisa/Makefile.am
@@ -0,0 +1,18 @@
+kde_module_LTLIBRARIES = kcm_lanbrowser.la
+
+kcm_lanbrowser_la_SOURCES = main.cpp setupwizard.cpp kcmlisa.cpp kcmreslisa.cpp kcmkiolan.cpp portsettingsbar.cpp findnic.cpp
+
+kcm_lanbrowser_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module
+kcm_lanbrowser_la_LIBADD = -lkdeui
+
+INCLUDES= $(all_includes)
+
+SUBDIRS =
+
+kcm_lanbrowser_la_METASOURCES = AUTO
+
+messages:
+ $(XGETTEXT) $(kcm_lanbrowser_la_SOURCES) -o $(podir)/kcmlanbrowser.pot
+
+apps_DATA = kcmkiolan.desktop kcmlisa.desktop kcmreslisa.desktop
+appsdir = $(kde_appsdir)/.hidden
diff --git a/lanbrowsing/kcmlisa/configure.in.in b/lanbrowsing/kcmlisa/configure.in.in
new file mode 100644
index 00000000..e08832eb
--- /dev/null
+++ b/lanbrowsing/kcmlisa/configure.in.in
@@ -0,0 +1,4 @@
+AC_CHECK_FUNCS(getifaddrs getnameinfo)
+AC_CHECK_MEMBERS([struct sockaddr.sa_len],,,[
+#include <sys/types.h>
+#include <sys/socket.h>])
diff --git a/lanbrowsing/kcmlisa/findnic.cpp b/lanbrowsing/kcmlisa/findnic.cpp
new file mode 100644
index 00000000..75f40f0e
--- /dev/null
+++ b/lanbrowsing/kcmlisa/findnic.cpp
@@ -0,0 +1,298 @@
+/*
+ * findnic.cpp
+ *
+ * Copyright (c) 2001 Alexander Neundorf <neundorf@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/socket.h>
+
+#ifdef USE_SOLARIS
+/* net/if.h is incompatible with STL on Solaris 2.6 - 2.8, redefine
+ map in the header file because we don't need it. -- Simon Josefsson */
+#define map junkmap
+#endif
+# include <net/if.h>
+#ifdef USE_SOLARIS
+#undef map
+#endif
+
+#include <sys/ioctl.h>
+
+#ifndef HAVE_STRUCT_SOCKADDR_SA_LEN
+ #undef HAVE_GETNAMEINFO
+ #undef HAVE_GETIFADDRS
+#endif
+
+#if defined(HAVE_GETNAMEINFO) && defined(HAVE_GETIFADDRS)
+ #include <ifaddrs.h>
+ #include <netdb.h>
+ #include <qstring.h>
+
+ QString flags_tos (unsigned int flags);
+#endif
+
+#include "findnic.h"
+
+#include <klocale.h>
+#include <ksockaddr.h>
+
+NICList* findNICs()
+{
+ NICList* nl=new NICList;
+ nl->setAutoDelete(true);
+
+#if !defined(HAVE_GETIFADDRS) && !defined(HAVE_GETNAMEINFO)
+
+ int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+
+ char buf[8*1024];
+ struct ifconf ifc;
+ ifc.ifc_len = sizeof(buf);
+ ifc.ifc_req = (struct ifreq *) buf;
+ int result=ioctl(sockfd, SIOCGIFCONF, &ifc);
+
+ for (char* ptr = buf; ptr < buf + ifc.ifc_len; )
+ {
+ struct ifreq *ifr =(struct ifreq *) ptr;
+ int len = sizeof(struct sockaddr);
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+ if (ifr->ifr_addr.sa_len > len)
+ len = ifr->ifr_addr.sa_len; /* length > 16 */
+#endif
+ ptr += sizeof(ifr->ifr_name) + len; /* for next one in buffer */
+
+ int flags;
+ struct sockaddr_in *sinptr;
+ MyNIC *tmp=0;
+ switch (ifr->ifr_addr.sa_family)
+ {
+ case AF_INET:
+ sinptr = (struct sockaddr_in *) &ifr->ifr_addr;
+ flags=0;
+
+ struct ifreq ifcopy;
+ ifcopy=*ifr;
+ result=ioctl(sockfd,SIOCGIFFLAGS,&ifcopy);
+ flags=ifcopy.ifr_flags;
+
+ tmp=new MyNIC;
+ tmp->name=ifr->ifr_name;
+ if ((flags & IFF_UP) == IFF_UP)
+ tmp->state=i18n("Up");
+ else
+ tmp->state=i18n("Down");
+
+ if ((flags & IFF_BROADCAST) == IFF_BROADCAST)
+ tmp->type=i18n("Broadcast");
+ else if ((flags & IFF_POINTOPOINT) == IFF_POINTOPOINT)
+ tmp->type=i18n("Point to Point");
+#ifndef _AIX
+ else if ((flags & IFF_MULTICAST) == IFF_MULTICAST)
+ tmp->type=i18n("Multicast");
+#endif
+ else if ((flags & IFF_LOOPBACK) == IFF_LOOPBACK)
+ tmp->type=i18n("Loopback");
+ else
+ tmp->type=i18n("Unknown");
+
+ tmp->addr=inet_ntoa(sinptr->sin_addr);
+
+ ifcopy=*ifr;
+ result=ioctl(sockfd,SIOCGIFNETMASK,&ifcopy);
+ if (result==0)
+ {
+ sinptr = (struct sockaddr_in *) &ifcopy.ifr_addr;
+ tmp->netmask=inet_ntoa(sinptr->sin_addr);
+ }
+ else
+ tmp->netmask=i18n("Unknown");
+ nl->append(tmp);
+ break;
+
+ default:
+ break;
+ }
+ }
+#else
+ struct ifaddrs *ifap, *ifa;
+ if (getifaddrs(&ifap) != 0) {
+ return nl;
+ }
+
+ MyNIC *tmp=0;
+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+ switch (ifa->ifa_addr->sa_family) {
+ case AF_INET6:
+ case AF_INET: {
+ tmp = new MyNIC;
+ tmp->name = ifa->ifa_name;
+
+ char buf[128];
+
+ bzero(buf, 128);
+ getnameinfo(ifa->ifa_addr, ifa->ifa_addr->sa_len, buf, 127, 0, 0, NI_NUMERICHOST);
+ tmp->addr = buf;
+
+ if (ifa->ifa_netmask != NULL) {
+#ifdef Q_OS_FREEBSD
+ struct sockaddr_in *sinptr = (struct sockaddr_in *)ifa->ifa_netmask;
+ tmp->netmask=inet_ntoa(sinptr->sin_addr);
+#else
+ bzero(buf, 128);
+ getnameinfo(ifa->ifa_netmask, ifa->ifa_netmask->sa_len, buf, 127, 0, 0, NI_NUMERICHOST);
+ tmp->netmask = buf;
+#endif
+ }
+
+ if (ifa->ifa_flags & IFF_UP)
+ tmp->state=i18n("Up");
+ else
+ tmp->state=i18n("Down");
+
+ tmp->type = flags_tos(ifa->ifa_flags);
+
+ nl->append(tmp);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ freeifaddrs(ifap);
+#endif
+ return nl;
+}
+
+void suggestSettingsForAddress(const QString& addrMask, LisaConfigInfo& lci)
+{
+ QString ip=addrMask.left(addrMask.find("/"));
+ QString mask=addrMask.mid(addrMask.find("/")+1);
+
+ if (mask[mask.length()-1]==';')
+ mask=mask.left(mask.length()-1);
+ MyNIC tmpNic;
+ KInetSocketAddress::stringToAddr(AF_INET, mask.latin1(), &tmpNic.netmask);
+ KInetSocketAddress::stringToAddr(AF_INET, ip.latin1(), &tmpNic.addr);
+ suggestSettingsForNic(&tmpNic,lci);
+}
+
+void suggestSettingsForNic(MyNIC* nic, LisaConfigInfo& lci)
+{
+ lci.clear();
+ if (nic==0)
+ return;
+ QString address = nic->addr;
+ QString netmask = nic->netmask;
+
+ QString addrMask(address+"/"+netmask+";");
+ struct in_addr tmpaddr;
+ inet_aton(nic->netmask.latin1(), &tmpaddr);
+ unsigned int tmp= ntohl(tmpaddr.s_addr);
+
+ //if the host part is less than 20 bits simply take it
+ //this might be a problem on 64 bit machines
+ if (tmp>0xfffff000)
+ {
+ lci.pingAddresses=addrMask;
+ lci.broadcastNetwork=addrMask;
+ lci.allowedAddresses=addrMask;
+ lci.secondWait=0;
+ lci.secondScan=false;
+ lci.firstWait=30;
+ lci.maxPingsAtOnce=256;
+ lci.updatePeriod=300;
+ lci.useNmblookup=false;
+ lci.unnamedHosts=false;
+ }
+ else
+ {
+ lci.pingAddresses="";
+ lci.broadcastNetwork=addrMask;
+ lci.allowedAddresses=addrMask;
+ lci.secondWait=0;
+ lci.secondScan=false;
+ lci.firstWait=30;
+ lci.maxPingsAtOnce=256;
+ lci.updatePeriod=300;
+ lci.useNmblookup=true;
+ lci.unnamedHosts=false;
+ }
+}
+
+LisaConfigInfo::LisaConfigInfo()
+{
+ clear();
+}
+
+void LisaConfigInfo::clear()
+{
+ pingAddresses="";
+ broadcastNetwork="";
+ allowedAddresses="";
+ secondWait=0;
+ firstWait=0;
+ secondScan=false;
+ maxPingsAtOnce=256;
+ updatePeriod=0;
+ useNmblookup=false;
+ unnamedHosts=false;
+}
+
+#if defined(HAVE_GETNAMEINFO) && defined(HAVE_GETIFADDRS)
+QString flags_tos (unsigned int flags)
+{
+ QString tmp;
+ if (flags & IFF_POINTOPOINT) {
+ tmp += i18n("Point to Point");
+ }
+
+ if (flags & IFF_BROADCAST) {
+ if (tmp.length()) {
+ tmp += QString::fromLatin1(", ");
+ }
+ tmp += i18n("Broadcast");
+ }
+
+ if (flags & IFF_MULTICAST) {
+ if (tmp.length()) {
+ tmp += QString::fromLatin1(", ");
+ }
+ tmp += i18n("Multicast");
+ }
+
+ if (flags & IFF_LOOPBACK) {
+ if (tmp.length()) {
+ tmp += QString::fromLatin1(", ");
+ }
+ tmp += i18n("Loopback");
+ }
+ return tmp;
+}
+#endif
diff --git a/lanbrowsing/kcmlisa/findnic.h b/lanbrowsing/kcmlisa/findnic.h
new file mode 100644
index 00000000..45273749
--- /dev/null
+++ b/lanbrowsing/kcmlisa/findnic.h
@@ -0,0 +1,69 @@
+/*
+ * findnic.h
+ *
+ * Copyright (c) 2001 Alexander Neundorf <neundorf@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef FINDNIC_H
+#define FINDNIC_H
+
+#include <qptrlist.h>
+#include <qstring.h>
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+struct MyNIC
+{
+ QString name;
+ QString addr;
+ QString netmask;
+ QString state;
+ QString type;
+};
+
+struct LisaConfigInfo
+{
+ LisaConfigInfo();
+ void clear();
+ QString pingAddresses;
+ QString broadcastNetwork;
+ QString allowedAddresses;
+ int secondWait;
+ bool secondScan;
+ int firstWait;
+ int maxPingsAtOnce;
+ int updatePeriod;
+ bool useNmblookup;
+ bool unnamedHosts;
+};
+
+
+typedef QPtrList<MyNIC> NICList;
+
+//some plain C-like helper functions
+
+///Return a list with all NIC, which are up and broadcast-able
+NICList* findNICs();
+///Enter some settings into lci which might be appropriate for nic
+void suggestSettingsForNic(MyNIC* nic, LisaConfigInfo& lci);
+
+void suggestSettingsForAddress(const QString& addrMask, LisaConfigInfo& lci);
+
+#endif
+
diff --git a/lanbrowsing/kcmlisa/kcmkiolan.cpp b/lanbrowsing/kcmlisa/kcmkiolan.cpp
new file mode 100644
index 00000000..89ae761e
--- /dev/null
+++ b/lanbrowsing/kcmlisa/kcmkiolan.cpp
@@ -0,0 +1,103 @@
+/*
+ * kcmkiolan.cpp
+ *
+ * Copyright (c) 2000 Alexander Neundorf <neundorf@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "kcmkiolan.h"
+
+#include <qcheckbox.h>
+#include <qlayout.h>
+#include <qlineedit.h>
+#include <qhbox.h>
+#include <qlabel.h>
+#include <qgroupbox.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <kdialog.h>
+
+IOSlaveSettings::IOSlaveSettings(const QString& config, QWidget *parent)
+:KCModule(parent)
+,m_config(config,false,true)
+{
+ QVBoxLayout *layout = new QVBoxLayout(this, KDialog::marginHint(), KDialog::spacingHint());
+ layout->setAutoAdd(true);
+
+ QGroupBox* group=new QGroupBox(1, Horizontal, i18n("Show Links for Following Services"), this);
+
+ m_ftpSettings=new PortSettingsBar(i18n("FTP (TCP, port 21): "), group);
+ m_httpSettings=new PortSettingsBar(i18n("HTTP (TCP, port 80): "),group);
+ m_nfsSettings=new PortSettingsBar(i18n("NFS (TCP, port 2049): "),group);
+ m_smbSettings=new PortSettingsBar(i18n("Windows shares (TCP, ports 445 and 139):"),group);
+ m_fishSettings=new PortSettingsBar(i18n("Secure Shell/Fish (TCP, port 22): "),group);
+ m_shortHostnames = new QCheckBox(i18n("Show &short hostnames (without domain suffix)"),this);
+
+ QHBox *hbox=new QHBox(this);
+ QLabel *label=new QLabel(i18n("Default LISa server host: "), hbox);
+ m_defaultLisaHostLe=new QLineEdit(hbox);
+ label->setBuddy(m_defaultLisaHostLe);
+
+ QWidget *w=new QWidget(this);
+ layout->setStretchFactor(m_ftpSettings,0);
+ layout->setStretchFactor(m_httpSettings,0);
+ layout->setStretchFactor(m_nfsSettings,0);
+ layout->setStretchFactor(m_smbSettings,0);
+ layout->setStretchFactor(m_shortHostnames,0);
+ layout->setStretchFactor(hbox,0);
+ layout->setStretchFactor(w,1);
+
+ connect(m_ftpSettings,SIGNAL(changed()),this,SIGNAL(changed()));
+ connect(m_httpSettings,SIGNAL(changed()),this,SIGNAL(changed()));
+ connect(m_nfsSettings,SIGNAL(changed()),this,SIGNAL(changed()));
+ connect(m_smbSettings,SIGNAL(changed()),this,SIGNAL(changed()));
+ connect(m_fishSettings,SIGNAL(changed()),this,SIGNAL(changed()));
+ connect(m_shortHostnames,SIGNAL(clicked()),this,SIGNAL(changed()));
+ connect(m_defaultLisaHostLe, SIGNAL(textChanged(const QString&)),this,SIGNAL(changed()));
+}
+
+void IOSlaveSettings::load()
+{
+ kdDebug()<<"IOSlaveSettings::load()"<<endl;
+ m_ftpSettings->setChecked(m_config.readNumEntry("Support_FTP", PORTSETTINGS_CHECK));
+ m_httpSettings->setChecked(m_config.readNumEntry("Support_HTTP", PORTSETTINGS_CHECK));
+ m_nfsSettings->setChecked(m_config.readNumEntry("Support_NFS", PORTSETTINGS_CHECK));
+ m_smbSettings->setChecked(m_config.readNumEntry("Support_SMB", PORTSETTINGS_CHECK));
+ m_fishSettings->setChecked(m_config.readNumEntry("Support_FISH", PORTSETTINGS_CHECK));
+ m_shortHostnames->setChecked(m_config.readBoolEntry("ShowShortHostnames",false));
+// m_rlanSidebar->setChecked(m_config.readEntry("sidebarURL", "lan:/") == "rlan:/" ? true : false );
+ m_defaultLisaHostLe->setText(m_config.readEntry("DefaultLisaHost", "localhost"));
+}
+
+void IOSlaveSettings::save()
+{
+ kdDebug()<<"IOSlaveSettings::save()"<<endl;
+ m_config.writeEntry("AlreadyConfigured",true);
+ m_config.writeEntry("Support_FTP", m_ftpSettings->selected());
+ m_config.writeEntry("Support_HTTP", m_httpSettings->selected());
+ m_config.writeEntry("Support_NFS", m_nfsSettings->selected());
+ m_config.writeEntry("Support_SMB", m_smbSettings->selected());
+ m_config.writeEntry("Support_FISH", m_fishSettings->selected());
+ m_config.writeEntry("ShowShortHostnames",m_shortHostnames->isChecked());
+// m_config.writeEntry("sidebarURL", m_rlanSidebar->isChecked() ? "rlan:/" : "lan:/");
+ m_config.writeEntry("DefaultLisaHost", m_defaultLisaHostLe->text());
+
+ m_config.sync();
+}
+
+#include "kcmkiolan.moc"
+
diff --git a/lanbrowsing/kcmlisa/kcmkiolan.desktop b/lanbrowsing/kcmlisa/kcmkiolan.desktop
new file mode 100644
index 00000000..c15e9724
--- /dev/null
+++ b/lanbrowsing/kcmlisa/kcmkiolan.desktop
@@ -0,0 +1,140 @@
+[Desktop Entry]
+Type=Application
+Icon=samba
+Exec=kcmshell kcmkiolan
+
+X-KDE-ModuleType=Library
+X-KDE-Library=lanbrowser
+X-KDE-FactoryName=kiolan
+
+Name=LAN KIO Slave
+Name[ar]=الشبكة المحلية KIO Slave
+Name[be]=Модуль kioslave для мясцовай сетцы
+Name[bn]=ল্যান কে-আই-ও স্লেভ
+Name[br]=Sklav LAN evit KIO
+Name[bs]=LAN KIO slave
+Name[cs]=LAN KIO slave
+Name[cy]=Gwas KIO LAN
+Name[da]=LAN KIO-slave
+Name[de]=Ein-/Ausgabemodul für LAN
+Name[eo]=LAN-enel-sklavo
+Name[es]=Esclavo de LAN KIO
+Name[et]=Kohtvõrgu KIO moodul
+Name[eu]=LAN KIO morroia
+Name[fi]=LAN-siirräntätyöskentelijä
+Name[fr]=Module KIO LAN
+Name[ga]=Sclábhaí KIO LAN
+Name[gl]=Escravo KIO para redes locáis
+Name[hi]=लैन केआईओ स्लेव
+Name[hu]=Hálózatböngészés
+Name[is]=LAN KIO þræll
+Name[it]=Slave LAN KIO
+Name[ja]=LAN KIO スレーブ
+Name[km]=KIO Slave បណ្ដាញ​មូលដ្ឋាន
+Name[lt]=LAN antrinė KDE programa
+Name[mn]=Протокол IO LAN
+Name[ms]=Hamba LAN KIO
+Name[nb]=KIO-slave for LAN
+Name[nds]=Nettwark-In-/Utgaavdeenst
+Name[ne]=LAN KIO स्लाभ
+Name[nl]=LAN IO Slave
+Name[nn]=LAN-iuslave
+Name[nso]=Lekgoba la LAN KIO
+Name[pa]=LAN KIO ਸਲੇਵ
+Name[pl]=Procedura we/wy dla sieci lokalnej
+Name[pt]='Kioslave' LAN
+Name[ru]=Протокол IO LAN
+Name[se]=LAN KIO-šláva
+Name[sk]=LAN KIO slave
+Name[sl]=KIO Slave za LAN
+Name[sv]=I/O-slav för lokalt nätverk
+Name[ta]=LAN KIO அடிமை
+Name[tg]=Фармонбари Шабакаи Маҳаллии KIO
+Name[uk]=Підлеглий KIO ЛОМ
+Name[zh_CN]=LAN KIO 从属进程
+
+Comment=lan: and rlan: setup
+Comment[ar]=lan: و rlan: تنصيب
+Comment[be]=Настаўленне lan: і rlan:
+Comment[bg]=Настройване на протоколите lan: и rlan:
+Comment[bn]=ল্যান: এবং আর-ল্যান: ব্যবস্থাপনা
+Comment[br]=kefluniañ lan: ha rlan:
+Comment[bs]=Podešavanje lan: i rlan: URLova
+Comment[ca]=Per l'arranjament de lan: i rlan:
+Comment[cs]=Nastavení lan: and rlan:
+Comment[cy]=gosod lan: a rlan:
+Comment[da]=lan: og rlan: opsætning
+Comment[de]=lan: und rlan: einrichten
+Comment[el]=Ρύθμιση lan: και rlan:
+Comment[eo]=lan kaj rlan: agordo
+Comment[es]=lan: y rlan: configuración
+Comment[et]=lan: ja rlan: seadistamine
+Comment[eu]=lan: eta rlan: konfigurazioa
+Comment[fa]=شبکۀ محلی: و شبکۀ محلی راه دور: برپایی
+Comment[fi]=lan: ja rlan: asetukset
+Comment[fr]=configuration pour lan: et rlan:
+Comment[ga]=Cumraíocht lan: agus rlan:
+Comment[gl]=Configuración de lan: e rlan:
+Comment[he]=שינוי הגדרות :lan ו-:rlan
+Comment[hi]=लैन: तथा आर-लैन: सेटअप
+Comment[hr]=Podešavanje lan-a i rlan-a
+Comment[hu]=A lan: és az rlan: protokoll beállítása
+Comment[is]=lan: og rlan: uppsetning
+Comment[it]=Configurazione lan: e rlan:
+Comment[ja]=lan と rlan のセットアップ
+Comment[ka]=lan: და rlan: გამართვა
+Comment[kk]=lan: мен rlan: параметрлерді орнату
+Comment[km]=រៀបចំ lan: និង rlan:
+Comment[lt]=lan: ir rlan: nustatymas
+Comment[mk]=Поставување на lan: и rlan:
+Comment[mn]=lan: ба rlan: тохируулга
+Comment[ms]=lan: dan rlan: pemasangan
+Comment[nb]=Oppsett for lan: og rlan:
+Comment[nds]=lan: un rlan: instellen
+Comment[ne]=lan: र rlan: सेटअप
+Comment[nl]=Instellen van lan: en rlan:
+Comment[nn]=Oppsett av lan: og rlan:
+Comment[nso]=peakanyo ya lan: le rlan:
+Comment[pl]=ustawienia lan: i rlan:
+Comment[pt]=Configuração do lan: e do rlan:
+Comment[pt_BR]=lan: e rlan: configuração
+Comment[ru]=параметры lan: и rlan:
+Comment[se]=Heivet lan: ja rlan:
+Comment[sk]=lan: a rlan: nastavenie
+Comment[sl]=Nastavitve lan: in rlan:
+Comment[sr]=Подешавање lan:-а и rlan:-а
+Comment[sr@Latn]=Podešavanje lan:-a i rlan:-a
+Comment[sv]=Inställning av lan: och rlan:
+Comment[ta]=lan: மற்றும் rlan: அமைப்பு
+Comment[tg]=барпосозии шабакаи маҳаллӣ: ва rlan:
+Comment[tr]=lan: ve rlan: ayarları
+Comment[uk]=Налаштування lan: і rlan:
+Comment[ven]=lan: na rlan: mavhekanyele
+Comment[xh]=lan: kunye ne rlan: ucwangciso
+Comment[zh_CN]=lan: 和 rlan: 设置
+Comment[zh_HK]=lan: 與 rlan: 設定
+Comment[zh_TW]=lan: 與 rlan: 設定
+Comment[zu]=Ilayini yokuyalela ye applet
+
+Keywords=lan
+Keywords[bg]=настройки, локална, мрежа, lan
+Keywords[bn]=ল্যান
+Keywords[de]=LAN
+Keywords[eo]=reto
+Keywords[fa]=شبکۀ داخلی
+Keywords[fr]=lan,réseau local,réseau
+Keywords[gl]=lan,redes locáis
+Keywords[he]=lan,רשת מקומית
+Keywords[hi]=लैन
+Keywords[lt]=lan,vietinis tinklas
+Keywords[nds]=lan,nettwark
+Keywords[ne]=ल्यान
+Keywords[nl]=lan,lokaal netwerk,netwerk
+Keywords[pl]=lan,LAN
+Keywords[ru]=lan, локальная сеть
+Keywords[sk]=lan,sieť
+Keywords[tg]=шабакаи маҳаллӣ
+Keywords[uk]=lan, локальна мережа
+Keywords[uz]=lokal tarmoq
+Keywords[uz@cyrillic]=локал тармоқ
+Keywords[zh_CN]=lan,局域网
diff --git a/lanbrowsing/kcmlisa/kcmkiolan.h b/lanbrowsing/kcmlisa/kcmkiolan.h
new file mode 100644
index 00000000..8711deab
--- /dev/null
+++ b/lanbrowsing/kcmlisa/kcmkiolan.h
@@ -0,0 +1,53 @@
+/*
+ * kcmkiolan.h
+ *
+ * Copyright (c) 2000 Alexander Neundorf <neundorf@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef KCMKIOLAN_H
+#define KCMKIOLAN_H
+
+#include "portsettingsbar.h"
+#include <kcmodule.h>
+#include <kconfig.h>
+
+class QCheckBox;
+class QLineEdit;
+
+class IOSlaveSettings:public KCModule
+{
+ Q_OBJECT
+ public:
+ IOSlaveSettings(const QString& config, QWidget *parent=0);
+ virtual ~IOSlaveSettings() {};
+ void load();
+ void save();
+ signals:
+ void changed();
+ protected:
+ KConfig m_config;
+ QCheckBox *m_shortHostnames;
+ QCheckBox *m_rlanSidebar;
+ PortSettingsBar *m_ftpSettings;
+ PortSettingsBar *m_httpSettings;
+ PortSettingsBar *m_nfsSettings;
+ PortSettingsBar *m_smbSettings;
+ PortSettingsBar *m_fishSettings;
+ QLineEdit *m_defaultLisaHostLe;
+};
+
+#endif
diff --git a/lanbrowsing/kcmlisa/kcmlisa.cpp b/lanbrowsing/kcmlisa/kcmlisa.cpp
new file mode 100644
index 00000000..654c5848
--- /dev/null
+++ b/lanbrowsing/kcmlisa/kcmlisa.cpp
@@ -0,0 +1,394 @@
+/*
+ * kcmlisa.cpp
+ *
+ * Copyright (c) 2000,2001 Alexander Neundorf <neundorf@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "kcmlisa.h"
+
+#include "findnic.h"
+#include "setupwizard.h"
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <pwd.h>
+#include <time.h>
+
+#include <qtooltip.h>
+#include <qfile.h>
+#include <qspinbox.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+#include <qgrid.h>
+#include <qvbuttongroup.h>
+
+#include <kapplication.h>
+#include <kprocess.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <keditlistbox.h>
+#include <krestrictedline.h>
+#include <kdialogbase.h>
+#include <ktempfile.h>
+
+#include <kdebug.h>
+
+LisaSettings::LisaSettings(const QString& config, QWidget *parent)
+: KCModule(parent, "kcmlanbrowser")
+,m_config(config,false,true)
+,m_wizard(0)
+,m_configFilename(config)
+,m_changed(false)
+{
+ QVBoxLayout *layout = new QVBoxLayout(this, KDialog::marginHint(), KDialog::spacingHint());
+ layout->setAutoAdd(true);
+
+ QWidget *dummy(0);
+
+ QVButtonGroup *gb=new QVButtonGroup(i18n("Tell LISa Daemon How to Search for Hosts"),this);
+ gb->setInsideSpacing(10);
+
+ m_useNmblookup=new QCheckBox(i18n("Send &NetBIOS broadcasts using nmblookup"), gb);
+ QToolTip::add(m_useNmblookup,i18n("Only hosts running SMB servers will answer"));
+
+ m_sendPings=new QCheckBox(i18n("Send &pings (ICMP echo packets)"), gb);
+ QToolTip::add(m_sendPings,i18n("All hosts running TCP/IP will answer"));
+
+ QHBox *hbox=new QHBox(gb);
+ hbox->setSpacing(10);
+
+ dummy=new QWidget(hbox);
+ dummy->setMinimumWidth(10);
+ QLabel *label=new QLabel(i18n("To these &IP addresses:"),hbox);
+ QString comment = i18n("Enter all ranges to scan, using the format '192.168.0.1/255.255.255.0;10.0.0.1;255.0.0.0'");
+ QToolTip::add(label,comment);
+ m_pingAddresses=new KRestrictedLine(hbox,"a","0123456789.-/;");
+ QToolTip::add(m_pingAddresses, comment);
+ label->setBuddy(m_pingAddresses);
+
+ QGrid *addressesGrid = new QGrid(2, Qt::Horizontal, this);
+ addressesGrid->setSpacing(10);
+ layout->setStretchFactor(addressesGrid,0);
+
+ label=new QLabel(i18n("&Broadcast network address:"),addressesGrid);
+ comment=i18n("Your network address/subnet mask (e.g. 192.168.0.0/255.255.255.0;)");
+ QToolTip::add(label, comment);
+
+ m_broadcastNetwork=new KRestrictedLine(addressesGrid,"a","0123456789./;");
+ QToolTip::add(m_broadcastNetwork,comment);
+ label->setBuddy(m_broadcastNetwork);
+
+ label=new QLabel(i18n("&Trusted IP addresses:"),addressesGrid);
+ comment = i18n("Usually your network address/subnet mask (e.g. 192.168.0.0/255.255.255.0;)");
+ QToolTip::add(label, comment);
+
+ m_allowedAddresses=new KRestrictedLine(addressesGrid,"a","0123456789./;");
+ QToolTip::add(m_allowedAddresses, comment);
+ label->setBuddy(m_allowedAddresses);
+
+ dummy=new QWidget(this);
+ layout->setStretchFactor(dummy,10);
+
+ hbox = new QHBox(this);
+ hbox->setSpacing(10);
+// m_autoSetup=new QPushButton(i18n("&Guided LISa Setup..."),hbox);
+ m_autoSetup=new QPushButton(i18n("Setup Wizard..."),hbox);
+ m_autoSetup->setFixedWidth( m_autoSetup->sizeHint().width() );
+
+ m_suggestSettings=new QPushButton(i18n("&Suggest Settings"),hbox);
+
+ new QWidget(hbox);
+
+ m_advancedSettingsButton=new QPushButton(i18n("Ad&vanced Settings..."),hbox);
+
+ m_lisaAdvancedDlg=new KDialogBase(0,0,true,i18n("Advanced Settings for LISa"),KDialogBase::Close, KDialogBase::Close);
+ connect(m_advancedSettingsButton,SIGNAL(clicked()),m_lisaAdvancedDlg,SLOT(show()));
+
+ QVBox *vbox=m_lisaAdvancedDlg->makeVBoxMainWidget();
+
+ m_pingNames=new KEditListBox(i18n("&Additionally Check These Hosts"),vbox,"a",false, KEditListBox::Add|KEditListBox::Remove);
+ m_pingNames->setMinimumHeight(180);
+ QToolTip::add(m_pingNames,i18n("The hosts listed here will be pinged"));
+
+ dummy=new QWidget(vbox);
+ dummy->setMinimumHeight(10);
+ m_deliverUnnamedHosts=new QCheckBox(i18n("Show &hosts without DNS names"),vbox);
+
+ QGrid *advGrid = new QGrid(2, Qt::Horizontal, vbox);
+ advGrid->setSpacing(10);
+
+ label=new QLabel(i18n("Host list update interval:"),advGrid);
+ QToolTip::add(label,i18n("Search hosts after this number of seconds"));
+ m_updatePeriod=new QSpinBox(30,1800,10,advGrid);
+ m_updatePeriod->setSuffix(i18n(" sec"));
+ QToolTip::add(m_updatePeriod,i18n("Search hosts after this number of seconds"));
+
+ m_secondScan=new QCheckBox(i18n("Always check twice for hosts when searching"),advGrid);
+ new QWidget(advGrid);
+
+ label=new QLabel(i18n("Wait for replies from hosts after first scan:"),advGrid);
+ QToolTip::add(label,i18n("How long to wait for replies to the ICMP echo requests from hosts"));
+ m_firstWait=new QSpinBox(10,1000,50,advGrid);
+ m_firstWait->setSuffix(i18n(" ms"));
+ QToolTip::add(m_firstWait,i18n("How long to wait for replies to the ICMP echo requests from hosts"));
+
+ label=new QLabel(i18n("Wait for replies from hosts after second scan:"),advGrid);
+ QToolTip::add(label,i18n("How long to wait for replies to the ICMP echo requests from hosts"));
+ m_secondWait=new QSpinBox(0,1000,50,advGrid);
+ m_secondWait->setSuffix(i18n(" ms"));
+ QToolTip::add(m_secondWait,i18n("How long to wait for replies to the ICMP echo requests from hosts"));
+
+ label=new QLabel(i18n("Max. number of ping packets to send at once:"),advGrid);
+ m_maxPingsAtOnce=new QSpinBox(8,1024,5,advGrid);
+
+ dummy=new QWidget(advGrid);
+ dummy->setMinimumHeight(10);
+
+ connect(m_secondScan,SIGNAL(toggled(bool)),m_secondWait,SLOT(setEnabled(bool)));
+ connect(m_sendPings,SIGNAL(toggled(bool)),m_pingAddresses,SLOT(setEnabled(bool)));
+
+ connect(m_pingAddresses,SIGNAL(textChanged(const QString&)),this,SIGNAL(changed()));
+ connect(m_allowedAddresses,SIGNAL(textChanged(const QString&)),this,SIGNAL(changed()));
+ connect(m_broadcastNetwork,SIGNAL(textChanged(const QString&)),this,SIGNAL(changed()));
+
+ connect(m_pingAddresses,SIGNAL(returnPressed()),this,SIGNAL(changed()));
+ connect(m_allowedAddresses,SIGNAL(returnPressed()),this,SIGNAL(changed()));
+ connect(m_broadcastNetwork,SIGNAL(returnPressed()),this,SIGNAL(changed()));
+
+ connect(m_sendPings,SIGNAL(toggled(bool)),this,SIGNAL(changed()));
+ connect(m_firstWait,SIGNAL(valueChanged(int)),this,SIGNAL(changed()));
+ connect(m_secondWait,SIGNAL(valueChanged(int)),this,SIGNAL(changed()));
+ connect(m_maxPingsAtOnce,SIGNAL(valueChanged(int)),this,SIGNAL(changed()));
+ connect(m_secondScan,SIGNAL(toggled(bool)),this,SIGNAL(changed()));
+ connect(m_deliverUnnamedHosts,SIGNAL(toggled(bool)),this,SIGNAL(changed()));
+ connect(m_updatePeriod,SIGNAL(valueChanged(int)),this,SIGNAL(changed()));
+ connect(m_pingNames,SIGNAL(changed()),this,SIGNAL(changed()));
+ connect(m_useNmblookup,SIGNAL(toggled(bool)),this,SIGNAL(changed()));
+ connect(m_autoSetup,SIGNAL(clicked()),this,SLOT(autoSetup()));
+ connect(m_suggestSettings,SIGNAL(clicked()),this,SLOT(suggestSettings()));
+ connect(this, SIGNAL(changed()), SLOT(slotChanged()));
+}
+
+void LisaSettings::load()
+{
+ int secondWait=m_config.readNumEntry("SecondWait",-1);
+ if (secondWait<0)
+ {
+ m_secondWait->setValue(300);
+ m_secondScan->setChecked(FALSE);
+ m_secondWait->setEnabled(FALSE);
+ }
+ else
+ {
+ m_secondWait->setValue(secondWait*10);
+ m_secondScan->setChecked(TRUE);
+ m_secondWait->setEnabled(TRUE);
+ }
+ m_deliverUnnamedHosts->setChecked(m_config.readNumEntry("DeliverUnnamedHosts",0));
+
+ m_firstWait->setValue(m_config.readNumEntry("FirstWait",30)*10);
+ m_maxPingsAtOnce->setValue(m_config.readNumEntry("MaxPingsAtOnce",256));
+ m_updatePeriod->setValue(m_config.readNumEntry("UpdatePeriod",300));
+ m_pingAddresses->setText(m_config.readEntry("PingAddresses","192.168.0.0/255.255.255.0;192.168.100.0-192.168.100.254"));
+ m_sendPings->setChecked(!m_pingAddresses->text().isEmpty());
+ m_allowedAddresses->setText(m_config.readEntry("AllowedAddresses","192.168.0.0/255.255.255.0"));
+ m_broadcastNetwork->setText(m_config.readEntry("BroadcastNetwork","192.168.0.0/255.255.255.0"));
+ m_pingNames->clear();
+ m_pingNames->insertStringList(m_config.readListEntry("PingNames",';'));
+ int i=m_config.readNumEntry("SearchUsingNmblookup",1);
+ m_useNmblookup->setChecked(i!=0);
+ m_changed = false;
+}
+
+void LisaSettings::save()
+{
+ if (!m_changed) return;
+
+ if ( getuid()==0)
+ {
+ if (m_secondScan->isChecked())
+ m_config.writeEntry("SecondWait",(m_secondWait->value()+5)/10);
+ else
+ m_config.writeEntry("SecondWait",-1);
+
+ if (m_useNmblookup->isChecked())
+ m_config.writeEntry("SearchUsingNmblookup",1);
+ else
+ m_config.writeEntry("SearchUsingNmblookup",0);
+
+ if (m_deliverUnnamedHosts->isChecked())
+ m_config.writeEntry("DeliverUnnamedHosts",1);
+ else
+ m_config.writeEntry("DeliverUnnamedHosts",0);
+
+ m_config.writeEntry("FirstWait",(m_firstWait->value()+5)/10);
+ m_config.writeEntry("MaxPingsAtOnce",m_maxPingsAtOnce->value());
+ m_config.writeEntry("UpdatePeriod",m_updatePeriod->value());
+ m_config.writeEntry("PingAddresses",m_sendPings->isChecked()?m_pingAddresses->text():"");
+ m_config.writeEntry("AllowedAddresses",m_allowedAddresses->text());
+ m_config.writeEntry("BroadcastNetwork",m_broadcastNetwork->text());
+ QStringList writeStuff;
+ for (int i=0; i<m_pingNames->count(); i++)
+ writeStuff.append(m_pingNames->text(i));
+ m_config.writeEntry("PingNames",writeStuff,';');
+
+ m_config.sync();
+ chmod(QFile::encodeName(m_configFilename),S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
+ }
+ else
+ {
+ //ok, now it gets harder
+ //we are not root but we want to write into /etc ....
+ //any idea how to do it better ?
+ KTempFile tmp;
+
+ if (tmp.status() == 0 && tmp.textStream())
+ {
+ m_tmpFilename = tmp.name();
+ QTextStream &confStream = *(tmp.textStream());
+ if (m_secondScan->isChecked())
+ confStream<<"SecondWait = "<<(m_secondWait->value()+5)/10<<"\n";
+ else
+ confStream<<"SecondWait = -1\n";
+
+ if (m_useNmblookup->isChecked())
+ confStream<<"SearchUsingNmblookup = 1\n";
+ else
+ confStream<<"SearchUsingNmblookup = 0\n";
+
+ if (m_deliverUnnamedHosts->isChecked())
+ confStream<<"DeliverUnnamedHosts = 1\n";
+ else
+ confStream<<"DeliverUnnamedHosts = 0\n";
+
+ confStream<<"FirstWait = "<< (m_firstWait->value()+5)/10 <<"\n";
+ confStream<<"MaxPingsAtOnce = "<<m_maxPingsAtOnce->value()<<"\n";
+ confStream<<"UpdatePeriod = "<<m_updatePeriod->value()<<"\n";
+ confStream<<"PingAddresses = "<<m_pingAddresses->text().latin1()<<"\n";
+ confStream<<"AllowedAddresses = "<<m_allowedAddresses->text().latin1()<<"\n";
+ confStream<<"BroadcastNetwork = "<<m_broadcastNetwork->text().latin1()<<"\n";
+ QString writeStuff;
+ for (int i=0; i<m_pingNames->count(); i++)
+ writeStuff=writeStuff+m_pingNames->text(i).latin1()+";";
+
+ confStream<<"PingNames = "<<writeStuff.latin1()<<"\n";
+ tmp.close();
+ QString suCommand=QString("cp '%1' '%2'; chmod 644 '%3'; rm -f '%4'").arg(m_tmpFilename).arg(m_configFilename).arg(m_configFilename).arg(m_tmpFilename);
+ KProcess *proc = new KProcess();
+ connect(proc, SIGNAL(processExited(KProcess *)), this, SLOT(saveDone(KProcess *)));
+ *proc<<"kdesu"<<"-c"<<suCommand;
+ KApplication::setOverrideCursor(Qt::waitCursor);
+ setEnabled(false);
+ if ( !proc->start() )
+ delete proc;
+ }
+ else
+ KMessageBox::sorry(0,i18n("Saving the results to %1 failed.").arg(m_configFilename));
+ }
+}
+
+void LisaSettings::suggestSettings()
+{
+ NICList *nics=findNICs();
+ if (nics->count()==0)
+ {
+ KMessageBox::sorry(0,i18n("No network interface cards found."));
+ delete nics;
+ return;
+ }
+ MyNIC *nic=nics->first();
+ LisaConfigInfo lci;
+ suggestSettingsForNic(nic,lci);
+ m_pingAddresses->setText(lci.pingAddresses);
+ m_sendPings->setChecked(!m_pingAddresses->text().isEmpty());
+ m_broadcastNetwork->setText(lci.broadcastNetwork);
+ m_allowedAddresses->setText(lci.allowedAddresses);
+ m_secondWait->setValue(lci.secondWait*10);
+ m_secondScan->setChecked(lci.secondScan);
+ m_secondWait->setEnabled(lci.secondScan);
+ m_firstWait->setValue(lci.firstWait*10);
+ m_maxPingsAtOnce->setValue(lci.maxPingsAtOnce);
+ m_updatePeriod->setValue(lci.updatePeriod);
+ m_useNmblookup->setChecked(lci.useNmblookup);
+ m_deliverUnnamedHosts->setChecked(lci.unnamedHosts);
+
+ if (nics->count()>1)
+ {
+ QString msg(i18n("You have more than one network interface installed.<br>"
+ "Please make sure the suggested settings are correct.<br>"
+ "<br>The following interfaces were found:<br><br>"));
+ //not that easy to handle
+ for (MyNIC* tmp=nics->first(); tmp!=0; tmp=nics->next())
+ {
+ msg+="<b>"+tmp->name+": </b>"+tmp->addr+"/"+tmp->netmask+";<br>";
+ }
+ KMessageBox::information(0,QString("<html>%1</html>").arg(msg));
+ }
+
+ emit changed();
+ delete nics;
+}
+
+void LisaSettings::autoSetup()
+{
+ LisaConfigInfo lci;
+ if (m_wizard==0)
+ m_wizard=new SetupWizard(this,&lci);
+ else
+ m_wizard->clearAll();
+ int result=m_wizard->exec();
+
+ if (result!=QDialog::Accepted)
+ return;
+
+ m_pingAddresses->setText(lci.pingAddresses);
+ m_sendPings->setChecked(!m_pingAddresses->text().isEmpty());
+ m_broadcastNetwork->setText(lci.broadcastNetwork);
+ m_allowedAddresses->setText(lci.allowedAddresses);
+ m_secondWait->setValue(lci.secondWait*10);
+ m_secondScan->setChecked(lci.secondScan);
+ m_secondWait->setEnabled(lci.secondScan);
+ m_firstWait->setValue(lci.firstWait*10);
+ m_maxPingsAtOnce->setValue(lci.maxPingsAtOnce);
+ m_updatePeriod->setValue(lci.updatePeriod);
+ m_useNmblookup->setChecked(lci.useNmblookup);
+ m_deliverUnnamedHosts->setChecked(lci.unnamedHosts);
+
+ emit changed();
+ return;
+}
+
+void LisaSettings::saveDone(KProcess *proc)
+{
+ unlink(QFile::encodeName(m_tmpFilename));
+ KApplication::restoreOverrideCursor();
+ setEnabled(true);
+ KMessageBox::information(0,i18n("The configuration has been saved to /etc/lisarc.\n"
+ "Make sure that the LISa daemon is started,\n e.g. using an init script when booting.\n"
+ "You can find examples and documentation at http://lisa-home.sourceforge.net ."));
+
+ delete(proc);
+}
+
+void LisaSettings::slotChanged()
+{
+ m_changed = true;
+}
+
+#include "kcmlisa.moc"
+
diff --git a/lanbrowsing/kcmlisa/kcmlisa.desktop b/lanbrowsing/kcmlisa/kcmlisa.desktop
new file mode 100644
index 00000000..f995a9cf
--- /dev/null
+++ b/lanbrowsing/kcmlisa/kcmlisa.desktop
@@ -0,0 +1,122 @@
+[Desktop Entry]
+Type=Application
+Icon=samba
+Exec=kcmshell kcmlisa
+
+X-KDE-ModuleType=Library
+X-KDE-Library=lanbrowser
+X-KDE-FactoryName=lisa
+
+Name=LISa
+Name[hi]=लिसा
+Name[sv]=Lisa
+Name[th]=ลิซา
+
+Comment=Setup LISa
+Comment[ar]=تنصيب LISa
+Comment[be]=Настаўленны LISы
+Comment[bg]=Настройване на LISa
+Comment[bn]=LISa ব্যবস্থাপনা
+Comment[br]=Kefluniañ LISa
+Comment[bs]=Podešavanje LISe
+Comment[ca]=Per l'arranjament de LISa
+Comment[cs]=Nastavit LISa
+Comment[cy]=Gosod LISa
+Comment[da]=Opsætning af LISa
+Comment[de]=LISa einrichten
+Comment[el]=Ρύθμιση LISa
+Comment[eo]=Agordo de LISa
+Comment[es]=Configuración LISa
+Comment[et]=LISa seadistamine
+Comment[eu]=LISa konfiguratu
+Comment[fa]=برپایی LISa
+Comment[fi]=Aseta LISa
+Comment[fr]=Configuration de LISa
+Comment[ga]=Cumraigh LISa
+Comment[gl]=Configuración de LISa
+Comment[he]=שינוי הגדרות LISa
+Comment[hi]=लिसा सेटअप
+Comment[hr]=Podešavanje LISa-e
+Comment[hu]=A LISa szolgáltatás beállítása
+Comment[is]=Stillingar LISa
+Comment[it]=Impostazioni LISa
+Comment[ja]=LISa のセットアップ
+Comment[ka]=LISa-ს გამართვა
+Comment[kk]=LISa баптауы
+Comment[km]=រៀបចំ LISa
+Comment[lt]=Nustatyti LISa
+Comment[mk]=Поставување на LISa
+Comment[mn]=LISa тохируулга
+Comment[ms]=Pasang LISa
+Comment[nb]=Tilpass LISa
+Comment[nds]=LISa instellen
+Comment[ne]=LISa सेटअप गर्नुहोस्
+Comment[nl]=LISa instellen
+Comment[nn]=LISa-oppsett
+Comment[nso]=Beakanya LISa
+Comment[pl]=Ustawienia programu LISa
+Comment[pt]=Configuração do LISa
+Comment[pt_BR]=Configuração de LISa
+Comment[ru]=Параметры LISa
+Comment[se]=Heivet LISa
+Comment[sk]=Nastavenie LISy
+Comment[sl]=Nastavi LISa
+Comment[sr]=Подесите LISa-у
+Comment[sr@Latn]=Podesite LISa-u
+Comment[sv]=Anpassa Lisa
+Comment[ta]=LISa அமைப்புகள்
+Comment[tg]=Барпосозии LISa
+Comment[th]=ตั้งค่าลิซา
+Comment[tr]=LISa'yı yapılandır
+Comment[uk]=Налаштування LISa
+Comment[uz]=LISa'ni oʻrnatish
+Comment[uz@cyrillic]=LISa'ни ўрнатиш
+Comment[ven]=Vhekanyani LISa
+Comment[wa]=Apontiaedje di LISa
+Comment[xh]=Cwangcis i LISa
+Comment[zh_CN]=设置 LISa
+Comment[zh_HK]=設定 LISa
+Comment[zh_TW]=設定 LISa
+Comment[zu]=Lungisa i-LISa
+
+Keywords=lisa,network,smb,ftp,fish,http
+Keywords[be]=сетка,lisa,network,smb,ftp,fish,http
+Keywords[bg]=мрежа, самба, настройки, локална, споделяне, lisa, network, smb, ftp, fish, http
+Keywords[br]=lisa,rouedad,smb,ftp,fish,http
+Keywords[ca]=lisa,xarxa,smb,ftp,fish,http
+Keywords[cs]=lisa,síť,smb,ftp,fish,http
+Keywords[cy]=lisa,rhwydwaith,smb,ftp,fish,http
+Keywords[da]=lisa,netværk,smb,ftp,fish,http
+Keywords[de]=lisa,Netzwerk,smb,ftp,fish,http
+Keywords[el]=lisa,δίκτυο,smb,ftp,fish,http
+Keywords[et]=lisa,võrk,smb,ftp,fish,http
+Keywords[eu]=lisa,sarea,smb,ftp,fish,http
+Keywords[fa]=lisa، شبکه، smb، قاپ، fish، قام
+Keywords[fi]=lisa,verkko,smb,ftp,fish,http
+Keywords[fr]=lisa,réseau,smb,ftp,fish,http
+Keywords[gl]=lisa,rede,smb,ftp,fish,http
+Keywords[he]=lisa,רשת,smb,ftp,fish,http
+Keywords[hi]=लिसा,नेटवर्क,एसएमबी,एफटीपी,फिश,एचटीटीपी
+Keywords[hu]=lisa,hálózat,smb,ftp,fish,http
+Keywords[it]=lisa,rete,smb,ftp,fish,http
+Keywords[ja]=lisa,ネットワーク,smb,ftp,fish,http
+Keywords[km]=lisa,បណ្ដាញ,smb,ftp,fish,http
+Keywords[lt]=lisa,network,smb,ftp,fish,http,tinklas
+Keywords[mk]=lisa,network,smb,ftp,fish,http,мрежа
+Keywords[nb]=lisa,nettverk,smb,ftp,fish,http
+Keywords[nds]=lisa,nettwark,smb,ftp,fish,http
+Keywords[ne]=लिसा,सञ्जाल,smb,ftp,fish,http
+Keywords[nl]=lisa,netwerk,smb,ftp,fish,http,samba
+Keywords[nn]=lisa,nettverk,smb,ftp,fish,http
+Keywords[pl]=lisa,sieć,smb,ftp,fish,http
+Keywords[pt]=lisa,rede,smb,ftp,fish,http
+Keywords[pt_BR]=lisa,rede,smb,ftp,fish,http
+Keywords[ru]=lisa,сеть,smb,ftp,fish,http
+Keywords[sk]=lisa,sieť,smb,ftp,fish,http
+Keywords[sl]=lisa,omrežje,smb,ftp,fish,http
+Keywords[sv]=lisa,nätverk,smb,ftp,fish,http
+Keywords[tr]=lisa,ağ,smb,ftp,fish,http
+Keywords[uk]=lisa,мережа,smb,ftp,fish,http
+Keywords[uz]=lisa,tarmoq,smb,ftp,fish,http
+Keywords[uz@cyrillic]=lisa,тармоқ,smb,ftp,fish,http
+Keywords[zh_CN]=lisa,network,smb,ftp,fish,http,网络
diff --git a/lanbrowsing/kcmlisa/kcmlisa.h b/lanbrowsing/kcmlisa/kcmlisa.h
new file mode 100644
index 00000000..fcda0a89
--- /dev/null
+++ b/lanbrowsing/kcmlisa/kcmlisa.h
@@ -0,0 +1,79 @@
+/*
+ * kcmlisa.h
+ *
+ * Copyright (c) 2000-2002 Alexander Neundorf <neundorf@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef KCMLISA_H
+#define KCMLISA_H
+
+#include <kconfig.h>
+#include <kcmodule.h>
+
+class QPushButton;
+class QCheckBox;
+class QSpinBox;
+class QPushButton;
+class KProcess;
+class KDialogBase;
+class KRestrictedLine;
+class KEditListBox;
+class SetupWizard;
+
+class LisaSettings:public KCModule
+{
+ Q_OBJECT
+ public:
+ LisaSettings(const QString& config, QWidget *parent=0);
+ virtual ~LisaSettings() {};
+ void load();
+ void save();
+ signals:
+ void changed();
+ protected slots:
+ void slotChanged();
+ void autoSetup();
+ void saveDone(KProcess *); // called after the kdesud returns (on save)
+ void suggestSettings();
+ protected:
+ KConfig m_config;
+ QPushButton *m_autoSetup;
+ QCheckBox *m_useNmblookup;
+ QCheckBox *m_sendPings;
+ KRestrictedLine *m_pingAddresses;
+ KEditListBox *m_pingNames;
+ KRestrictedLine *m_allowedAddresses;
+ KRestrictedLine *m_broadcastNetwork;
+ QSpinBox *m_firstWait;
+ QCheckBox *m_secondScan;
+ QSpinBox *m_secondWait;
+ QSpinBox *m_updatePeriod;
+ QCheckBox *m_deliverUnnamedHosts;
+ QSpinBox *m_maxPingsAtOnce;
+ QPushButton* m_suggestSettings;
+ QPushButton *m_advancedSettingsButton;
+ KDialogBase *m_lisaAdvancedDlg;
+
+ SetupWizard *m_wizard;
+ private:
+ QString m_tmpFilename;
+ QString m_configFilename;
+ bool m_changed;
+};
+
+#endif
+
diff --git a/lanbrowsing/kcmlisa/kcmreslisa.cpp b/lanbrowsing/kcmlisa/kcmreslisa.cpp
new file mode 100644
index 00000000..c4f14d1a
--- /dev/null
+++ b/lanbrowsing/kcmlisa/kcmreslisa.cpp
@@ -0,0 +1,250 @@
+/*
+ * kcmreslisa.cpp
+ *
+ * Copyright (c) 2000-2002 Alexander Neundorf <neundorf@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include "kcmreslisa.h"
+#include "findnic.h"
+
+#include <qspinbox.h>
+#include <qcheckbox.h>
+#include <qvbox.h>
+#include <qpushbutton.h>
+#include <qgrid.h>
+#include <qlabel.h>
+#include <qtooltip.h>
+#include <qlayout.h>
+#include <qvbuttongroup.h>
+
+#include <kdialogbase.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <krestrictedline.h>
+#include <keditlistbox.h>
+
+ResLisaSettings::ResLisaSettings(const QString& config, QWidget *parent)
+: KCModule(parent)
+,m_config(config,false,true)
+,m_kiolanConfig("kio_lanrc",false,true)
+,m_advancedSettingsButton(0)
+,m_suggestSettings(0)
+,m_useNmblookup(0)
+,m_pingNames(0)
+,m_allowedAddresses(0)
+,m_firstWait(0)
+,m_secondScan(0)
+,m_secondWait(0)
+,m_updatePeriod(0)
+,m_deliverUnnamedHosts(0)
+,m_maxPingsAtOnce(0)
+,m_reslisaAdvancedDlg(0)
+{
+ QVBoxLayout *layout = new QVBoxLayout(this, KDialog::marginHint(), KDialog::spacingHint());
+ layout->setAutoAdd(true);
+
+ QVButtonGroup *gb=new QVButtonGroup(i18n("Tell ResLISa Daemon How to Search for Hosts"),this);
+ gb->setInsideSpacing(10);
+
+ m_useNmblookup=new QCheckBox(i18n("Send &NetBIOS broadcasts using &nmblookup"),gb);
+ QToolTip::add(m_useNmblookup,i18n("Only hosts running SMB servers will answer"));
+
+ m_pingNames=new KEditListBox(i18n("A&dditionally Check These Hosts"),gb,"a",false, KEditListBox::Add|KEditListBox::Remove);
+ QToolTip::add(m_pingNames,i18n("The hosts listed here will be pinged."));
+
+ QHBox *hbox=new QHBox(this);
+ hbox->setSpacing(10);
+ QLabel *label=new QLabel(i18n("&Trusted addresses:"),hbox);
+ QString comment = i18n("Usually your network address/subnet mask (e.g. 192.168.0.0/255.255.255.0;)");
+ QToolTip::add(label, comment);
+ m_allowedAddresses=new KRestrictedLine(hbox,"a","0123456789./;");
+ QToolTip::add(m_allowedAddresses,comment);
+ label->setBuddy(m_allowedAddresses);
+
+ m_rlanSidebar = new QCheckBox(i18n("Use &rlan:/ instead of lan:/ in Konqueror's navigation panel"), this);
+
+ hbox = new QHBox(this);
+ m_suggestSettings=new QPushButton(i18n("&Suggest Settings"),hbox);
+
+ new QWidget(hbox);
+
+ m_advancedSettingsButton=new QPushButton(i18n("Ad&vanced Settings"),hbox);
+
+
+ m_reslisaAdvancedDlg=new KDialogBase(0,0,true,i18n("Advanced Settings for ResLISa"),KDialogBase::Close, KDialogBase::Close);
+ connect(m_advancedSettingsButton,SIGNAL(clicked()),m_reslisaAdvancedDlg,SLOT(show()));
+
+ QVBox *vbox=m_reslisaAdvancedDlg->makeVBoxMainWidget();
+
+ m_deliverUnnamedHosts=new QCheckBox(i18n("Show &hosts without DNS names"),vbox);
+
+ QGrid *advGrid = new QGrid(2, Qt::Horizontal, vbox);
+ advGrid->setSpacing(10);
+
+ label=new QLabel(i18n("Host list update interval:"),advGrid);
+ QToolTip::add(label,i18n("Search hosts after this number of seconds"));
+ m_updatePeriod=new QSpinBox(30,1800,10,advGrid);
+ m_updatePeriod->setSuffix(i18n(" sec"));
+ QToolTip::add(m_updatePeriod,i18n("Search hosts after this number of seconds"));
+
+ m_secondScan=new QCheckBox(i18n("Always check twice for hosts when searching"),advGrid);
+ new QWidget(advGrid);
+
+ label=new QLabel(i18n("Wait for replies from hosts after first scan:"),advGrid);
+ QToolTip::add(label,i18n("How long to wait for replies to the ICMP echo requests from hosts"));
+ m_firstWait=new QSpinBox(10,1000,50,advGrid);
+ m_firstWait->setSuffix(i18n(" ms"));
+ QToolTip::add(m_firstWait,i18n("How long to wait for replies to the ICMP echo requests from hosts"));
+
+ label=new QLabel(i18n("Wait for replies from hosts after second scan:"),advGrid);
+ QToolTip::add(label,i18n("How long to wait for replies to the ICMP echo requests from hosts"));
+ m_secondWait=new QSpinBox(0,1000,50,advGrid);
+ m_secondWait->setSuffix(i18n(" ms"));
+ QToolTip::add(m_secondWait,i18n("How long to wait for replies to the ICMP echo requests from hosts"));
+
+ label=new QLabel(i18n("Max. number of ping packets to send at once:"),advGrid);
+ m_maxPingsAtOnce=new QSpinBox(8,1024,5,advGrid);
+
+ QWidget *dummy=new QWidget(advGrid);
+ dummy->setMinimumHeight(10);
+
+ connect(m_secondScan,SIGNAL(toggled(bool)),m_secondWait,SLOT(setEnabled(bool)));
+
+ connect(m_allowedAddresses,SIGNAL(textChanged(const QString&)),this,SIGNAL(changed()));
+
+ connect(m_allowedAddresses,SIGNAL(returnPressed()),this,SIGNAL(changed()));
+
+ connect(m_firstWait,SIGNAL(valueChanged(int)),this,SIGNAL(changed()));
+ connect(m_secondWait,SIGNAL(valueChanged(int)),this,SIGNAL(changed()));
+ connect(m_maxPingsAtOnce,SIGNAL(valueChanged(int)),this,SIGNAL(changed()));
+ connect(m_secondScan,SIGNAL(toggled(bool)),this,SIGNAL(changed()));
+ connect(m_deliverUnnamedHosts,SIGNAL(toggled(bool)),this,SIGNAL(changed()));
+ connect(m_updatePeriod,SIGNAL(valueChanged(int)),this,SIGNAL(changed()));
+ connect(m_pingNames,SIGNAL(changed()),this,SIGNAL(changed()));
+ connect(m_useNmblookup,SIGNAL(toggled(bool)),this,SIGNAL(changed()));
+ connect(m_suggestSettings,SIGNAL(clicked()),this,SLOT(suggestSettings()));
+ connect(m_rlanSidebar,SIGNAL(clicked()),this,SIGNAL(changed()));
+
+ load();
+}
+
+void ResLisaSettings::load()
+{
+ int secondWait=m_config.readNumEntry("SecondWait",-1);
+ if (secondWait<0)
+ {
+ m_secondWait->setValue(300);
+ m_secondScan->setChecked(FALSE);
+ m_secondWait->setEnabled(FALSE);
+ }
+ else
+ {
+ m_secondWait->setValue(secondWait*10);
+ m_secondScan->setChecked(TRUE);
+ m_secondWait->setEnabled(TRUE);
+ };
+ m_deliverUnnamedHosts->setChecked(m_config.readNumEntry("DeliverUnnamedHosts",0));
+
+ m_firstWait->setValue(m_config.readNumEntry("FirstWait",30)*10);
+ m_maxPingsAtOnce->setValue(m_config.readNumEntry("MaxPingsAtOnce",256));
+ m_updatePeriod->setValue(m_config.readNumEntry("UpdatePeriod",300));
+ m_allowedAddresses->setText(m_config.readEntry("AllowedAddresses","192.168.0.0/255.255.255.0"));
+
+ int i=m_config.readNumEntry("SearchUsingNmblookup",1);
+ m_useNmblookup->setChecked(i!=0);
+ m_pingNames->clear();
+ m_pingNames->insertStringList(m_config.readListEntry("PingNames",';'));
+
+ m_rlanSidebar->setChecked(m_kiolanConfig.readEntry("sidebarURL", "lan:/") == "rlan:/" ? true : false );
+}
+
+void ResLisaSettings::save()
+{
+ if (m_secondScan->isChecked())
+ m_config.writeEntry("SecondWait",(m_secondWait->value()+5)/10);
+ else
+ m_config.writeEntry("SecondWait",-1);
+
+ if (m_useNmblookup->isChecked())
+ m_config.writeEntry("SearchUsingNmblookup",1);
+ else
+ m_config.writeEntry("SearchUsingNmblookup",0);
+
+ if (m_deliverUnnamedHosts->isChecked())
+ m_config.writeEntry("DeliverUnnamedHosts",1);
+ else
+ m_config.writeEntry("DeliverUnnamedHosts",0);
+
+ m_config.writeEntry("FirstWait",(m_firstWait->value()+5)/10);
+ m_config.writeEntry("MaxPingsAtOnce",m_maxPingsAtOnce->value());
+ m_config.writeEntry("UpdatePeriod",m_updatePeriod->value());
+ m_config.writeEntry("AllowedAddresses",m_allowedAddresses->text());
+ //m_config.writeEntry("BroadcastNetwork",m_broadcastNetwork->text());
+ QStringList writeStuff;
+ for (int i=0; i<m_pingNames->count(); i++)
+ writeStuff.append(m_pingNames->text(i));
+ m_config.writeEntry("PingNames",writeStuff,';');
+
+ m_config.sync();
+
+ m_kiolanConfig.writeEntry("sidebarURL", m_rlanSidebar->isChecked() ? "rlan:/" : "lan:/");
+ m_kiolanConfig.sync();
+
+}
+
+void ResLisaSettings::suggestSettings()
+{
+ NICList* nics=findNICs();
+ if (nics->count()==0)
+ {
+ //ok, easy one :-)
+ KMessageBox::sorry(0,i18n("It appears you do not have any network interfaces installed on your system."));
+ delete nics;
+ return;
+ }
+
+ MyNIC *nic=nics->first();
+ QString address = nic->addr;
+ QString netmask = nic->netmask;
+ m_allowedAddresses->setText(address+"/"+netmask+";");
+ m_secondWait->setValue(0);
+ m_secondScan->setChecked(FALSE);
+ m_secondWait->setEnabled(FALSE);
+ m_firstWait->setValue(300);
+ m_maxPingsAtOnce->setValue(256);
+ m_updatePeriod->setValue(300);
+ m_useNmblookup->setChecked(true);
+ if (nics->count()>1)
+ {
+ QString msg(i18n("You have more than one network interface installed.<br>"
+ "Please make sure the suggested settings are correct.<br>"
+ "<br>The following interfaces were found:<br><br>"));
+ //not that easy to handle
+ for (MyNIC* tmp=nics->first(); tmp!=0; tmp=nics->next())
+ {
+ msg+="<b>"+tmp->name+": </b>"+tmp->addr+"/"+tmp->netmask+";<br>";
+ }
+ KMessageBox::information(0,QString("<html>%1</html>").arg(msg));
+ }
+ KMessageBox::information(0,QString("<html>%1</html>").arg(i18n("The ResLISa daemon is now configured "
+ "correctly, hopefully.<br>Make sure that the reslisa binary is installed <i>suid root</i>.")));
+
+ emit changed();
+ delete nics;
+}
+
+#include "kcmreslisa.moc"
+
diff --git a/lanbrowsing/kcmlisa/kcmreslisa.desktop b/lanbrowsing/kcmlisa/kcmreslisa.desktop
new file mode 100644
index 00000000..47d54652
--- /dev/null
+++ b/lanbrowsing/kcmlisa/kcmreslisa.desktop
@@ -0,0 +1,123 @@
+[Desktop Entry]
+Type=Application
+Icon=samba
+Exec=kcmshell kcmreslisa
+
+X-KDE-ModuleType=Library
+X-KDE-Library=lanbrowser
+X-KDE-FactoryName=reslisa
+
+Name=ResLISa
+Name[hi]=रेस-लिसा
+Name[sv]=ResLisa
+Name[zh_TW]=ResLISaName=ResLISa
+
+Comment=Setup ResLISa
+Comment[ar]=تنصيب ResLISa
+Comment[be]=Настаўленне ResLISы
+Comment[bg]=Настройване на ResLISa
+Comment[bn]=ResLISa ব্যবস্থাপনা
+Comment[br]=Kefluniañ ResLISa
+Comment[bs]=Podešavanje ResLISe
+Comment[ca]=Per l'arranjament de ResLISa
+Comment[cs]=Nastavit ResLISa
+Comment[cy]=Gosod ResLISa
+Comment[da]=Opsætning af ResLISa
+Comment[de]=ResLISa einrichten
+Comment[el]=Ρύθμιση ResLISa
+Comment[eo]=Agordo de ResLISa
+Comment[es]=Configuración ResLISa
+Comment[et]=ResLISa seadistamine
+Comment[eu]=ResLISa konfiguratu
+Comment[fa]=برپایی ResLISa
+Comment[fi]=Aseta ResLISa
+Comment[fr]=Configuration de ResLISa
+Comment[ga]=Cumraigh ResLISa
+Comment[gl]=Configuración de ResLISa
+Comment[he]=שינוי הגדרות ResLISa
+Comment[hi]=सेटअप रेस-लिसा
+Comment[hr]=Podešavanje ResLISa-e
+Comment[hu]=A ResLISa szolgáltatás beállítása
+Comment[is]=Stillingar ResLISa
+Comment[it]=Impostazioni ResLISa
+Comment[ja]=ResLISa のセットアップ
+Comment[ka]=ResLISa გამართვა
+Comment[kk]=ResLISa баптауы
+Comment[km]=រៀបចំ ResLISa
+Comment[lt]=Nustatyti ResLISa
+Comment[mk]=Поставување на ResLISa
+Comment[mn]=ResLISa тохируулга
+Comment[ms]=Pasang ResLISa
+Comment[nb]=Tilpass ResLISa
+Comment[nds]=ResLISa instellen
+Comment[ne]=ResLIsa सेटअप गर्नुहोस्
+Comment[nl]=ResLISa instellen
+Comment[nn]=ResLISa-oppsett
+Comment[nso]=Beakanya ResLISa
+Comment[pl]=Ustawienia programu ResLISa
+Comment[pt]=Configuração do ResLISa
+Comment[pt_BR]=Configuração de ResLISa
+Comment[ru]=Параметры ResLISa
+Comment[se]=Heivet ResLISa
+Comment[sk]=Nastavenie ResLISy
+Comment[sl]=Nastavi ResLISa
+Comment[sr]=Подесите ResLISa-у
+Comment[sr@Latn]=Podesite ResLISa-u
+Comment[sv]=Anpassa ResLisa
+Comment[ta]=ResLISa அமைப்பு
+Comment[tg]=Барпосозии ResLISa
+Comment[th]=ตั้งค่า ResLISa
+Comment[tr]=ResLISa'yı yapılandır
+Comment[uk]=Налаштування ResLISa
+Comment[uz]=ResLISa'ni oʻrnatish
+Comment[uz@cyrillic]=ResLISa'ни ўрнатиш
+Comment[ven]=Vhekanyani ResLISa
+Comment[wa]=Apontiaedje di ResLISa
+Comment[xh]=Cwangcisa ResLISa
+Comment[zh_CN]=设置 ResLISa
+Comment[zh_HK]=設定 ResLISa
+Comment[zh_TW]=設定 ResLISa
+Comment[zu]=Lungisa i-ResLISa
+
+
+Keywords=reslisa,network,smb,ftp,fish,http
+Keywords[be]=сетка,reslisa,network,smb,ftp,fish,http
+Keywords[bg]=мрежа, самба, настройки, локална, споделяне, reslisa, network, smb, ftp, fish, http
+Keywords[br]=reslisa,rouedad,smb,ftp,fish,http
+Keywords[ca]=reslisa,xarxa,smb,ftp,fish,http
+Keywords[cs]=reslisa,síť,smb,ftp,fish,http
+Keywords[cy]=reslisa,rhwydwaith,smb,ftp,fish,http
+Keywords[da]=reslisa,netværk,smb,ftp,fish,http
+Keywords[de]=reslisa,Netzwerk,smb,ftp,fish,http
+Keywords[el]=reslisa,δίκτυο,smb,ftp,fish,http
+Keywords[et]=reslisa,võrk,smb,ftp,fish,http
+Keywords[eu]=reslisa,sarea,smb,ftp,fish,http
+Keywords[fa]=reslisa، شبکه، smb، قاپ، fish، قام
+Keywords[fi]=reslisa,verkko,smb,ftp,fish,http
+Keywords[fr]=reslisa,réseau,smb,ftp,fish,http
+Keywords[gl]=reslisa,redes,smb,ftp,fish,http
+Keywords[he]=reslisa,רשת,smb,ftp,fish,http
+Keywords[hi]=रेसलिसा,नेटवर्क,एसएमबी,एफटीपी,फिश,एचटीटीपी
+Keywords[hu]=reslisa,hálózat,smb,ftp,fish,http
+Keywords[it]=reslisa,rete,smb,ftp,fish,http
+Keywords[ja]=reslisa,ネットワーク,smb,ftp,fish,http
+Keywords[km]=reslisa,បណ្ដាញ,smb,ftp,fish,http
+Keywords[lt]=reslisa,network,smb,ftp,fish,http,tinklas
+Keywords[mk]=reslisa,network,smb,ftp,fish,http,мрежа
+Keywords[nb]=reslisa,nettverk,smb,ftp,fish,http
+Keywords[nds]=reslisa,nettwark,smb,ftp,fish,http
+Keywords[ne]=रेसलिसा,सञ्जाल,smb,ftp,fish,http
+Keywords[nl]=reslisa,netwerk,smb,ftp,fish,http,samba
+Keywords[nn]=reslisa,nettverk,smb,ftp,fish,http
+Keywords[pl]=reslisa,sieć,smb,ftp,fish,http
+Keywords[pt]=reslisa,rede,smb,ftp,fish,http
+Keywords[pt_BR]=reslisa,rede,smb,ftp,fish,http
+Keywords[ru]=reslisa,сеть,smb,ftp,fish,http
+Keywords[sk]=reslisa,sieť,smb,ftp,fish,http
+Keywords[sl]=reslisa,omrežje,smb,ftp,fish,http
+Keywords[sv]=reslisa,nätverk,smb,ftp,fish,http
+Keywords[tr]=reslisa,ağ,smb,ftp,fish,http
+Keywords[uk]=reslisa,мережа,smb,ftp,fish,http
+Keywords[uz]=reslisa,tarmoq,smb,ftp,fish,http
+Keywords[uz@cyrillic]=reslisa,тармоқ,smb,ftp,fish,http
+Keywords[zh_CN]=reslisa,network,smb,ftp,fish,http,网络
diff --git a/lanbrowsing/kcmlisa/kcmreslisa.h b/lanbrowsing/kcmlisa/kcmreslisa.h
new file mode 100644
index 00000000..ee8734df
--- /dev/null
+++ b/lanbrowsing/kcmlisa/kcmreslisa.h
@@ -0,0 +1,67 @@
+/*
+ * kcmreslisa.h
+ *
+ * Copyright (c) 2000-2002 Alexander Neundorf <neundorf@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef KCMRESLISA_H
+#define KCMRESLISA_H
+
+#include <kcmodule.h>
+#include <kconfig.h>
+
+
+class QSpinBox;
+class QCheckBox;
+class QPushButton;
+class KEditListBox;
+class KDialogBase;
+class KRestrictedLine;
+
+class ResLisaSettings:public KCModule
+{
+ Q_OBJECT
+ public:
+ ResLisaSettings(const QString& config, QWidget *parent=0);
+ virtual ~ResLisaSettings() {}
+ void load();
+ void save();
+ signals:
+ void changed();
+ protected slots:
+ void suggestSettings();
+ protected:
+ KConfig m_config;
+ KConfig m_kiolanConfig;
+ QPushButton* m_advancedSettingsButton;
+ QPushButton* m_suggestSettings;
+ QCheckBox* m_useNmblookup;
+ KEditListBox *m_pingNames;
+
+ KRestrictedLine *m_allowedAddresses;
+ QSpinBox *m_firstWait;
+ QCheckBox *m_secondScan;
+ QSpinBox *m_secondWait;
+ QSpinBox *m_updatePeriod;
+ QCheckBox *m_deliverUnnamedHosts;
+ QSpinBox *m_maxPingsAtOnce;
+ QCheckBox* m_rlanSidebar;
+ KDialogBase* m_reslisaAdvancedDlg;
+};
+
+#endif
+
diff --git a/lanbrowsing/kcmlisa/main.cpp b/lanbrowsing/kcmlisa/main.cpp
new file mode 100644
index 00000000..c9d9b6b2
--- /dev/null
+++ b/lanbrowsing/kcmlisa/main.cpp
@@ -0,0 +1,49 @@
+/*
+ * main.cpp for lisa,reslisa,kio_lan and kio_rlan kcm module
+ *
+ * Copyright (C) 2000,2001,2005 Alexander Neundorf <neundorf@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <klocale.h>
+#include <kdebug.h>
+
+#include <qdir.h>
+#include <qdatetime.h>
+
+#include <unistd.h>
+#include <sys/types.h>
+
+#include "kcmlisa.h"
+#include "kcmreslisa.h"
+#include "kcmkiolan.h"
+
+extern "C"
+{
+ KDE_EXPORT KCModule *create_lisa(QWidget *parent, const char *)
+ {
+ return new LisaSettings("/etc/lisarc", parent);
+ }
+ KDE_EXPORT KCModule *create_reslisa(QWidget *parent, const char *)
+ {
+ return new ResLisaSettings(QDir::homeDirPath()+"/.reslisarc", parent);
+ }
+ KDE_EXPORT KCModule *create_kiolan(QWidget *parent, const char *)
+ {
+ return new IOSlaveSettings("kio_lanrc", parent);
+ }
+}
+
diff --git a/lanbrowsing/kcmlisa/portsettingsbar.cpp b/lanbrowsing/kcmlisa/portsettingsbar.cpp
new file mode 100644
index 00000000..a6bc94d9
--- /dev/null
+++ b/lanbrowsing/kcmlisa/portsettingsbar.cpp
@@ -0,0 +1,51 @@
+/*
+ * portsettingsbar.cpp
+ *
+ * Copyright (c) 2000, 2005 Alexander Neundorf <neundorf@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "portsettingsbar.h"
+#include <klocale.h>
+
+#include <qlabel.h>
+
+PortSettingsBar::PortSettingsBar(const QString& title, QWidget *parent)
+:QHBox(parent)
+{
+ QLabel* label=new QLabel(title, this);
+ m_box=new QComboBox(this);
+ label->setBuddy(m_box);
+
+ m_box->insertItem(i18n("Check Availability"));
+ m_box->insertItem(i18n("Always"));
+ m_box->insertItem(i18n("Never"));
+
+ connect(m_box,SIGNAL(activated(int)),this,SIGNAL(changed()));
+}
+
+int PortSettingsBar::selected() const
+{
+ return m_box->currentItem();
+}
+
+void PortSettingsBar::setChecked(int what)
+{
+ m_box->setCurrentItem(what);
+}
+
+#include "portsettingsbar.moc"
+
diff --git a/lanbrowsing/kcmlisa/portsettingsbar.h b/lanbrowsing/kcmlisa/portsettingsbar.h
new file mode 100644
index 00000000..9cc92e02
--- /dev/null
+++ b/lanbrowsing/kcmlisa/portsettingsbar.h
@@ -0,0 +1,45 @@
+/*
+ * portsettingsbar.h
+ *
+ * Copyright (c) 2000, 2005 Alexander Neundorf <neundorf@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PORTSETTINGSBAR_H
+#define PORTSETTINGSBAR_H
+
+#include <qhbox.h>
+#include <qcombobox.h>
+
+#define PORTSETTINGS_CHECK 0
+#define PORTSETTINGS_PROVIDE 1
+#define PORTSETTINGS_DISABLE 2
+
+class PortSettingsBar:public QHBox
+{
+ Q_OBJECT
+ public:
+ PortSettingsBar(const QString& title, QWidget *parent=0);
+ virtual ~PortSettingsBar() {};
+ int selected() const;
+ void setChecked(int what);
+ signals:
+ void changed();
+ protected:
+ QComboBox *m_box;
+};
+
+#endif
diff --git a/lanbrowsing/kcmlisa/setupwizard.cpp b/lanbrowsing/kcmlisa/setupwizard.cpp
new file mode 100644
index 00000000..7ff91f8f
--- /dev/null
+++ b/lanbrowsing/kcmlisa/setupwizard.cpp
@@ -0,0 +1,569 @@
+/*
+ * setupwizard.cpp
+ *
+ * Copyright (C) 2001 Alexander Neundorf <neundorf@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "setupwizard.h"
+
+#include <qregexp.h>
+
+#include <klocale.h>
+#include <kdialog.h>
+#include <ksockaddr.h>
+#include <kdebug.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+SetupWizard::SetupWizard(QWidget* parent, LisaConfigInfo* configInfo)
+ :QWizard(parent,"hallo",true)
+ ,m_page1(0)
+ ,m_noNicPage(0)
+ ,m_multiNicPage(0)
+ ,m_searchPage(0)
+ ,m_addressesPage(0)
+ ,m_allowedAddressesPage(0)
+ ,m_bcastPage(0)
+ ,m_intervalPage(0)
+ ,m_advancedPage(0)
+ ,m_finalPage(0)
+ ,m_nicListBox(0)
+ ,m_trustedHostsLabel(0)
+ ,m_ping(0)
+ ,m_nmblookup(0)
+ ,m_pingAddresses(0)
+ ,m_allowedAddresses(0)
+ ,m_bcastAddress(0)
+ ,m_manualAddress(0)
+ ,m_updatePeriod(0)
+ ,m_deliverUnnamedHosts(0)
+ ,m_firstWait(0)
+ ,m_maxPingsAtOnce(0)
+ ,m_secondScan(0)
+ ,m_secondWait(0)
+ ,m_nics(0)
+ ,m_configInfo(configInfo)
+{
+ QString title( i18n("LISa Network Neighborhood Setup") );
+ setCaption(title);
+
+ m_configInfo->clear();
+ setupPage1();
+ addPage( m_page1, title);
+
+ setupAdvancedSettingsPage();
+ addPage( m_advancedPage, i18n("Advanced Settings"));
+
+}
+
+SetupWizard::~SetupWizard()
+{}
+
+void SetupWizard::clearAll()
+{
+ showPage(m_page1);
+ if (m_nicListBox)
+ m_nicListBox->clear();
+
+ if (m_manualAddress)
+ m_manualAddress->setText("");
+
+ if (m_ping)
+ m_ping->setChecked(false);
+ if (m_nmblookup)
+ m_nmblookup->setChecked(false);
+
+ if (m_pingAddresses)
+ m_pingAddresses->setText("");
+ if (m_allowedAddresses)
+ m_allowedAddresses->setText("");
+ if (m_bcastAddress)
+ m_bcastAddress->setText("");
+ if (m_updatePeriod)
+ m_updatePeriod->setValue(300);
+
+ if (m_deliverUnnamedHosts)
+ m_deliverUnnamedHosts->setChecked(false);
+ if (m_firstWait)
+ m_firstWait->setValue(10);
+ if (m_maxPingsAtOnce)
+ m_maxPingsAtOnce->setValue(256);
+ if (m_secondScan)
+ m_secondScan->setChecked(false);
+ if (m_secondWait)
+ {
+ m_secondWait->setEnabled(false);
+ m_secondWait->setValue(0);
+ }
+
+ if (m_nics)
+ {
+ delete m_nics;
+ m_nics=0;
+ }
+}
+
+void SetupWizard::setupPage1()
+{
+ m_page1 = new QVBox( this );
+
+ new QLabel(i18n("<qt><p>This wizard will ask you a few questions about your network.</p> "
+ "<p>Usually you can simply keep the suggested settings.</p> "
+ "<p>After you have finished the wizard, you will be able to browse and use "
+ "shared resources on your LAN, not only Samba/Windows shares, but also "
+ "FTP, HTTP and NFS resources exactly the same way.</p> "
+ "<p>Therefore you need to setup the <i>LAN Information Server</i> (LISa) on your machine. "
+ "Think of the LISa server as an FTP or HTTP server; "
+ "it has to be run by root, it should be started during the boot process and "
+ "only one LISa server can run on one machine.</qt>"),
+ m_page1);
+
+ QWidget *dummy=new QWidget(m_page1);
+ m_page1->setStretchFactor(dummy,10);
+ m_page1->setSpacing(KDialog::spacingHint());
+ m_page1->setMargin(KDialog::marginHint());
+
+ setNextEnabled( m_page1, true );
+ setHelpEnabled( m_page1, false );
+}
+
+void SetupWizard::setupMultiNicPage()
+{
+ m_multiNicPage=new QVBox(this);
+ new QLabel(i18n("<qt><p>More than one network interface card was found on your system.</p>"
+ "<p>Please choose the one to which your LAN is connected.</p></qt>"),
+ m_multiNicPage);
+
+ m_multiNicPage->setMargin(KDialog::marginHint());
+ m_multiNicPage->setSpacing(KDialog::spacingHint());
+
+ m_nicListBox=new QListBox(m_multiNicPage);
+ m_nicListBox->setSelectionMode(QListBox::Single);
+ setHelpEnabled( m_multiNicPage, false );
+}
+
+void SetupWizard::setupNoNicPage()
+{
+ m_noNicPage=new QVBox(this);
+ new QLabel(i18n("<qt><p><b>No network interface card was found on your system.</b></p>"
+ "<p>Possible reason: no network card is installed. You probably want to cancel now "
+ "or enter your IP address and network manually</p>"
+ "Example: <code>192.168.0.1/255.255.255.0</code>.</qt>"),
+ m_noNicPage);
+
+ m_noNicPage->setMargin(KDialog::marginHint());
+ m_noNicPage->setSpacing(KDialog::spacingHint());
+ m_manualAddress=new KRestrictedLine(m_noNicPage,"0123456789./");
+ connect(m_manualAddress,SIGNAL(textChanged(const QString&)),this,SLOT(checkIPAddress(const QString&)));
+ QWidget *dummy=new QWidget(m_noNicPage);
+ m_noNicPage->setStretchFactor(dummy,10);
+
+ setNextEnabled(m_noNicPage, false);
+ setHelpEnabled(m_noNicPage, false);
+}
+
+
+void SetupWizard::setupSearchPage()
+{
+ m_searchPage=new QVBox(this);
+ QLabel *info=new QLabel(i18n("There are two ways LISa can search hosts on your network."),m_searchPage);
+ info->setTextFormat(Qt::RichText);
+ m_ping=new QCheckBox(i18n("Send pings"), m_searchPage);
+ info=new QLabel(i18n("All hosts with TCP/IP will respond,<br>"
+ "whether or not they are samba servers.<br>"
+ "Don\'t use it if your network is very large, i.e. more than 1000 hosts.<br>"),m_searchPage);
+ m_nmblookup=new QCheckBox(i18n("Send NetBIOS broadcasts"),m_searchPage);
+ info=new QLabel(i18n("You need to have the samba package (nmblookup) installed.<br>"
+ "Only samba/windows servers will respond.<br>"
+ "This method is not very reliable.<br>"
+ "You should enable it if you are part of a large network."),m_searchPage);
+ info->setTextFormat(Qt::RichText);
+ QWidget *dummy=new QWidget(m_searchPage);
+ m_searchPage->setStretchFactor(dummy,10);
+ m_searchPage->setSpacing(KDialog::spacingHint());
+ m_searchPage->setMargin(KDialog::marginHint());
+ info=new QLabel(i18n("<b>If unsure, keep it as is.</b>"),m_searchPage);
+ info->setAlignment(AlignRight|AlignVCenter);
+
+ setHelpEnabled( m_searchPage, false );
+}
+
+void SetupWizard::setupAddressesPage()
+{
+ m_addressesPage=new QVBox(this);
+ QLabel *info=new QLabel(i18n("All IP addresses included in the specified range will be pinged.<br>"
+ "If you are part of a small network, e.g. with network mask 255.255.255.0<br>"
+ "use your IP address/network mask.<br>"),m_addressesPage);
+ info->setTextFormat(Qt::RichText);
+ m_pingAddresses=new KRestrictedLine(m_addressesPage,"0123456789./;-");
+ info=new QLabel(i18n("<br>There are four ways to specify address ranges:<br>"
+ "1. IP address/network mask, like <code>192.168.0.0/255.255.255.0;</code><br>"
+ "2. single IP addresses, like <code>10.0.0.23;</code><br>"
+ "3. continuous ranges, like <code>10.0.1.0-10.0.1.200;</code><br>"
+ "4. ranges for each part of the address, like <code>10-10.1-5.1-25.1-3;</code><br>"
+ "You can also enter combinations of 1 to 4, separated by \";\", like<br>"
+ "<code>192.168.0.0/255.255.255.0;10.0.0.0;10.0.1.1-10.0.1.100;</code><br>"),m_addressesPage);
+ info->setAlignment(AlignLeft|AlignVCenter|WordBreak);
+ QWidget *dummy=new QWidget(m_addressesPage);
+ m_addressesPage->setStretchFactor(dummy,10);
+ m_addressesPage->setSpacing(KDialog::spacingHint());
+ m_addressesPage->setMargin(KDialog::marginHint());
+ info=new QLabel(i18n("<b>If unsure, keep it as is.</b>"), m_addressesPage);
+ info->setAlignment(AlignRight|AlignVCenter);
+
+ setHelpEnabled( m_addressesPage, false );
+}
+
+void SetupWizard::setupAllowedPage()
+{
+ m_allowedAddressesPage=new QVBox(this);
+ QLabel* info=new QLabel(i18n("This is a security related setting.<br>"
+ "It provides a simple IP address based way to specify \"trusted\" hosts.<br>"
+ "Only hosts which fit into the addresses given here are accepted by LISa as clients. "
+ "The list of hosts published by LISa will also only contain hosts which fit into this scheme.<br>"
+ "Usually you enter your IP address/network mask here."),m_allowedAddressesPage);
+ info->setAlignment(AlignLeft|AlignVCenter|WordBreak);
+ m_allowedAddresses=new KRestrictedLine(m_allowedAddressesPage,"0123456789./-;");
+ m_trustedHostsLabel=new QLabel(m_allowedAddressesPage);
+
+ QWidget *dummy=new QWidget(m_allowedAddressesPage);
+ m_allowedAddressesPage->setStretchFactor(dummy,10);
+ m_allowedAddressesPage->setSpacing(KDialog::spacingHint());
+ m_allowedAddressesPage->setMargin(KDialog::marginHint());
+ info=new QLabel(i18n("<b>If unsure, keep it as is.</b>"), m_allowedAddressesPage);
+ info->setAlignment(AlignRight|AlignVCenter);
+
+ setHelpEnabled( m_allowedAddressesPage, false );
+}
+
+void SetupWizard::setupBcastPage()
+{
+ m_bcastPage=new QVBox(this);
+ QLabel *info=new QLabel(i18n("<br>Enter your IP address and network mask here, like <code>192.168.0.1/255.255.255.0</code>"),m_bcastPage);
+ info->setAlignment(AlignLeft|AlignVCenter|WordBreak);
+ m_bcastAddress=new KRestrictedLine(m_bcastPage,"0123456789./");
+ info=new QLabel(i18n("<br>To reduce the network load, the LISa servers in one network<br>"
+ "cooperate with each other. Therefore you have to enter the broadcast<br>"
+ "address here. If you are connected to more than one network, choose <br>"
+ "one of the broadcast addresses."),m_bcastPage);
+ info->setAlignment(AlignLeft|AlignVCenter|WordBreak);
+ QWidget *dummy=new QWidget(m_bcastPage);
+ m_bcastPage->setStretchFactor(dummy,10);
+ m_bcastPage->setSpacing(KDialog::spacingHint());
+ info=new QLabel(i18n("<b>If unsure, keep it as is.</b>"), m_bcastPage);
+ info->setAlignment(AlignRight|AlignVCenter);
+
+ m_bcastPage->setSpacing(KDialog::spacingHint());
+ m_bcastPage->setMargin(KDialog::marginHint());
+ setHelpEnabled( m_bcastPage, false );
+}
+
+void SetupWizard::setupUpdateIntervalPage()
+{
+ m_intervalPage=new QVBox(this);
+ QLabel *info=new QLabel(i18n("<br>Enter the interval after which LISa, if busy, will update its host list."),m_intervalPage);
+ info->setTextFormat(Qt::RichText);
+
+ m_updatePeriod=new QSpinBox(300,1800,10,m_intervalPage);
+ m_updatePeriod->setSuffix(i18n(" sec"));
+
+ info=new QLabel(i18n("<br>Please note that the update interval will grow automatically by "
+ "up to 16 times the value you enter here, if nobody accesses the LISa server. "
+ "So if you enter 300 sec = 5 min here, this does not mean that LISa will ping "
+ "your whole network every 5 minutes. The interval will increase up to 16 x 5 min = 80 min."),m_intervalPage);
+ info->setAlignment(AlignLeft|AlignVCenter|WordBreak);
+ QWidget *dummy=new QWidget(m_intervalPage);
+ m_intervalPage->setStretchFactor(dummy,10);
+ m_intervalPage->setSpacing(KDialog::spacingHint());
+ m_intervalPage->setMargin(KDialog::marginHint());
+ info=new QLabel(i18n("<b>If unsure, keep it as is.</b>"), m_intervalPage);
+ info->setAlignment(AlignRight|AlignVCenter);
+ info->setTextFormat(Qt::RichText);
+
+ setHelpEnabled( m_intervalPage, false );
+}
+
+void SetupWizard::setupAdvancedSettingsPage()
+{
+ m_advancedPage=new QVBox(this);
+ QLabel *info=new QLabel(i18n("This page contains several settings you usually only<br>"
+ "need if LISa doesn't find all hosts in your network."),m_advancedPage);
+ info->setTextFormat(Qt::RichText);
+ m_deliverUnnamedHosts=new QCheckBox(i18n("Re&port unnamed hosts"),m_advancedPage);
+ info=new QLabel(i18n("Should hosts for which LISa can\'t resolve the name be included in the host list?<br>"),m_advancedPage);
+
+ QHBox* hbox=new QHBox(m_advancedPage);
+
+ info=new QLabel(i18n("Wait for replies after first scan"),hbox);
+ m_firstWait=new QSpinBox(10,1000,50,hbox);
+ m_firstWait->setSuffix(i18n(" ms"));
+ info=new QLabel(i18n("How long should LISa wait for answers to pings?<br>"
+ "If LISa doesn\'t find all hosts, try to increase this value.<br>"),m_advancedPage);
+
+ hbox=new QHBox(m_advancedPage);
+ info=new QLabel(i18n("Max. number of pings to send at once"),hbox);
+ info->setTextFormat(Qt::RichText);
+ m_maxPingsAtOnce=new QSpinBox(8,1024,5,hbox);
+ info=new QLabel(i18n("How many ping packets should LISa send at once?<br>"
+ "If LISa doesn't find all hosts you could try to decrease this value.<br>"),m_advancedPage);
+
+ m_secondScan=new QCheckBox(i18n("Al&ways scan twice"),m_advancedPage);
+
+ hbox=new QHBox(m_advancedPage);
+// hbox->setSpacing(10); // WTF?
+ info=new QLabel(i18n("Wait for replies after second scan"),hbox);
+ info->setTextFormat(Qt::RichText);
+ m_secondWait=new QSpinBox(0,1000,50,hbox);
+ m_secondWait->setSuffix(i18n(" ms"));
+ info=new QLabel(i18n("If LISa doesn't find all hosts, enable this option."),m_advancedPage);
+
+ //this would make the dialog to large
+ //m_advancedPage->setSpacing(KDialog::spacingHint());
+ //m_advancedPage->setMargin(KDialog::marginHint());
+
+ info=new QLabel(i18n("<b>If unsure, keep it as is.</b>"), m_advancedPage);
+ info->setAlignment(AlignRight|AlignVCenter);
+
+ connect(m_secondScan,SIGNAL(toggled(bool)),m_secondWait,SLOT(setEnabled(bool)));
+ setHelpEnabled( m_advancedPage, false );
+}
+
+void SetupWizard::setupFinalPage()
+{
+ m_finalPage=new QVBox(this);
+ QLabel *info=new QLabel(i18n("<br>Your LAN browsing has been successfully set up.<br><br>"
+ "Make sure that the LISa server is started during the "
+ "boot process. How this is done depends on your "
+ "distribution and OS. Usually you have to insert it somewhere "
+ "in a boot script under <code>/etc</code>.<br>"
+ "Start the LISa server as root and without any command line options.<br>"
+ "The config file will now be saved to <code>/etc/lisarc</code>.<br>"
+ "To test the server, try <code>lan:/</code> in Konqueror.<br><br>"
+ "If you have problems or suggestions, visit http://lisa-home.sourceforge.net."),m_finalPage);
+ info->setTextFormat(Qt::RichText);
+ QWidget *dummy=new QWidget(m_finalPage);
+ m_finalPage->setStretchFactor(dummy,10);
+ m_finalPage->setSpacing(KDialog::spacingHint());
+ m_finalPage->setMargin(KDialog::marginHint());
+
+ setHelpEnabled( m_finalPage, false );
+}
+
+void SetupWizard::next()
+{
+ if (currentPage()==m_page1)
+ {
+ if (m_noNicPage==0)
+ setupRest();
+
+ setAppropriate(m_noNicPage,false);
+ setAppropriate(m_multiNicPage,false);
+ if (m_nics!=0)
+ delete m_nics;
+ m_nics=findNICs();
+
+ if (m_nics->count()==0)
+ {
+ setAppropriate(m_noNicPage,true);
+ }
+ else if (m_nics->count()==1)
+ {
+ //still easy
+ //if the host part is less than 20 bits simply take it
+ MyNIC *nic=m_nics->first();
+ LisaConfigInfo lci;
+ suggestSettingsForNic(nic,lci);
+ applyLisaConfigInfo(lci);
+ }
+ else
+ {
+ //more than one nic
+ setAppropriate(m_multiNicPage,true);
+ m_nicListBox->clear();
+ for (MyNIC *nic=m_nics->first(); nic!=0; nic=m_nics->next())
+ {
+ QString tmp=nic->name+": "+nic->addr+"/"+nic->netmask+";";
+ m_nicListBox->insertItem(tmp);
+ }
+ m_nicListBox->setSelected(0,true);
+ }
+ }
+ else if (currentPage()==m_multiNicPage)
+ {
+ QString nic=m_nicListBox->currentText();
+ unsigned int i=0;
+ for (i=0; i<m_nicListBox->count(); i++)
+ {
+ if (m_nicListBox->isSelected(i))
+ {
+ nic=m_nicListBox->text(i);
+ break;
+ }
+ }
+ MyNIC* thisNic=m_nics->at(i);
+ LisaConfigInfo lci;
+ suggestSettingsForNic(thisNic,lci);
+ applyLisaConfigInfo(lci);
+ }
+ else if (currentPage()==m_noNicPage)
+ {
+ LisaConfigInfo lci;
+ suggestSettingsForAddress(m_manualAddress->text(),lci);
+ applyLisaConfigInfo(lci);
+ }
+ else if (currentPage()==m_searchPage)
+ setAppropriate(m_addressesPage, m_ping->isChecked());
+ else if (currentPage()==m_intervalPage)
+ {
+ if (m_finalPage==0)
+ {
+ setupFinalPage();
+ addPage( m_finalPage, i18n("Congratulations!"));
+ }
+ setAppropriate(m_advancedPage, m_ping->isChecked());
+ }
+ QWizard::next();
+}
+
+void SetupWizard::showPage(QWidget* page)
+{
+ if (page==m_noNicPage)
+ {
+ m_manualAddress->setFocus();
+ setNextEnabled(m_noNicPage, false);
+ setHelpEnabled(m_noNicPage, false);
+ }
+ else if (page==m_multiNicPage)
+ m_nicListBox->setFocus();
+ else if ( page == m_searchPage)
+ m_ping->setFocus();
+ else if (page==m_addressesPage)
+ m_pingAddresses->setFocus();
+ else if (page==m_allowedAddressesPage)
+ {
+ QString text;
+ if (m_ping->isChecked())
+ text+=i18n("You can use the same syntax as on the previous page.<br>");
+ else
+ text+=i18n("There are three ways to specify IP addresses:<br>"
+ "1. IP address/network mask, like<code> 192.168.0.0/255.255.255.0;</code><br>"
+ "2. continuous ranges, like<code> 10.0.1.0-10.0.1.200;</code><br>"
+ "3. single IP addresses, like<code> 10.0.0.23;</code><br>"
+ "You can also enter combinations of 1 to 3, separated by \";\", <br>"
+ "like<code> 192.168.0.0/255.255.255.0;10.0.0.0;10.0.1.1-10.0.1.100;</code><br>");
+ m_trustedHostsLabel->setText(text);
+ m_allowedAddresses->setFocus();
+ }
+ else if (page==m_bcastPage)
+ m_bcastAddress->setFocus();
+ else if (page==m_intervalPage)
+ m_updatePeriod->setFocus();
+ else if (page==m_advancedPage)
+ m_deliverUnnamedHosts->setFocus();
+ else if (page==m_finalPage)
+ setFinishEnabled(m_finalPage,true);
+
+ QWizard::showPage(page);
+}
+
+void SetupWizard::setupRest()
+{
+ removePage(m_advancedPage);
+
+ setupMultiNicPage();
+ addPage( m_multiNicPage, i18n("Multiple Network Interfaces Found"));
+
+ setupNoNicPage();
+ addPage( m_noNicPage, i18n("No Network Interface Found"));
+ setNextEnabled(m_noNicPage, false);
+ setHelpEnabled(m_noNicPage, false);
+
+ setupSearchPage();
+ addPage( m_searchPage, i18n("Specify Search Method"));
+
+ setupAddressesPage();
+ addPage( m_addressesPage, i18n("Specify Address Range LISa Will Ping"));
+
+ setupAllowedPage();
+ addPage( m_allowedAddressesPage, i18n("\"Trusted\" Hosts"));
+
+ setupBcastPage();
+ addPage( m_bcastPage, i18n("Your Broadcast Address"));
+
+ setupUpdateIntervalPage();
+ addPage( m_intervalPage, i18n("LISa Update Interval"));
+
+ addPage( m_advancedPage, i18n("Advanced Settings"));
+}
+
+void SetupWizard::accept()
+{
+ if (m_ping->isChecked())
+ {
+ m_configInfo->pingAddresses=m_pingAddresses->text();
+ m_configInfo->secondScan=m_secondScan->isChecked();
+ if (m_configInfo->secondScan)
+ m_configInfo->secondWait=(m_secondWait->value()+5)/10;
+ else
+ m_configInfo->secondWait=0;
+ m_configInfo->firstWait=(m_firstWait->value()+5)/10;
+ }
+ else
+ {
+ m_configInfo->pingAddresses="";
+ m_configInfo->secondScan=false;
+ m_configInfo->secondWait=0;
+ m_configInfo->firstWait=30;
+ }
+
+ m_configInfo->broadcastNetwork=m_bcastAddress->text();
+ m_configInfo->allowedAddresses=m_allowedAddresses->text();
+ m_configInfo->maxPingsAtOnce=m_maxPingsAtOnce->value();
+ m_configInfo->updatePeriod=m_updatePeriod->value();
+ m_configInfo->useNmblookup=m_nmblookup->isChecked();
+ m_configInfo->unnamedHosts=m_deliverUnnamedHosts->isChecked();
+ QWizard::accept();
+}
+
+void SetupWizard::checkIPAddress(const QString& addr)
+{
+ QString address=addr.simplifyWhiteSpace();
+ QRegExp regex("^\\d+\\.\\d+\\.\\d+\\.\\d+\\s*/\\s*\\d+\\.\\d+\\.\\d+\\.\\d+$");
+ setNextEnabled(m_noNicPage, (regex.search(address,0)!=-1));
+// setNextEnabled(m_noNicPage, (regex.find(address,0)!=-1));
+}
+
+void SetupWizard::applyLisaConfigInfo(LisaConfigInfo& lci)
+{
+ m_ping->setChecked(!lci.pingAddresses.isEmpty());
+ m_pingAddresses->setText(lci.pingAddresses);
+ m_nmblookup->setChecked(lci.useNmblookup);
+ m_allowedAddresses->setText(lci.allowedAddresses);
+ m_bcastAddress->setText(lci.broadcastNetwork);
+ m_updatePeriod->setValue(lci.updatePeriod);
+ m_deliverUnnamedHosts->setChecked(lci.unnamedHosts);
+ m_firstWait->setValue(lci.firstWait*10);
+ m_maxPingsAtOnce->setValue(lci.maxPingsAtOnce);
+ m_secondWait->setValue(lci.secondWait*10);
+ m_secondScan->setChecked(lci.secondScan);
+ m_secondWait->setEnabled(lci.secondScan);
+}
+
+#include "setupwizard.moc"
+
diff --git a/lanbrowsing/kcmlisa/setupwizard.h b/lanbrowsing/kcmlisa/setupwizard.h
new file mode 100644
index 00000000..a64cfaa2
--- /dev/null
+++ b/lanbrowsing/kcmlisa/setupwizard.h
@@ -0,0 +1,103 @@
+/*
+ * main.cpp for lisa,reslisa,kio_lan and kio_rlan kcm module
+ *
+ * Copyright (C) 2000 Alexander Neundorf <neundorf@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef LISA_SETUPWIZARD_H
+#define LISA_SETUPWIZARD_H
+
+#include "kcmlisa.h"
+#include "kcmreslisa.h"
+#include "kcmkiolan.h"
+
+#include "findnic.h"
+
+#include <qspinbox.h>
+#include <qcheckbox.h>
+#include <krestrictedline.h>
+#include <qwizard.h>
+#include <kglobal.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qlistbox.h>
+#include <qvbox.h>
+
+#include <kcmodule.h>
+
+
+class SetupWizard:public QWizard
+{
+ Q_OBJECT
+ public:
+ SetupWizard(QWidget* parent, LisaConfigInfo* configInfo);
+ ~SetupWizard();
+ virtual void showPage(QWidget* page);
+ void clearAll();
+ protected slots:
+ virtual void next();
+ virtual void accept();
+ void checkIPAddress(const QString& address);
+ protected:
+ void applyLisaConfigInfo(LisaConfigInfo& lci);
+
+ void setupPage1();
+ void setupNoNicPage();
+ void setupMultiNicPage();
+ void setupSearchPage();
+ void setupAddressesPage();
+ void setupAllowedPage();
+ void setupBcastPage();
+ void setupUpdateIntervalPage();
+ void setupAdvancedSettingsPage();
+ void setupFinalPage();
+ void setupRest();
+
+ QVBox* m_page1;
+ QVBox* m_noNicPage;
+ QVBox* m_multiNicPage;
+ QVBox* m_searchPage;
+ QVBox* m_addressesPage;
+ QVBox* m_allowedAddressesPage;
+ QVBox* m_bcastPage;
+ QVBox* m_intervalPage;
+ QVBox* m_advancedPage;
+ QVBox* m_finalPage;
+
+
+ QListBox *m_nicListBox;
+ QLabel *m_trustedHostsLabel;
+ QCheckBox *m_ping;
+ QCheckBox *m_nmblookup;
+ KRestrictedLine* m_pingAddresses;
+ KRestrictedLine* m_allowedAddresses;
+ KRestrictedLine* m_bcastAddress;
+ KRestrictedLine* m_manualAddress;
+ QSpinBox* m_updatePeriod;
+ QCheckBox* m_deliverUnnamedHosts;
+ QSpinBox* m_firstWait;
+ QSpinBox* m_maxPingsAtOnce;
+ QCheckBox* m_secondScan;
+ QSpinBox* m_secondWait;
+
+ NICList* m_nics;
+ LisaConfigInfo* m_configInfo;
+};
+
+
+#endif
+
diff --git a/lanbrowsing/kio_lan/AUTHORS b/lanbrowsing/kio_lan/AUTHORS
new file mode 100644
index 00000000..062f9d6c
--- /dev/null
+++ b/lanbrowsing/kio_lan/AUTHORS
@@ -0,0 +1,2 @@
+Written and maintained by:
+Alexander Neundorf, neundorf@kde.org
diff --git a/lanbrowsing/kio_lan/Makefile.am b/lanbrowsing/kio_lan/Makefile.am
new file mode 100644
index 00000000..e0f76e4b
--- /dev/null
+++ b/lanbrowsing/kio_lan/Makefile.am
@@ -0,0 +1,31 @@
+## Makefile.am of kdebase/kioslave/man
+
+INCLUDES= $(all_includes)
+
+####### Files
+
+kde_module_LTLIBRARIES = kio_lan.la
+
+kio_lan_la_SOURCES = kio_lan.cpp
+kio_lan_la_LIBADD = $(LIB_KIO)
+kio_lan_la_LDFLAGS = -module -avoid-version -no-undefined $(all_libraries) $(KDE_RPATH)
+
+noinst_HEADERS = kio_lan.h
+
+kdelnk_DATA = lan.protocol rlan.protocol
+kdelnkdir = $(kde_servicesdir)
+
+remote_DATA = lan.desktop
+remotedir = $(kde_datadir)/konqueror/dirtree/remote
+
+remoteio_DATA = lan.desktop
+remoteiodir = $(kde_datadir)/remoteview
+
+konq_sidebartree_DATA = lisa.desktop
+konq_sidebartreedir = $(kde_datadir)/konqsidebartng/virtual_folders/services
+
+METASOURCES = AUTO
+
+messages:
+ $(XGETTEXT) *.cpp -o $(podir)/kio_lan.pot
+
diff --git a/lanbrowsing/kio_lan/README b/lanbrowsing/kio_lan/README
new file mode 100644
index 00000000..0a49f83c
--- /dev/null
+++ b/lanbrowsing/kio_lan/README
@@ -0,0 +1,16 @@
+This is a brandnew ioslave for my brandnew LISa daemon/server.
+It provides something like a network neighbourhood
+only relying on the TCP/IP protocol stack for KDE. Enter lan:/ to see it.
+Read the README for lisa/reslisa.
+LISa/resLISa is in the subdir lisa/.
+Maybe you have to adjust the Makefile a little bit, it currently doesn't
+use the automake/configure stuff.
+On some systems (e.g. Solaris) you will have to add some libraries, like
+-lnsl, I think.
+
+Copy this directory e.g. under kdebase/kioslave and enter it in
+kdebase/kioslave/Makefile.am in the SUBDIR line. The rerun make in
+kdebase/kioslave.
+
+Alexander Neundorf
+<neundorf@kde.org>
diff --git a/lanbrowsing/kio_lan/TODO b/lanbrowsing/kio_lan/TODO
new file mode 100644
index 00000000..8640402e
--- /dev/null
+++ b/lanbrowsing/kio_lan/TODO
@@ -0,0 +1,3 @@
+mainly testing, I think
+
+Alex
diff --git a/lanbrowsing/kio_lan/kio_lan.cpp b/lanbrowsing/kio_lan/kio_lan.cpp
new file mode 100644
index 00000000..06368b8d
--- /dev/null
+++ b/lanbrowsing/kio_lan/kio_lan.cpp
@@ -0,0 +1,794 @@
+/* This file is part of the KDE project
+ Copyright (C) 2000,2001 Alexander Neundorf <neundorf@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kinstance.h>
+#include <kconfig.h>
+#include <kglobal.h>
+#include <kprocess.h>
+
+#include <qfile.h>
+
+#include <iostream>
+#include <string.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <time.h>
+#include <pwd.h>
+
+#include "kio_lan.h"
+
+#ifndef AF_LOCAL
+#define AF_LOCAL AF_UNIX
+#endif
+
+#define PORTSETTINGS_CHECK 0
+#define PORTSETTINGS_PROVIDE 1
+#define PORTSETTINGS_DISABLE 2
+
+using namespace KIO;
+
+#ifndef SHUT_RDWR
+#define SHUT_RDWR 2
+#endif
+
+extern "C" { KDE_EXPORT int kdemain(int argc, char **argv); }
+
+int kdemain( int argc, char **argv )
+{
+ KInstance instance( "kio_lan" );
+
+ if (argc != 4)
+ {
+ fprintf(stderr, "Usage: kio_lan protocol domain-socket1 domain-socket2\n");
+ exit(-1);
+ }
+ int isLanIoslave=(strcmp("lan",argv[1])==0);
+
+ // Trigger creation to make sure we pick up KIOSK settings correctly.
+ (void)KGlobal::dirs();
+ (void)KGlobal::locale();
+ (void)KGlobal::config();
+
+ kdDebug(7101) << "LAN: kdemain: starting" << endl;
+
+ LANProtocol slave(isLanIoslave, argv[2], argv[3]);
+ slave.dispatchLoop();
+ return 0;
+}
+
+LANProtocol::LANProtocol(int isLanIoslave, const QCString &pool, const QCString &app )
+:TCPSlaveBase(7741,isLanIoslave?"lan":"rlan", pool, app)
+,m_currentHost("")
+,m_port(7741)
+,m_maxAge(15*60)
+,m_isLanIoslave(isLanIoslave?true:false)
+{
+ KConfig *config=KGlobal::config();
+
+ m_protocolInfo[KIOLAN_FTP].enabled=config->readNumEntry("Support_FTP",PORTSETTINGS_CHECK);
+ m_protocolInfo[KIOLAN_HTTP].enabled=config->readNumEntry("Support_HTTP",PORTSETTINGS_CHECK);
+ m_protocolInfo[KIOLAN_NFS].enabled=config->readNumEntry("Support_NFS",PORTSETTINGS_CHECK);
+ m_protocolInfo[KIOLAN_SMB].enabled=config->readNumEntry("Support_SMB",PORTSETTINGS_CHECK);
+ m_protocolInfo[KIOLAN_FISH].enabled=config->readNumEntry("Support_FISH",PORTSETTINGS_CHECK);
+
+ m_defaultLisaHost=config->readEntry("DefaultLisaHost", "localhost");
+ m_shortHostnames=config->readBoolEntry("ShowShortHostnames",false);
+ m_maxAge=config->readNumEntry("MaxAge",15)*60;
+ if (m_maxAge<0) m_maxAge=0;
+
+ strcpy(m_protocolInfo[KIOLAN_NFS].name,"NFS");
+ strcpy(m_protocolInfo[KIOLAN_FTP].name,"FTP");
+ strcpy(m_protocolInfo[KIOLAN_SMB].name,"SMB");
+ strcpy(m_protocolInfo[KIOLAN_HTTP].name,"HTTP");
+ strcpy(m_protocolInfo[KIOLAN_FISH].name,"FISH");
+
+ // Now we check for port 445 for SMB/CIFS also. But we call both entries
+ // SMB. Clients will see only one SMB folder, though, whichever
+ // port (or both) is detected. The smb ioslave should be able
+ // to figure out which port to actually use.
+
+ m_protocolInfo[KIOLAN_NFS].ports.push_back(2049);
+ m_protocolInfo[KIOLAN_FTP].ports.push_back(21);
+ m_protocolInfo[KIOLAN_SMB].ports.push_back(445);
+ m_protocolInfo[KIOLAN_SMB].ports.push_back(139);
+ m_protocolInfo[KIOLAN_HTTP].ports.push_back(80);
+ m_protocolInfo[KIOLAN_FISH].ports.push_back(22);
+
+ m_hostInfoCache.setAutoDelete(true);
+}
+
+LANProtocol::~LANProtocol()
+{
+ m_hostInfoCache.clear();
+}
+
+int LANProtocol::readDataFromServer()
+{
+ if (m_isLanIoslave)
+ return lanReadDataFromServer();
+ else
+ return rlanReadDataFromServer();
+ return 0;
+}
+
+int LANProtocol::lanReadDataFromServer()
+{
+ kdDebug(7101)<<"LANProtocol::lanReadDataFromServer() host: "<<m_currentHost<<" port: "<<m_port<<endl;
+ if (!connectToHost(m_currentHost.latin1(), m_port, false))
+ {
+ error(ERR_SLAVE_DEFINED, i18n("<qt>The Lisa daemon does not appear to be running.<p>"
+ "In order to use the LAN Browser the Lisa daemon must be "
+ "installed and activated by the system administrator."));
+ return 0;
+ }
+ kdDebug(7101)<<"LANProtocol::lanReadDataFromServer() connected"<<endl;
+
+ int receivedBytes(0);
+ char* receiveBuffer(0);
+ char tmpBuf[64*1024];
+ int bytesRead(0);
+ do
+ {
+ fd_set tmpFDs;
+ FD_ZERO(&tmpFDs);
+ FD_SET(m_iSock,&tmpFDs);
+ timeval tv;
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ select(m_iSock+1,&tmpFDs,0,0,&tv);
+ if (FD_ISSET(m_iSock,&tmpFDs))
+ {
+ bytesRead=read(tmpBuf,64*1024);
+ kdDebug(7101)<<"LANProtocol::lanReadDataFromServer: read "<<bytesRead<<" bytes"<<endl;
+
+ if (bytesRead>0)
+ {
+ char *newBuf=new char[receivedBytes+bytesRead];
+ if (receiveBuffer!=0) memcpy(newBuf,receiveBuffer,receivedBytes);
+ memcpy(newBuf+receivedBytes,tmpBuf,bytesRead);
+ receivedBytes+=bytesRead;
+ if (receiveBuffer!=0) delete [] receiveBuffer;
+ receiveBuffer=newBuf;
+ }
+ }
+ } while (bytesRead>0);
+ closeDescriptor();
+ if ((bytesRead<0) || (receivedBytes<4))
+ {
+ delete [] receiveBuffer;
+ error(ERR_INTERNAL_SERVER,i18n("Received unexpected data from %1").arg(m_currentHost));
+ return 0;
+ }
+
+ UDSEntry entry;
+
+ char *currentBuf=receiveBuffer;
+ int bytesLeft=receivedBytes;
+ //this should be large enough for a name
+ char tmpName[4*1024];
+ //this should be large enough for the hostname
+ char tmpHostname[4*1024];
+ while (bytesLeft>0)
+ {
+ int tmpIP=2;
+ tmpName[0]='\0';
+ if ((memchr(currentBuf,0,bytesLeft)==0) || (memchr(currentBuf,int('\n'),bytesLeft)==0))
+ {
+ delete [] receiveBuffer;
+ error(ERR_INTERNAL_SERVER,i18n("Received unexpected data from %1").arg(m_currentHost));
+ return 0;
+ }
+ kdDebug(7101)<<"LANProtocol::lanReadDataFromServer: processing "<<currentBuf;
+ //since we check for 0 and \n with memchr() we can be sure
+ //at this point that tmpBuf is correctly terminated
+ int length=strlen(currentBuf)+1;
+ if (length<(4*1024))
+ sscanf(currentBuf,"%u %s\n",&tmpIP,tmpName);
+ else
+ {
+ kdDebug(7101)<<"LANProtocol::lanReadDataFromServer: buffer overflow attempt detected, aborting"<<endl;
+ break;
+ }
+
+ bytesLeft-=length;
+ currentBuf+=length;
+ if ((bytesLeft==0) && ((tmpIP==0) ||(tmpIP==1)) && (strstr(tmpName,"succeeded")!=0))
+ {
+ kdDebug(7101)<<"LANProtocol::lanReadDataFromServer: succeeded"<<endl;
+ }
+ else if (tmpIP!=2)
+ {
+ kdDebug(7101)<<"LANProtocol::lanReadDataFromServer: listing host: "<<tmpName<<" with ip: "<<tmpIP<<endl;
+ UDSAtom atom;
+
+ atom.m_uds = KIO::UDS_NAME;
+ if (m_shortHostnames)
+ {
+ if (inet_addr(tmpName)!=-1)
+ atom.m_str=tmpName;
+ else
+ {
+ sscanf(tmpName,"%[^.]",tmpHostname);
+ kdDebug(7101)<<"LANProtocol::lanReadDataFromServer: Hostname of " << tmpName << " is " << tmpHostname << "\n";
+ atom.m_str = tmpHostname;
+ }
+ }
+ else
+ atom.m_str = tmpName;
+
+ entry.append( atom );
+ atom.m_uds = KIO::UDS_SIZE;
+ atom.m_long = 1024;
+ entry.append(atom);
+ atom.m_uds = KIO::UDS_ACCESS;
+ atom.m_long = S_IRUSR | S_IRGRP | S_IROTH ;
+ //atom.m_long = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
+ entry.append(atom);
+ atom.m_uds = KIO::UDS_FILE_TYPE;
+ atom.m_long = S_IFDIR; // it is always a directory
+ entry.append( atom );
+ listEntry(entry,false);
+ }
+ }
+
+ listEntry( entry, true ); // ready
+ delete [] receiveBuffer;
+ return 1;
+}
+
+int LANProtocol::rlanReadDataFromServer()
+{
+ kdDebug(7101)<<"RLANProtocol::readDataFromServer"<<endl;
+
+ int sockFD=socket(AF_LOCAL, SOCK_STREAM, 0);
+ sockaddr_un addr;
+ memset((char*)&addr,0,sizeof(addr));
+ addr.sun_family=AF_LOCAL;
+ QCString socketname="/tmp/resLisa-";
+
+ struct passwd *user = getpwuid( getuid() );
+ if ( user )
+ socketname+=user->pw_name;
+ else
+ //should never happen
+ socketname+="???";
+
+ strlcpy(addr.sun_path,socketname,sizeof(addr.sun_path));
+ int result=::connect(sockFD,(sockaddr*)&addr, sizeof(addr));
+
+ kdDebug(7101)<<"readDataFromServer(): result: "<<result<<" name: "<<addr.sun_path<<" socket: "<<sockFD<<endl;
+
+ if (result!=0)
+ {
+ ::close(sockFD);
+ KProcess proc;
+ proc<<"reslisa";
+
+ bool ok=proc.start(KProcess::DontCare);
+ if (!ok)
+ {
+ error( ERR_CANNOT_LAUNCH_PROCESS, "reslisa" );
+ return 0;
+ }
+ //wait a moment
+ //reslisa starts kde-config, then does up to 64
+ //name lookups and then starts to ping
+ //results won't be available before this is done
+ kdDebug(7101)<<"sleeping..."<<endl;
+ ::sleep(1);
+ kdDebug(7101)<<"sleeping again..."<<endl;
+ ::sleep(5);
+ kdDebug(7101)<<"woke up "<<endl;
+ sockFD=socket(AF_LOCAL, SOCK_STREAM, 0);
+
+ memset((char*)&addr,0,sizeof(addr));
+ addr.sun_family=AF_LOCAL;
+ strlcpy(addr.sun_path,socketname,sizeof(addr.sun_path));
+
+ kdDebug(7101)<<"connecting..."<<endl;
+ result=::connect(sockFD,(sockaddr*)&addr, sizeof(addr));
+ kdDebug(7101)<<"readDataFromServer() after starting reslisa: result: "<<result<<" name: "<<addr.sun_path<<" socket: "<<sockFD<<endl;
+ if (result!=0)
+ {
+ error( ERR_CANNOT_OPEN_FOR_READING, socketname );
+ return 0;
+ }
+ kdDebug(7101)<<"succeeded :-)"<<endl;
+ }
+
+ int receivedBytes(0);
+ char* receiveBuffer(0);
+ char tmpBuf[64*1024];
+ int bytesRead(0);
+ do
+ {
+ fd_set tmpFDs;
+ FD_ZERO(&tmpFDs);
+ FD_SET(sockFD,&tmpFDs);
+ timeval tv;
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ select(sockFD+1,&tmpFDs,0,0,&tv);
+ if (FD_ISSET(sockFD,&tmpFDs))
+ {
+ bytesRead=::read(sockFD,tmpBuf,64*1024);
+ kdDebug(7101)<<"RLANProtocol::readDataFromServer: read "<<bytesRead<<" bytes"<<endl;
+
+ if (bytesRead>0)
+ {
+ char *newBuf=new char[receivedBytes+bytesRead];
+ if (receiveBuffer!=0) memcpy(newBuf,receiveBuffer,receivedBytes);
+ memcpy(newBuf+receivedBytes,tmpBuf,bytesRead);
+ receivedBytes+=bytesRead;
+ if (receiveBuffer!=0) delete [] receiveBuffer;
+ receiveBuffer=newBuf;
+ }
+ }
+ } while (bytesRead>0);
+ ::close(sockFD);
+
+
+ if ((bytesRead<0) || (receivedBytes<4))
+ {
+ delete [] receiveBuffer;
+ error(ERR_CANNOT_OPEN_FOR_READING,socketname);
+ return 0;
+ }
+
+ UDSEntry entry;
+
+ char *currentBuf=receiveBuffer;
+ int bytesLeft=receivedBytes;
+ //this should be large enough for a name
+ char tmpName[4*1024];
+ //this should be large enough for the hostname
+ char tmpHostname[4*1024];
+ while (bytesLeft>0)
+ {
+ int tmpIP=2;
+ tmpName[0]='\0';
+ if ((memchr(currentBuf,0,bytesLeft)==0) || (memchr(currentBuf,int('\n'),bytesLeft)==0))
+ {
+ delete [] receiveBuffer;
+ error(ERR_INTERNAL_SERVER,i18n("Received unexpected data from %1").arg(socketname));
+ return 0;
+ }
+ kdDebug(7101)<<"RLANProtocol::readDataFromServer: processing "<<currentBuf;
+ //since we check for 0 and \n with memchr() we can be sure
+ //at this point that tmpBuf is correctly terminated
+ int length=strlen(currentBuf)+1;
+ if (length<(4*1024))
+ sscanf(currentBuf,"%u %s\n",&tmpIP,tmpName);
+ else
+ {
+ kdDebug(7101)<<"RLANProtocol::readDataFromServer: buffer overflow attempt detected, aborting"<<endl;
+ break;
+ }
+
+ bytesLeft-=length;
+ currentBuf+=length;
+ if ((bytesLeft==0) && ((tmpIP==0) ||(tmpIP==1)) && (strstr(tmpName,"succeeded")!=0))
+ {
+ kdDebug(7101)<<"RLANProtocol::readDataFromServer: succeeded"<<endl;
+ }
+ else if (tmpIP!=2)
+ {
+ kdDebug(7101)<<"RLANProtocol::readDataFromServer: listing host: "<<tmpName<<" with ip: "<<tmpIP<<endl;
+ UDSAtom atom;
+
+ atom.m_uds = KIO::UDS_NAME;
+ if (m_shortHostnames)
+ {
+ if (inet_addr(tmpName)!=-1)
+ atom.m_str=tmpName;
+ else
+ {
+ sscanf(tmpName,"%[^.]",tmpHostname);
+ kdDebug(7101)<<"LANProtocol::lanReadDataFromServer: Hostname of " << tmpName << " is " << tmpHostname << "\n";
+ atom.m_str = tmpHostname;
+ }
+ }
+ else
+ atom.m_str = tmpName;
+ entry.append( atom );
+ atom.m_uds = KIO::UDS_SIZE;
+ atom.m_long = 1024;
+ entry.append(atom);
+ atom.m_uds = KIO::UDS_ACCESS;
+ atom.m_long = S_IRUSR | S_IRGRP | S_IROTH ;
+ //atom.m_long = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
+ entry.append(atom);
+ atom.m_uds = KIO::UDS_FILE_TYPE;
+ atom.m_long = S_IFDIR; // it is always a directory
+ entry.append( atom );
+ listEntry(entry,false);
+ }
+ }
+
+ listEntry( entry, true ); // ready
+ delete [] receiveBuffer;
+ return 1;
+}
+
+int LANProtocol::checkHost(const QString& host)
+{
+ kdDebug(7101)<<"LAN::checkHost() "<<host<<endl;
+
+ QString hostUpper=host.upper();
+ HostInfo* hostInfo=m_hostInfoCache[hostUpper];
+ if (hostInfo!=0)
+ {
+ kdDebug(7101)<<"LAN::checkHost() getting from cache"<<endl;
+ //this entry is too old, we delete it !
+ if ((time(0)-hostInfo->created)>m_maxAge)
+ {
+ kdDebug(7101)<<"LAN::checkHost() cache content too old, deleting it"<<endl;
+ m_hostInfoCache.remove(hostUpper);
+ hostInfo=0;
+ }
+ }
+ if (hostInfo==0)
+ {
+ hostInfo=new HostInfo;
+ in_addr ip;
+
+ struct hostent *hp=gethostbyname(host.latin1());
+ if (hp==0)
+ {
+ error( ERR_UNKNOWN_HOST, host.latin1() );
+ delete hostInfo;
+ return 0;
+ }
+ memcpy(&ip, hp->h_addr, sizeof(ip));
+
+ for (int i=0; i<KIOLAN_MAX; i++)
+ {
+ int result(0);
+ if (m_protocolInfo[i].enabled==PORTSETTINGS_DISABLE)
+ result=0;
+ else if (m_protocolInfo[i].enabled==PORTSETTINGS_PROVIDE)
+ result=1;
+ else if (m_protocolInfo[i].enabled==PORTSETTINGS_CHECK)
+ result=checkPort(m_protocolInfo[i].ports,ip);
+
+ //host not reachable
+ if (result==-1)
+ {
+ delete hostInfo;
+ hostInfo=0;
+ error( ERR_UNKNOWN_HOST, host.latin1() );
+ return 0;
+ }
+ hostInfo->services[i]=result;
+ }
+ hostInfo->created=time(0);
+ m_hostInfoCache.insert(hostUpper,hostInfo);
+ }
+ //here hostInfo is always != 0
+ if (hostInfo==0)
+ {
+ error( ERR_INTERNAL, "hostInfo==0" );
+ return 0;
+ }
+
+ UDSEntry entry;
+ for (int i=0; i<KIOLAN_MAX; i++)
+ {
+ if (hostInfo->services[i]==1)
+ {
+ kdDebug(7101)<<"LAN::checkHost(): Host ["<<hostUpper<<"] Service ["<<m_protocolInfo[i].name<<"]"<<endl;
+ UDSAtom atom;
+ // name
+ atom.m_uds = KIO::UDS_NAME;
+ atom.m_str = m_protocolInfo[i].name;
+ entry.append( atom );
+ // size
+ atom.m_uds = KIO::UDS_SIZE;
+ atom.m_long = 1024;
+ entry.append(atom);
+ // access permissions
+ atom.m_uds = KIO::UDS_ACCESS;
+ atom.m_long = S_IRUSR | S_IRGRP | S_IROTH ;
+ //atom.m_long = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
+ entry.append(atom);
+ // file type
+ atom.m_uds = KIO::UDS_FILE_TYPE;
+ if (strcmp(m_protocolInfo[i].name,"HTTP")==0)
+ {
+ // normal file -- if we called stat(2) on this,
+ // this flag would be set in the st_mode field of struct stat
+ atom.m_long=S_IFREG;
+ entry.append(atom);
+
+ // also define the mime-type for this file
+ atom.m_uds = KIO::UDS_MIME_TYPE;
+ atom.m_str="text/html";
+ entry.append( atom );
+ }
+ else
+ {
+ // directory -- if we called stat(2) on this, then this
+ // flag would be set in the st_mode field of the struct stat
+ atom.m_long = S_IFDIR; // it is always a directory
+ entry.append(atom);
+
+ // also set the mime-type
+ atom.m_uds = KIO::UDS_MIME_TYPE;
+ atom.m_str="inode/directory";
+ entry.append( atom );
+ }
+ listEntry(entry,false);
+ }
+ }
+ listEntry( entry, true ); // ready
+ return 1;
+}
+
+// Check if a service is running on a host with IP address 'ip'
+// by checking all the ports in '_ports', using a non-blocking connect.
+// Right now -- assume if *any* of these ports are active,
+// the service is active.
+int LANProtocol::checkPort( QValueVector<int>& _ports, in_addr ip )
+{
+ int _port=0;
+ struct sockaddr_in to_scan;
+
+ to_scan.sin_family = AF_INET;
+ to_scan.sin_addr = ip;
+
+ for (QValueVector<int>::iterator i= _ports.begin(); i != _ports.end(); i++)
+ {
+ _port=(*i);
+ kdDebug(7101)<<"LANProtocol::checkPort: "<<_port<<endl;
+ to_scan.sin_port = htons(_port);
+ // open a TCP socket
+ int mysocket = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (mysocket< 0 )
+ {
+ std::cerr << "LanProt::checkPort: Error while opening Socket" << std::endl;
+ ::close( mysocket );
+ return 0;
+ }
+ //make the socket non blocking
+ long int options = O_NONBLOCK | ::fcntl(mysocket, F_GETFL);
+ if (::fcntl( mysocket, F_SETFL, options )!=0)
+ {
+ std::cerr << "LanProt::checkPort: Error making it nonblocking"<< std::endl;
+ ::close( mysocket );
+ return 0;
+ }
+ int result=connect( mysocket, (struct sockaddr *) &to_scan, sizeof( to_scan ));
+ //it succeeded immediately
+ if (result==0)
+ {
+ std::cerr<<"LANProtocol::checkPort("<<_port<<") connect succeeded immediately"<<std::endl;
+ ::shutdown( mysocket, SHUT_RDWR );
+ return 1;
+ }
+ //it failed
+ if ((result<0) && (errno!=EINPROGRESS))
+ {
+ // errno was not EINPROGRESS, so there is some serious problem
+ ::shutdown( mysocket, SHUT_RDWR );
+ // maybe some other port will work
+ continue;
+ }
+ // last errno was EINPROGRESS, so we should select() on socket
+ // and wait for the final verdict
+ timeval tv;
+ tv.tv_sec=5;
+ tv.tv_usec=0;
+ fd_set rSet, wSet;
+ FD_ZERO(&rSet);
+ FD_SET(mysocket,&rSet);
+ wSet=rSet;
+ //timeout or error
+ result=select(mysocket+1,&rSet,&wSet,0,&tv);
+ ::shutdown( mysocket, SHUT_RDWR );
+ if (result==1)
+ return 1;
+ }
+ // gosh, no port worked
+ return 0;
+
+}
+
+void LANProtocol::setHost( const QString& host, int port, const QString& , const QString& )
+{
+ if (m_isLanIoslave)
+ {
+ m_currentHost=host;
+ if (port==0)
+ m_port=7741;
+ else
+ m_port=port;
+ kdDebug(7101)<<"LANProtocol::setHost: "<<m_currentHost<<endl;
+ }
+ else
+ {
+ if (!host.isEmpty())
+ error(ERR_MALFORMED_URL,i18n("No hosts allowed in rlan:/ URL"));
+ }
+}
+
+void LANProtocol::mimetype( const KURL& url)
+{
+ kdDebug(7101)<<"LANProtocol::mimetype -"<<url.prettyURL()<<"-"<<endl;
+ QString path( QFile::encodeName(url.path()));
+ QStringList pathList=QStringList::split( "/",path);
+ if ((pathList.count()==2) && (pathList[1].upper()=="HTTP"))
+ {
+ //kdDebug(7101)<<"LANProtocol::mimeType text/html"<<endl;
+ mimeType("text/html");
+ }
+ else
+ {
+ mimeType("inode/directory");
+ //kdDebug(7101)<<"LANProtocol::mimeType inode/directory"<<endl;
+ }
+ finished();
+}
+
+void LANProtocol::listDir( const KURL& _url)
+{
+ KURL url(_url);
+ QString path( QFile::encodeName(url.path()));
+ if (path.isEmpty())
+ {
+ url.setPath("/");
+ redirection(url);
+ finished();
+ return;
+ }
+ if ((m_currentHost.isEmpty()) && (m_isLanIoslave))
+ {
+ url.setHost(m_defaultLisaHost);
+ redirection(url);
+ finished();
+ return;
+ }
+ kdDebug(7101)<<"LANProtocol::listDir: host: "<<m_currentHost<<" port: "<<m_port<<" path: "<<path<<endl;
+ QStringList pathList=QStringList::split("/", path);
+ kdDebug(7101)<<"parts are: "<<endl;
+ for (QStringList::Iterator it=pathList.begin(); it !=pathList.end(); it++)
+ kdDebug(7101)<<"-"<<(*it)<<"-"<<endl;
+ if (pathList.count()>2)
+ {
+ kdDebug(7101)<<"LANProtocol::listDir: too deep path: "<<pathList.count()<<endl;
+ error(ERR_DOES_NOT_EXIST,_url.prettyURL());
+ return;
+ }
+ int succeeded(0);
+ if (path=="/")
+ {
+ //get the stuff from the netland server
+ succeeded=readDataFromServer();
+ }
+ else if (pathList.count()==1)
+ {
+ //check the ports and stuff
+ succeeded=checkHost(pathList[0]);
+ }
+ else
+ {
+ kdDebug(7101)<<"LANProtocol::listDir: trying to redirect"<<endl;
+ int isSupportedProtocol(0);
+ for (int i=0; i<KIOLAN_MAX; i++)
+ {
+ if (pathList[1].upper()==m_protocolInfo[i].name)
+ {
+ isSupportedProtocol=m_protocolInfo[i].enabled;
+ break;
+ }
+ }
+ if (isSupportedProtocol==PORTSETTINGS_DISABLE)
+ {
+ kdDebug(7101)<<"LANProtocol::listDir: protocol not enabled "<<endl;
+ error(ERR_DOES_NOT_EXIST,_url.prettyURL());
+ return;
+ }
+ //redirect it
+ KURL newUrl(pathList[1]+"://"+pathList[0]);
+ redirection(newUrl);
+ succeeded=1;
+ }
+ if (succeeded) finished();
+}
+
+void LANProtocol::stat( const KURL & url)
+{
+ kdDebug(7101)<<"LANProtocol::stat: "<<endl;
+ UDSEntry entry;
+ UDSAtom atom;
+
+ atom.m_uds = KIO::UDS_NAME;
+ atom.m_str = url.path();
+ entry.append( atom );
+ atom.m_uds = KIO::UDS_SIZE;
+ atom.m_long = 1024;
+ entry.append(atom);
+
+ atom.m_uds = KIO::UDS_ACCESS;
+ atom.m_long = S_IRUSR | S_IRGRP | S_IROTH ;
+ //atom.m_long = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
+ entry.append(atom);
+
+
+ QString path( QFile::encodeName(url.path()));
+ QStringList pathList=QStringList::split( "/",path);
+ if ((pathList.count()==2) && (pathList[1].upper()=="HTTP"))
+ {
+ atom.m_uds = KIO::UDS_FILE_TYPE;
+ atom.m_long=S_IFREG;
+ entry.append(atom);
+ atom.m_uds = KIO::UDS_MIME_TYPE;
+ atom.m_str="text/html";
+ //kdDebug(7101)<<"LANProtocol::stat: http is reg file"<<endl;
+ entry.append( atom );
+ }
+ else
+ {
+ atom.m_uds = KIO::UDS_FILE_TYPE;
+ atom.m_long = S_IFDIR; // it is always a directory
+ entry.append(atom);
+ atom.m_uds = KIO::UDS_MIME_TYPE;
+ atom.m_str="inode/directory";
+ //kdDebug(7101)<<"LANProtocol::stat: is dir"<<endl;
+ entry.append( atom );
+ }
+
+ statEntry( entry );
+ finished();
+}
+
+void LANProtocol::get(const KURL& url )
+{
+ QString path(QFile::encodeName(url.path()));
+
+ kdDebug(7101)<<"LANProtocol::get: "<<path<<endl;
+ QStringList pathList=QStringList::split("/", path);
+ kdDebug(7101)<<"parts are: "<<endl;
+ for (QStringList::Iterator it=pathList.begin(); it !=pathList.end(); it++)
+ kdDebug(7101)<<"-"<<(*it)<<"-"<<endl;
+ if ((pathList.count()!=2) || (pathList[1].upper()!="HTTP"))
+ {
+ kdDebug(7101)<<"LANProtocol::get: invalid url: "<<pathList.count()<<endl;
+ error(ERR_DOES_NOT_EXIST,url.prettyURL());
+ return;
+ }
+ KURL newUrl("http://"+pathList[0]);
+ redirection(newUrl);
+ finished();
+ return;
+}
diff --git a/lanbrowsing/kio_lan/kio_lan.h b/lanbrowsing/kio_lan/kio_lan.h
new file mode 100644
index 00000000..26bff398
--- /dev/null
+++ b/lanbrowsing/kio_lan/kio_lan.h
@@ -0,0 +1,87 @@
+/* This file is part of the KDE project
+ Copyright (C) 2000 Alexander Neundorf <neundorf@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ 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., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+#ifndef KIO_XLAN_H
+#define KIO_XLAN_H
+
+#include <kio/slavebase.h>
+#include <kio/tcpslavebase.h>
+#include <kio/global.h>
+
+#include <qvaluevector.h>
+#include <qcstring.h>
+#include <qstring.h>
+#include <qdict.h>
+
+#include <arpa/inet.h>
+#include <sys/types.h>
+
+#define KIOLAN_HTTP 0
+#define KIOLAN_FTP 1
+#define KIOLAN_SMB 2
+#define KIOLAN_NFS 3
+#define KIOLAN_FISH 4
+#define KIOLAN_MAX 5
+
+#define NAMELEN 8
+
+struct MyProtocolInfo
+{
+ int enabled;
+ QValueVector<int> ports;
+ //this should be large enough for things like "FTP" and so on
+ char name[NAMELEN];
+};
+
+struct HostInfo
+{
+ time_t created;
+ int services[KIOLAN_MAX];
+};
+
+class LANProtocol : public KIO::TCPSlaveBase
+{
+ public:
+ LANProtocol (int isLanIoSlave, const QCString &pool, const QCString &app );
+ virtual ~LANProtocol();
+
+ virtual void setHost( const QString& host, int port, const QString& user, const QString& pass );
+ virtual void mimetype( const KURL& );
+
+ virtual void listDir( const KURL& url);
+ virtual void stat( const KURL & url);
+ virtual void get( const KURL& url );
+
+ protected:
+ QDict<HostInfo> m_hostInfoCache;
+ int readDataFromServer();
+ int lanReadDataFromServer();
+ int rlanReadDataFromServer();
+ int checkHost(const QString& host);
+ int checkPort(QValueVector<int>& _ports, in_addr ip);
+ QString m_currentHost;
+ unsigned short int m_port;
+ MyProtocolInfo m_protocolInfo[KIOLAN_MAX];
+ int m_maxAge;
+ bool m_isLanIoslave;
+ bool m_shortHostnames;
+ QString m_defaultLisaHost;
+};
+
+#endif
diff --git a/lanbrowsing/kio_lan/lan.desktop b/lanbrowsing/kio_lan/lan.desktop
new file mode 100644
index 00000000..cb4716db
--- /dev/null
+++ b/lanbrowsing/kio_lan/lan.desktop
@@ -0,0 +1,81 @@
+[Desktop Entry]
+Type=Link
+DocPath=lisa/index.html
+URL=lan:/
+Icon=network_local
+Name=Local Network
+Name[af]=Plaaslike Netwerk
+Name[ar]=الشبكة المحلية
+Name[az]=Yerli Şəbəkə
+Name[be]=Мясцовая сетка
+Name[bg]=Локална мрежа
+Name[bn]=স্থানীয় নেটওয়ার্ক
+Name[br]=Rouedad lec'hel
+Name[bs]=Lokalna mreža
+Name[ca]=Xarxa local
+Name[cs]=Lokální síť
+Name[cy]=Rhwydwaith Lleol
+Name[da]=Lokalt netværk
+Name[de]=Lokales Netzwerk
+Name[el]=Τοπικό δίκτυο
+Name[eo]=Loka reto
+Name[es]=Red local
+Name[et]=Kohalik võrk
+Name[eu]=Sare lokala
+Name[fa]=شبکۀ محلی
+Name[fi]=Paikallisverkko
+Name[fr]=Réseau local
+Name[ga]=Gréasán Logánta
+Name[gl]=Rede Local
+Name[he]=רשת מקומית
+Name[hi]=स्थानीय नेटवर्क
+Name[hr]=Lokalna mreža
+Name[hu]=Helyi hálózat
+Name[id]=Jaringan lokal
+Name[is]=Staðarnet
+Name[it]=Rete locale
+Name[ja]=ローカルネットワーク
+Name[ka]=ლოკალური ქსელი
+Name[kk]=Жергілікті желі
+Name[km]=បណ្ដាញ​មូលដ្ឋាន
+Name[ko]=지역 네트워크
+Name[lt]=Vietinis tinklas
+Name[lv]=Lokālais Tīkls
+Name[mk]=Локална мрежа
+Name[mn]=Дотоод сүлжээ
+Name[ms]=Jaringan Setempat
+Name[mt]=Network Lokali
+Name[nb]=Lokalt nettverk
+Name[nds]=Lokaal Nettwark
+Name[ne]=स्थानीय सञ्जाल
+Name[nl]=Lokaal netwerk
+Name[nn]=Lokalt nettverk
+Name[nso]=Kgokagano Selegae
+Name[pa]=ਲੋਕਲ ਨੈੱਟਵਰਕ
+Name[pl]=Sieć lokalna
+Name[pt]=Rede Local
+Name[pt_BR]=Rede local
+Name[ro]=Reţea locală
+Name[ru]=Локальная сеть
+Name[se]=Báikkálaš fierpmádat
+Name[sk]=Lokálna sieť
+Name[sl]=Krajevno omrežje
+Name[sr]=Локална мрежа
+Name[sr@Latn]=Lokalna mreža
+Name[sv]=Lokalt nätverk
+Name[ta]=உள்ளக பிணையம்
+Name[tg]=Шабакаи Маҳаллӣ
+Name[th]=เครือข่ายท้องถิ่น
+Name[tr]=Yerel Ağ
+Name[uk]=Локальна мережа
+Name[uz]=Lokal tarmoq
+Name[uz@cyrillic]=Локал тармоқ
+Name[ven]=Vhukwamani ha tsini
+Name[wa]=Rantoele locåle
+Name[xh]=Umsebenzi womnatha Wobulali
+Name[zh_CN]=局域网
+Name[zh_HK]=區域網絡
+Name[zh_TW]=區域網路
+Name[zu]=Oluseduze Uxhumaniso olusakazekile
+Open=false
+X-KDE-TreeModule=Directory
diff --git a/lanbrowsing/kio_lan/lan.protocol b/lanbrowsing/kio_lan/lan.protocol
new file mode 100644
index 00000000..ba72a216
--- /dev/null
+++ b/lanbrowsing/kio_lan/lan.protocol
@@ -0,0 +1,15 @@
+[Protocol]
+exec=kio_lan
+protocol=lan
+input=none
+output=filesystem
+listing=Name,Type
+reading=true
+writing=false
+makedir=false
+deleting=false
+linking=false
+moving=false
+DocPath=kioslave/lan.html
+Icon=network_local
+Class=:local
diff --git a/lanbrowsing/kio_lan/lisa.desktop b/lanbrowsing/kio_lan/lisa.desktop
new file mode 100644
index 00000000..207ee3e5
--- /dev/null
+++ b/lanbrowsing/kio_lan/lisa.desktop
@@ -0,0 +1,66 @@
+[Desktop Entry]
+Type=Link
+URL=lan:/
+Icon=network
+Name=LAN Browser
+Name[be]=Аглядальнік мясцовай сеткі
+Name[bg]=Браузър на локалната мрежа
+Name[bn]=ল্যান ব্রাউজার
+Name[br]=Furcher LAN
+Name[bs]=LAN preglednik
+Name[ca]=Navegador LAN
+Name[cs]=Prohlížení lokální sítě
+Name[da]=LAN-søger
+Name[de]=LAN durchsuchen
+Name[el]=Περιηγητής LAN
+Name[eo]=Rigardilo por loka reto
+Name[es]=Navegador de red
+Name[et]=Kohtvõrgu sirvija
+Name[eu]=LAN arakatzailea
+Name[fa]=مرورگر شبکۀ داخلی
+Name[fi]=Lähiverkon selain
+Name[fr]=Navigateur réseau
+Name[ga]=Brabhsálaí an Ghréasáin Logánta
+Name[gl]=Explorador LAN
+Name[he]=LAN דפדפן
+Name[hr]=Preglednik LAN-a
+Name[hu]=Hálózatböngésző
+Name[is]=Netflakkari
+Name[it]=Navigazione della rete locale
+Name[ja]=LAN ブラウザ
+Name[ka]=LAN ბროუზერი
+Name[kk]=LAN шолғышы
+Name[km]=កម្មវិធី​រុករក​បណ្ដាញ​មូលដ្ឋាន
+Name[lt]=Vietinio tinklo naršyklė
+Name[lv]=LAN Pārlūks
+Name[mk]=Прегледувач на LAN
+Name[nb]=LAN-los
+Name[nds]=Nettwark-Kieker
+Name[ne]=LAN ब्राउजर
+Name[nn]=LAN-lesar
+Name[pa]=LAN ਝਲਕਾਰਾ
+Name[pl]=Przeglądarka sieci lokalnej
+Name[pt]=Navegador de Rede
+Name[pt_BR]=Navegador LAN
+Name[ru]=Проводник LAN
+Name[se]=LAN-bláđđejeaddji
+Name[sk]=Prehliadač siete
+Name[sl]=Brskalnik po krajevnem omrežju
+Name[sr]=Претраживач LAN-а
+Name[sr@Latn]=Pretraživač LAN-a
+Name[sv]=Bläddrare i lokalt nätverk
+Name[ta]=LAN உலாவி
+Name[tg]=Барраси Шабакаи Маҳаллӣ
+Name[th]=การเรียกดูระบบแลน
+Name[tr]=LAN Tarayıcı
+Name[uk]=Навігатор ЛОМ
+Name[ven]=Buronza ya LAN
+Name[xh]=Umkhangeli zincwadi we LAN
+Name[zh_CN]=局域网浏览器
+Name[zh_HK]=區域網絡瀏覽器
+Name[zh_TW]=LAN 瀏覽器
+Name[zu]=Umbheki zincwadi ze LAN
+Open=false
+X-KDE-TreeModule=Directory
+X-KDE-KonqSidebarModule=konqsidebar_tree
+X-KDE-ConfiguredURL=kio_lanrc:noGroup:sidebarURL
diff --git a/lanbrowsing/kio_lan/rlan.protocol b/lanbrowsing/kio_lan/rlan.protocol
new file mode 100644
index 00000000..de2c0ad4
--- /dev/null
+++ b/lanbrowsing/kio_lan/rlan.protocol
@@ -0,0 +1,15 @@
+[Protocol]
+exec=kio_lan
+protocol=rlan
+input=none
+output=filesystem
+listing=Name,Type
+reading=true
+writing=false
+makedir=false
+deleting=false
+linking=false
+moving=false
+DocPath=kioslave/rlan.html
+Icon=network_local
+Class=:local
diff --git a/lanbrowsing/lisa/AUTHORS b/lanbrowsing/lisa/AUTHORS
new file mode 100644
index 00000000..d13cadc9
--- /dev/null
+++ b/lanbrowsing/lisa/AUTHORS
@@ -0,0 +1,2 @@
+Written and maintained by
+ Alexander Neundorf <neundorf@kde.org>
diff --git a/lanbrowsing/lisa/COPYING b/lanbrowsing/lisa/COPYING
new file mode 100644
index 00000000..ded002ea
--- /dev/null
+++ b/lanbrowsing/lisa/COPYING
@@ -0,0 +1,347 @@
+NOTE! The GPL below is copyrighted by the Free Software Foundation, but
+the instance of code that it refers to (the kde programs) are copyrighted
+by the authors who actually wrote it.
+
+---------------------------------------------------------------------------
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/lanbrowsing/lisa/ChangeLog b/lanbrowsing/lisa/ChangeLog
new file mode 100644
index 00000000..7d0ef7e8
--- /dev/null
+++ b/lanbrowsing/lisa/ChangeLog
@@ -0,0 +1,8 @@
+0.1.3
+-security fixes: fixed LOGNAME vulnerabilty and another possible buffer overflow
+
+Version 0.1.2
+-various fixes and improvements...
+
+Version 0.1
+-initial version
diff --git a/lanbrowsing/lisa/INSTALL b/lanbrowsing/lisa/INSTALL
new file mode 100644
index 00000000..f8bad0c1
--- /dev/null
+++ b/lanbrowsing/lisa/INSTALL
@@ -0,0 +1,176 @@
+Basic Installation
+==================
+
+ These are generic installation instructions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, a file
+`config.cache' that saves the results of its tests to speed up
+reconfiguring, and a file `config.log' containing compiler output
+(useful mainly for debugging `configure').
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If at some point `config.cache'
+contains results you don't want to keep, you may remove or edit it.
+
+ The file `configure.in' is used to create `configure' by a program
+called `autoconf'. You only need `configure.in' if you want to change
+it or regenerate `configure' using a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system. If you're
+ using `csh' on an old version of System V, you might need to type
+ `sh ./configure' instead to prevent `csh' from trying to execute
+ `configure' itself.
+
+ Running `configure' takes a while. While running, it prints some
+ messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. You can give `configure'
+initial values for variables by setting them in the environment. Using
+a Bourne-compatible shell, you can do that on the command line like
+this:
+ CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
+
+Or on systems that have the `env' program, you can do it like this:
+ env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ If you have to use a `make' that does not supports the `VPATH'
+variable, you have to compile the package for one architecture at a time
+in the source code directory. After you have installed the package for
+one architecture, use `make distclean' before reconfiguring for another
+architecture.
+
+Installation Names
+==================
+
+ By default, `make install' will install the package's files in
+`/usr/local/kde/bin', `/usr/local/kde/lib', etc. You can specify an
+installation prefix other than `/usr/local/kde' by giving `configure'
+the option `--prefix=PATH'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+give `configure' the option `--exec-prefix=PATH', the package will use
+PATH as the prefix for installing programs and libraries.
+Documentation and other data files will still use the regular prefix.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+ There may be some features `configure' can not figure out
+automatically, but needs to determine by the type of host the package
+will run on. Usually `configure' can figure that out, but if it prints
+a message saying it can not guess the host type, give it the
+`--host=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name with three fields:
+ CPU-COMPANY-SYSTEM
+
+See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the host type.
+
+ If you are building compiler tools for cross-compiling, you can also
+use the `--target=TYPE' option to select the type of system they will
+produce code for and the `--build=TYPE' option to select the type of
+system on which you are compiling the package.
+
+Sharing Defaults
+================
+
+ If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Operation Controls
+==================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--cache-file=FILE'
+ Use and save the results of the tests in FILE instead of
+ `./config.cache'. Set FILE to `/dev/null' to disable caching, for
+ debugging `configure'.
+
+`--help'
+ Print a summary of the options to `configure', and exit.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made.
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`--version'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`configure' also accepts some other, not widely useful, options.
+
diff --git a/lanbrowsing/lisa/Makefile.am b/lanbrowsing/lisa/Makefile.am
new file mode 100644
index 00000000..ff1f8433
--- /dev/null
+++ b/lanbrowsing/lisa/Makefile.am
@@ -0,0 +1,41 @@
+##
+AM_CXXFALGS = -fno-rtti -fno-exceptions
+
+#CXXFLAGS = -fno-rtti -fno-exceptions
+
+bin_PROGRAMS = lisa reslisa
+#
+# Programs to compile, Manpages to install and Versions
+#
+#INCLUDES = $(all_includes)
+
+lisa_SOURCES = \
+addressvalidator.cpp \
+netmanager.cpp \
+netscanner.cpp \
+ipaddress.cpp \
+main.cpp \
+mystring.cpp \
+client.cpp \
+configfile.cpp
+
+reslisa_SOURCES = \
+addressvalidator.cpp \
+netmanager.cpp \
+netscanner.cpp \
+ipaddress.cpp \
+strictmain.cpp \
+mystring.cpp \
+client.cpp \
+configfile.cpp
+
+lisa_LDADD = $(LIBSOCKET)
+lisa_LDFLAGS = $(KDE_EXTRA_RPATH)
+
+reslisa_LDADD = $(LIBSOCKET)
+reslisa_LDFLAGS = $(KDE_EXTRA_RPATH)
+
+misc_DATA = README
+miscdir = $(kde_datadir)/lisa
+EXTRA_DIST=$(misc_DATA)
+
diff --git a/lanbrowsing/lisa/NEWS b/lanbrowsing/lisa/NEWS
new file mode 100644
index 00000000..898a3dab
--- /dev/null
+++ b/lanbrowsing/lisa/NEWS
@@ -0,0 +1 @@
+See ChangeLog.
diff --git a/lanbrowsing/lisa/README b/lanbrowsing/lisa/README
new file mode 100644
index 00000000..c6d5d1bd
--- /dev/null
+++ b/lanbrowsing/lisa/README
@@ -0,0 +1,419 @@
+This is the readme to the Lan Information Server LISa and the Restricted LAN
+Information Server resLISa.
+
++---------------+
+| LISa |
++---------------+
+
+LISa is intended to provide a kind of "network neighbourhood" but only
+relying on the TCP/IP protocol stack, no smb or whatever.
+It is completely independent from KDE/Qt.
+The list of running hosts is provided via TCP port 7741.
+
+LISa supports two ways of finding hosts:
+
+1. you give LISa a range of of IP-addresses, then LISa will send
+ICMP echo requests to all given IP addresses and wait for the answers
+
+2. you can say LISa to execute "nmblookup "*" ", i.e. the command line tool
+nmblookup must be installed, it is part of the samba package.
+nmblookup "*" sends a broadcast to the attached networks and all hosts
+running smb-services will answer this broadcast
+
+lisa and reslisa are distributed under the GNU General Public License.
+
+
+
+How it works
+-------------
+
+In the configuration file you provide a range of IP-addresses which
+LISa should check, wether they are running. In the most simple case
+this could be your network address/subnetmask, then LISa would
+check every possible host of your network wether it is running.
+The hosts are checked using ICMP echo requests. To be able to send and receive
+ICMP echo requests and replies the program has to open a so-called
+"raw socket". Therefor it needs root privileges. This socket is opened
+right after the start of the program, after successfully opening the socket
+root privileges are dropped immediately (see main.cpp and strictmain.cpp).
+If you configure LISa this way, that it also uses nmblookup, it will
+popen("nmblookup \"*\"") and then parse the results.
+
+Since the ICMP requests and the broadcasts can cause some network traffic
+if there are more than one such server running in one network, the servers
+cooperate with each other. Before they start pinging (or nmblookup),
+they send a broadcast on port 7741.
+If somebody answers this broadcast, they will retrieve the complete list
+of running hosts via TCP port 7741 from this host and will not start to
+ping (or nmblookup) theirselves. If nobody answers, the host which sent
+the broadcast will start pinging the hosts (or nmblookup) and then open a
+socket which listens for the mentioned broadcasts. If the host received an
+answer to his broadcast, it won't have the socket for listening to the
+broadcasts open. So usually exactly one of the servers will have this
+socket open and only this one will actually ping (or nmblookup) the hosts.
+In other words, the servers are lazy, they work like "I will only do something
+if nobody else can do it for me".
+
+There is another feature which reduces the network load. Let's say you configured LISa
+to update all 10 minutes. Now you don't access your server very often.
+If nobody accesses the server for the last update period, the server will
+update (either itself or from the one which actually does the work) and then
+double its update period, i.e. the next update will happen after 20 minutes.
+This will happen 4 times, so if nobody accesses the server with update period
+10 minutes for a long time, its update interval will increase up to
+160 minutes, almost three hours. If then somebody accesses the data from the
+server, he will get an old list ( up to 160 minutes old). With accessing
+the server will reset its update interval to its initial value,
+i.e. 10 minutes and immediately start updating if the last update is more
+than these 10 minutes over. This means if you get a very old list, you can try
+some seconds later again and you should get a current version.
+This will have fast effect for the servers, which don't ping (or nmblookup)
+theirselves, since only one user usually accesses them, and it will have
+less effect for the server which does the pinging (or nmblookup), since
+this server is accessed from all other servers in the network.
+
+
+This way it is possible that many hosts in a network run this server, but
+the net load will remain low. For the user it is not necessary to know
+wether there is a server (i.e. a name server or fileserver or whatever)
+in the network which also runs LISa. He can always run LISa locally
+and LISa will detect if there is one, transparently to the user.
+The first client for LISa is an ioslave for KDE2, so the user
+can enter there lan://localhost/ or lan:/, which will both
+contact LISa on the own system.
+If there is a machine which runs all the time and the user knows
+that this machine also runs LISa, he can use his LISa client directly with
+this server (would be with the mentioned ioslave lan://the_server_name/).
+
+If you don't want that your LISa takes part in the broadcasting, but always
+does the pinging itself, make it use another port with the
+command line option --port or -p.
+This is not recommended !
+
+If you send SIGHUP to LISa, it will reread its configfile.
+If you send SIGUSR1 to LISa, it will print some status information to stdout.
+
+The data provided over the socket has a simple format:
+
+<decimal ip address in network byte order><one space 0x20><full name of the host><a terminating '\0'><newline '\n'>
+and the last line
+0 succeeded<'\n'>
+
+e.g.
+
+"17302538 some_host.whatever.de
+18285834 linux.whatever.de
+17827082 nameserver.whatever.de
+0 succeeded
+"
+
+This should make it easy parseable.
+
+If there are very strict security rules in your network, some people
+might consider the pinging a potential attack. If you
+have problems with this, try the restricted version, resLISa.
+
++------------------+
+| resLISa |
++------------------+
+
+If you hav very strict security rules in your network or you don't want to
+have another port open or whatever, you can use resLISa.
+
+With resLISa you can't ping whole networks and address ranges, you can give
+resLISa up to currently 64 hosts by their names in its config file. These
+will be pinged. You are still able to use nmblookup.
+resLISa will also only provide the information over a unix domain socket, i.e.
+not over the network. The name of the socket is "/tmp/resLisa-YourLoginname",
+so resLISa can be safely run by more users on one machine.
+Since it should also not produce a security risk of any kind it is
+safe to install reslisa setuid root. root privileges will be dropped
+right after startup (see strictmain.cpp), they are only needed to create a raw socket
+for sending the ICMP echo requests..
+It will also not send or receive broadcasts.
+The first client for this is also an ioslave for KDE2 (makes rlan:/ in e.g. konqy).
+
+
+
+Configuration
+-------------
+
+Now an example config file:
+
+PingAddresses = 192.168.100.0/255.255.255.0;192.168.100.10-192.168.199.19;192.168.200.1;192-192.168-168.100-199.0-9;
+PingNames = bb_mail;
+AllowedAddresses = 192.168.0.0/255.255.0.0
+BroadcastNetwork = 192.168.100.0/255.255.255.0
+SearchUsingNmblookup = 1 #also try nmblookup
+FirstWait = 30 #30 hundredth seconds
+SecondWait = -1 #only one try
+#SecondWait = 60 #try twice, and the second time wait 0.6 seconds
+UpdatePeriod = 300 #update after 300 secs
+DeliverUnnamedHosts = 0 #don't publish hosts without name
+MaxPingsAtOnce = 256 #send up to 256 ICMP echo requests at once
+
+
+PingAddresses
+
+This is probably the most important entry.
+Here you say which addresses will be pinged. You can specify multiple
+ranges, they are divided by semicolons.
+
+There are four possible ways to define addresses:
+-net address/network mask: 192.168.100.0/255.255.255.0, i.e. an IP address
+ and the assigned network mask. This doesn't have the real network address
+ and netmask of your machine, it can be less. E.g. if you have
+ 10.0.0.0/255.0.0.0, you could specify 10.1.2.0/255.255.255.0 if you are only
+ interested in these addresses. The combination IP address-network mask
+ must be divided by a slash "/" and the address does not have to be a real
+ network address, it can also be a host address of the desired network,
+ i.e. 10.12.34.67/255.0.0.0 is the same as 10.0.0.0/255.0.0.0 .
+
+-a range of following IP addresses: 192.168.100.10-192.168.199.19, i.e.
+ an IP-address where pinging will start and an IP-address where pinging will end.
+ Both addresses must be divided by a "-".
+ In this example this would produce 199-100+1=100, 100*256=25.600,
+ 25.600+(19-10+1)=25.590 addresses
+
+-an IP-address can be presented by its four decimal numbers, you can specify
+ ranges four each of these four numbers: 192-192.169-171.100-199.0-9
+ In this example all IP addresses with first number 192, second number from
+ 168 to 168, third number from 100 up to 199 and last number from 0 up
+ to 9 will be pinged. This would give 1*1*100*10=1.000 addresses.
+ This is probably only useful in very seldom cases.
+ Here you have to provide ranges for every four numbers, always divided
+ by "-".
+
+-single IP-addresses: 192.168.200.1
+ well, single IP addresses or host names
+
+It is also valid to leave this entry empty.
+
+
+PingNames
+ here you can additionally specify hosts to ping using their names.
+ The names have to be divided by semicolons.
+
+It is also valid to leave this entry empty.
+
+
+AllowedAddresses
+
+ This is also very important. LISa will only ping addresses,
+ accept clients and answer broadcasts from addresses, which are covered by the
+ addresses given in this line. You can add up to 32 network addresses/network masks
+ or single addresses. Divide them by ; and don't put empty space between the
+ addresses !
+ Example: 192.168.0.0/255.255.0.0;192.169.0.0
+ -> a complete network and a single address are valid
+ Always make this as strict as possible, usually
+ your network address/subnetmask is a good choice.
+
+
+BroadcastNetwork
+
+ This entry contains exactly one network address/subnet mask.
+ To this network broadcasts will be sent. Usually this should be your
+ own network address/subnetmask.
+ Example: 192.168.0.0/255.255.0.0
+
+
+SearchUsingNmblookup
+
+ Here you can give 0 or 1.
+ 1 means that LISa will execute "nmblookup "*" " and parse the output
+ from this command. This produces less network traffic than the pinging,
+ but you will only get hosts which have a smb-service running (Windows
+ machines or machines running samba).
+ If you enable this option and also give IP addresses to ping, then nmblookup
+ will be executed first and then the pinging will start.
+ Then only addresses will be pinged, which were not already delivered
+ from nmblookup. This should slightly decrease the network load.
+
+
+FirstWait
+
+ If LISa pings, i.e. if it sends the ICMP echo requests, it sends a bunch
+ of requests at once, and the it will wait for the number of hundredth seconds
+ you specify here. Usually values from 5 to 50 should be good, the maximum
+ is 99 (gives 0.99 seconds, a very long time).
+ Try to make this value as small as possible while still finding all
+ running hosts.
+
+
+SecondWait
+
+ After LISa sent the echo requests the first time, it can be possible
+ that some hosts were not found. To improve the results, LISa can ping a
+ second time. This time it will only ping hosts, from which it didn't receive
+ answers. If you have good results with pinging only once, you can disable
+ the second time with setting SecondWait to -1.
+ Otherwise it might be a good idea to make this value a little bit bigger
+ than the value for FirstWait, since the hosts which were not found
+ on the first try, are probably slower or further away so they might take
+ some milliseconds longer to answer.
+ Usually values from 5 to 50 should be good or -1 to disable the second scan.
+ The maximum is 99 (gives 0.99 seconds, a very long time).
+
+
+UpdatePeriod
+
+ This is the interval after which LISa will update, i.e. ping or nmblookup
+ or get the list of hosts from the LISa server which actually does the pinging.
+ Valid values are between 30 seconds and 1800 seconds (half an hour).
+ If you have a big network, don't make the interval to small (to keep
+ network load low). Values from 300 to 900 seconds (5 to 15 minutes) might be
+ a good idea. Keep in mind that the update period is doubled
+ if nobody accesses the server, up to 4 times, so the interval will become
+ 16 times the value given here and will be reseted to the value given here
+ if somebody accesses the server.
+
+
+DeliverUnnamedHosts
+
+ If an answer to an echo request from an IP address was received, were LISa
+ could not determine a name, it will be only delivered over the port
+ if you set this to 1.
+ I am not really sure if this is a useful feature, but maybe
+ there are some infrastructure devices in your network without assigned names,
+ so they don't have to be published. Set this to 0 if you want to keep them
+ secret ;-)
+ If unsure, say 0.
+
+MaxPingsAtOnce
+
+ When sending the pings (echo requests), LISa sends a bunch of these at once
+ and then waits for the answers. By default there are 256 pings sent at once,
+ usually you should not need the change this value. If you make it much bigger,
+ the internal receive buffers for the answers to the echo requests may become to small,
+ if you make it to small, the updating will be slower.
+
+
+Three different example config files:
+
+You are member of a small network with 24 bit network mask, i.e.
+up to 256 hosts:
+
+PingAddresses = 192.168.100.0/255.255.255.0
+AllowedAddresses = 192.168.100.0/255.255.255.0
+BroadcastNetwork = 192.168.100.0/255.255.255.0
+SearchUsingNmblookup = 0 #don't use nmblookup
+FirstWait = 20 #20 hundredth seconds
+SecondWait = 30 #30 hundredth seconds on the seconds try
+UpdatePeriod = 300 #update after 300 secs
+DeliverUnnamedHosts = 0 #don't publish hosts without name
+
+
+You are only interested in hosts running smb services and you don't have
+routers in your network:
+
+AllowedAddresses = 192.168.100.0/255.255.255.0
+BroadcastNetwork = 192.168.100.0/255.255.255.0
+SearchUsingNmblookup = 1 #use nmblookup
+UpdatePeriod = 300 #update after 300 secs
+DeliverUnnamedHosts = 0 #don't publish hosts without name
+
+
+The same network, but here both nmblookup and pinging is used.
+
+PingAddresses = 192.168.100.0/255.255.255.0
+PingNames = bb_mail
+AllowedAddresses = 192.168.0.0/255.255.0.0
+BroadcastNetwork = 192.168.100.0/255.255.255.0
+SearchUsingNmblookup = 1 #also try nmblookup
+FirstWait = 30 #30 hundredth seconds
+SecondWait = -1 #only one try
+#SecondWait = 60 #try twice, and the second time wait 0.6 seconds
+UpdatePeriod = 300 #update after 300 secs
+DeliverUnnamedHosts = 0 #don't publish hosts without name
+MaxPingsAtOnce = 256 #send up to 256 ICMP echo requests at once
+
+And now a configuration file for resLISa, PingAddresses is not used by resLISa,
+neither is BroadcastNetwork.
+
+PingNames = bb_mail;some_host;some_other_host
+AllowedAddresses = 192.168.0.0/255.255.0.0
+SearchUsingNmblookup = 1 # use nmblookup
+FirstWait = 30 #30 hundredth seconds
+SecondWait = -1 #only one try
+#SecondWait = 60 #try twice, and the second time wait 0.6 seconds
+UpdatePeriod = 300 #update after 300 secs
+DeliverUnnamedHosts = 1 #also publish hosts without name
+MaxPingsAtOnce = 256 #send up to 256 ICMP echo requests at once
+
+
++----------------------+
+| Installation |
++----------------------+
+
+Both reslisa and lisa open a so called raw socket to send and receive
+ICMP echo requests (pings). To do this, they need root privileges.
+
+lisa offers a service on TCP port 7741, it should be installed by root
+and started when the system comes up, it depends on your distribution
+how to do this.
+
+reslisa is intended to be started per user, it doesn't offer anything to
+the network. It needs to be installed setuid root.
+
+If you use the rlan-ioslave from KDE2, reslisa can be started automatically
+by reslisa.
+
+lisa reads the file lisarc, reslisa reads the file reslisarc.
+If you want to be able to configure both from the KDE Control Center,
+you have to start them using the command line switch -K.
+
+For more information where they look for configuration files read
+the next chapter.
+
+
++--------------------------------------------+
+| Command Line Options and other usage |
++--------------------------------------------+
+
+The following command line options are supported:
+
+-v, --version prints a short version info
+-h, --help gives an overview over teh command line options
+
+Some options regarding search order for the configuration files.
+For reslisa the file is named reslisarc instead lisarc.
+
+-u, --unix search at first for $HOME/.lisarc, then
+ for /etc/lisarc, this is the default behaviour
+
+-k, --kde1 search at first for $HOME/.kde/share/config/lisarc,
+ then for $KDEDIR/share/config/lisarc
+
+-K, --kde2 looks for the file lisarc in every directory
+ returned by running "kde-config --path config"
+
+-c, --config=FILE read this and no other configuration file
+
+
+This one is only available for LISa, not for resLISa.
+
+-p, --port PORTNR start the server om this portnumber
+ if you use this LISa won't be able to
+ cooperate with other LISa's in the network
+
+
+If you send the Hangup-Signal to lisa or reslisa, it will reread its
+configuration file (killall -HUP lisa).
+
+If you send the User1-Signal to lisa or reslisa, it will print some status
+information to the standard output (killall -USR1 lisa). You won't see
+anything if the console from which lisa/reslisa was started has terminated.
+
+
+LISa and resLISa need a libstdc++ (it uses only the string-class from it),
+it *doesn't* need neither Qt nor KDE.
+
+So, that's it for now.
+If you have suggestions, problems or whatever, contact me.
+
+
+Have fun
+Alexander Neundorf
+<neundorf@kde.org>
+
diff --git a/lanbrowsing/lisa/addressvalidator.cpp b/lanbrowsing/lisa/addressvalidator.cpp
new file mode 100644
index 00000000..aa292806
--- /dev/null
+++ b/lanbrowsing/lisa/addressvalidator.cpp
@@ -0,0 +1,228 @@
+/* addressvalidator.cpp
+ *
+ * Copyright (c) 2000, Alexander Neundorf
+ * neundorf@kde.org
+ *
+ * You may distribute under the terms of the GNU General Public
+ * License as specified in the COPYING file.
+ *
+ * This program 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 General Public License for more details.
+ *
+ */
+
+#include "addressvalidator.h"
+#include "mystring.h"
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <iostream>
+using namespace std;
+
+#ifdef LISA_DEBUG
+#undef LISA_DEBUG
+#endif
+#define LISA_DEBUG 0
+#define dcerr if (LISA_DEBUG==1) std::cerr<<"AddressValidator::"
+
+AddressValidator::AddressValidator(const MyString& addressSpecs)
+//this is 127.0.0.0
+:localhostNet(htonl(0x7f000000))
+//with mask 255.255.255.0
+,localhostMask(htonl(0xffffff00))
+{
+ clearSpecs();
+ MyString tmp=addressSpecs;
+ setValidAddresses(tmp);
+}
+
+AddressValidator::AddressValidator()
+ //this is 127.0.0.0
+ :localhostNet(htonl(0x7f000000))
+ //with mask 255.255.255.0
+ ,localhostMask(htonl(0xffffff00))
+{
+ clearSpecs();
+}
+
+AddressValidator::~AddressValidator()
+{}
+
+void AddressValidator::configure(Config& config)
+{
+ MyString tmp=stripWhiteSpace(config.getEntry("AllowedAddresses",""));
+ tmp=tmp+";";
+ setValidAddresses(tmp);
+ dcerr<<"configure(): "<<tmp<<std::endl;
+}
+
+
+void AddressValidator::setValidAddresses(MyString addressSpecs)
+{
+ dcerr<<"setValidAddresses"<<std::endl;
+ allowedHosts=addressSpecs;
+ MyString nextPart;
+ while (!addressSpecs.isEmpty())
+ {
+ dcerr<<"setValidAddresses: "<<addressSpecs<<std::endl;
+ int pos=addressSpecs.find(";");
+ nextPart=addressSpecs.left(pos);
+ addressSpecs=addressSpecs.mid(pos+1);
+ dcerr<<"setValidAddresses: nextPart: "<<nextPart<<std::endl;
+ if ((nextPart.contains('.')==3) && (nextPart.contains('-')==0))
+ {
+ addSpec(EXACTADDR_SPEC,inet_addr(nextPart.data()));
+ dcerr<<"setValidAddresses: exact addr: "
+ <<std::ios::hex<<inet_addr(nextPart.data())<<std::ios::dec<<std::endl;
+ }
+ else if ((nextPart.contains('-')==1) && (nextPart.contains('.')==6))
+ {
+ int p2=nextPart.find("-");
+ MyString from=nextPart.left(p2);
+ MyString to=nextPart.mid(p2+1);
+ addSpec(RANGE_SPEC,ntohl(inet_addr(from.data())),ntohl(inet_addr(to.data())));
+ }
+ else if ((nextPart.contains('-')==4) && (nextPart.contains('.')==3))
+ {
+ unsigned int i1=0;
+ unsigned int i2=0;
+ int p2=0;
+ MyString rest=nextPart+'.';
+ MyString digit;
+
+ for (int i=0; i<4; i++)
+ {
+ p2=rest.find("-");
+ digit=rest.left(p2);
+ i1=i1<<8;
+ i1+=atoi(digit.data());
+ rest=rest.mid(p2+1);
+ p2=rest.find(".");
+ digit=rest.left(p2);
+ i2=i2<<8;
+ i2+=atoi(digit.data());
+ rest=rest.mid(p2+1);
+ };
+ addSpec(MULTIRANGE_SPEC,i1,i2);
+ }
+ else
+ {
+ pos=nextPart.find('/');
+ MyString netStr=nextPart.left(pos);
+ MyString maskStr=nextPart.mid(pos+1);
+ int mask=inet_addr(maskStr.data());
+ int net= (inet_addr(netStr.data()) & mask);
+ dcerr<<"setValidAddresses: net/mask: "
+ <<std::ios::hex<<net<<"/"<<mask<<std::ios::dec<<std::endl;
+ addSpec(NETMASK_SPEC,net,mask);
+ }
+ }
+}
+
+void AddressValidator::clearSpecs()
+{
+ allowedHosts="";
+ for (int i=0; i<MAX_SPECS; i++)
+ {
+ specs[i].address=0;
+ specs[i].mask=0;
+ specs[i].typeOfSpec=NO_SPEC;
+ }
+}
+
+void AddressValidator::addSpec(int type, int address, int mask)
+{
+ for (int i=0; i<MAX_SPECS; i++)
+ {
+ if (specs[i].typeOfSpec==NO_SPEC)
+ {
+ specs[i].address=address;
+ specs[i].mask=mask;
+ specs[i].typeOfSpec=type;
+ return;
+ }
+ }
+}
+
+int AddressValidator::isValid(int addressNBO)
+{
+ dcerr<<"isValid: "
+ <<std::ios::hex<<addressNBO<<std::ios::dec<<std::endl;
+ //localhost is always allowed
+ dcerr<<"isValid() local net: "<<
+ std::ios::hex<<localhostNet<<" mask: "<<localhostMask<<" AND: "<<(addressNBO &
+ localhostMask)<<std::ios::dec<<std::endl;
+ if ((addressNBO & localhostMask) == localhostNet)
+ return 1;
+
+ for (int i=0; i<MAX_SPECS; i++)
+ {
+ if (specs[i].typeOfSpec==NO_SPEC)
+ {
+ //since the specifications are always entered from the beginning
+ //of the array, we already passed the last one if we get here
+ //so we can return now "it is invalid !" ;-)
+ return 0;
+ //continue;
+ }
+ else if (specs[i].typeOfSpec==EXACTADDR_SPEC)
+ {
+ dcerr<<"isValid: comparing "
+ <<std::ios::hex<<specs[i].address<<std::ios::dec<<std::endl;
+ if (addressNBO==specs[i].address)
+ {
+ dcerr<<"isValid: exact address"<<std::endl;
+ return 1; // this one is allowed to :-)
+ }
+ }
+ else if (specs[i].typeOfSpec==NETMASK_SPEC)
+ {
+ dcerr<<"isValid: ANDing "<<
+ std::ios::hex<<(addressNBO & specs[i].mask)<<" "<<
+ specs[i].address<<std::ios::dec<<std::endl;
+ if ((addressNBO & specs[i].mask) == specs[i].address)
+ {
+ dcerr<<"isValid: net/mask"<<std::endl;
+ return 1;
+ }
+ }
+ else if (specs[i].typeOfSpec==RANGE_SPEC)
+ {
+ if ((ntohl(addressNBO)>=specs[i].address) && (ntohl(addressNBO)<=specs[i].mask))
+ {
+ dcerr<<"isValid: range"<<std::endl;
+ return 1;
+ }
+ }
+ else if (specs[i].typeOfSpec==MULTIRANGE_SPEC)
+ {
+ unsigned int addr=ntohl(addressNBO);
+ dcerr<<"isValid ntohl="<<hex<<addr<<" addr: "<<specs[i].address<<" ma: "<<specs[i].mask<<dec<<std::endl;
+ unsigned int mask=0x000000ff;
+ int failure=0;
+ for (int j=0; j<4; j++)
+ {
+ dcerr<<"isValid "<<hex<<"mask="<<mask<<" addr="<<(addr&mask)<<" addr="<<(specs[i].address & mask)<<" ma="<<(specs[i].mask&mask)<<std::endl;
+ if (((addr & mask) < (specs[i].address & mask))
+ || ((addr & mask) > (specs[i].mask & mask)))
+ {
+ failure=1;
+ break;
+ }
+ mask=mask<<8;
+ }
+ dcerr<<"isValid: multirange"<<std::endl;
+ if (!failure)
+ return 1;
+ }
+ }
+ //if ((addressNBO==htonl(0x0a040801)) || (addressNBO==htonl(0xc0a80001))) return 0;
+ dcerr<<"isValid: invalid address"<<std::endl;
+ return 0;
+}
+
diff --git a/lanbrowsing/lisa/addressvalidator.h b/lanbrowsing/lisa/addressvalidator.h
new file mode 100644
index 00000000..6f1c723e
--- /dev/null
+++ b/lanbrowsing/lisa/addressvalidator.h
@@ -0,0 +1,55 @@
+/* addressvalidator.h
+ *
+ * Copyright (c) 2000, Alexander Neundorf
+ * neundorf@kde.org
+ *
+ * You may distribute under the terms of the GNU General Public
+ * License as specified in the COPYING file.
+ *
+ * This program 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 General Public License for more details.
+ *
+ */
+
+#ifndef ADDRESSVALIDATOR_H
+#define ADDRESSVALIDATOR_H
+
+#include "lisadefines.h"
+#include "mystring.h"
+#include "configfile.h"
+
+#define NO_SPEC 0
+#define NETMASK_SPEC 1
+#define EXACTADDR_SPEC 2
+#define RANGE_SPEC 3
+#define MULTIRANGE_SPEC 4
+
+struct AddressSpec
+{
+ int address;
+ int mask;
+ int typeOfSpec;
+};
+
+class AddressValidator
+{
+ public:
+ AddressValidator(const MyString& addressSpecs);
+ AddressValidator();
+ ~AddressValidator();
+ void configure(Config& config);
+ void setValidAddresses(MyString addressSpecs);
+ void clearSpecs();
+ int isValid(int addressNBO);
+ MyString validAddresses() {return allowedHosts;};
+ private:
+ int localhostNet;
+ int localhostMask;
+ MyString allowedHosts;
+ void addSpec(int type, int address, int mask=0);
+ AddressSpec specs[MAX_SPECS];
+};
+
+#endif
diff --git a/lanbrowsing/lisa/client.cpp b/lanbrowsing/lisa/client.cpp
new file mode 100644
index 00000000..21069a17
--- /dev/null
+++ b/lanbrowsing/lisa/client.cpp
@@ -0,0 +1,122 @@
+/* client.cpp
+ *
+ * Copyright (c) 2000, Alexander Neundorf
+ * neundorf@kde.org
+ *
+ * You may distribute under the terms of the GNU General Public
+ * License as specified in the COPYING file.
+ *
+ * This program 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 General Public License for more details.
+ *
+ */
+
+#include "netmanager.h"
+#include "client.h"
+#include "lisadefines.h"
+
+#include <iostream>
+#include <unistd.h>
+
+#include <strings.h>
+
+#ifdef LISA_DEBUG
+#undef LISA_DEBUG
+#endif
+
+#ifdef dcerr
+#undef dcerr
+#endif
+
+#define LISA_DEBUG 0
+#define dcerr if (LISA_DEBUG==1) std::cerr<<"Client::"
+
+
+Client::Client(NetManager* parent, int socketFD, int closeOnDelete)
+:parentServer(parent)
+,m_fd(socketFD)
+,m_done(0)
+,m_closeOnDelete(closeOnDelete)
+{
+ dcerr<<"ctor created new client"<<std::endl;
+ if (m_fd==-1) m_done=1;
+ m_creationTime=time(0);
+}
+
+Client::Client()
+:parentServer(0)
+,m_fd(-1)
+,m_done(1)
+,m_closeOnDelete(1)
+{
+ m_creationTime=time(0);
+}
+
+Client::Client(const Client& c)
+:parentServer(c.parentServer)
+,m_fd(c.m_fd)
+,m_creationTime(c.m_creationTime)
+,m_done(c.m_done)
+,m_closeOnDelete(1)
+{
+ dcerr<<"Client copy ctor"<<std::endl;
+}
+
+int Client::tryToGetInfo()
+{
+ dcerr<<"tryToGetInfo: m_done: "<<m_done<<std::endl;
+ if (done()) return 1;
+ if (m_fd==-1)
+ {
+ close();
+ return 1;
+ }
+ dcerr<<"tryToGetInfo: calling data.getFile()"<<std::endl;
+ if (!parentServer->isInformed()) return 0;
+ //we fork now, so that writing to the client can't block the server process
+ /* int pid=fork();
+ if (pid==-1)
+ {
+ //parent
+ dcerr<<"NetScanner::scan: error occurred"<<std::endl;
+ return 1;
+ }
+ else if (pid!=0)
+ {
+ //parent
+ return 1;
+ };*/
+ //child
+ //this one does it all :-)
+ dcerr<<"tryToGetInfo: sending data to client"<<std::endl;
+ parentServer->writeDataToFD(fd(),0);
+ close();
+ //exit(0);
+ return 1;
+}
+
+void Client::close()
+{
+ if (m_fd!=-1) ::close(m_fd);
+ m_fd=-1;
+ m_done=1;
+}
+
+void Client::read()
+{
+ dcerr<<"read()"<<std::endl;
+ if (m_fd==-1) return;
+ char buf[1024];
+ //the clients should not send us something !
+ int result=::read(m_fd,buf,1024);
+ if (result>=0) close();
+}
+
+Client::~Client()
+{
+ if (m_closeOnDelete)
+ close();
+}
+
diff --git a/lanbrowsing/lisa/client.h b/lanbrowsing/lisa/client.h
new file mode 100644
index 00000000..efcf5f86
--- /dev/null
+++ b/lanbrowsing/lisa/client.h
@@ -0,0 +1,45 @@
+/* client.h
+ *
+ * Copyright (c) 2000, Alexander Neundorf
+ * neundorf@kde.org
+ *
+ * You may distribute under the terms of the GNU General Public
+ * License as specified in the COPYING file.
+ *
+ * This program 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 General Public License for more details.
+ *
+ */
+
+#ifndef CLIENT_H
+#define CLIENT_H
+
+#include <time.h>
+
+class NetManager;
+
+class Client
+{
+ public:
+ Client(NetManager* parent, int socketFD, int closeOnDelete=1);
+ Client();
+ Client(const Client& c);
+ ~Client();
+ int tryToGetInfo();
+ int done() {return m_done;};
+ int fd() {return m_fd;};
+ void read();
+ void close();
+ time_t age() {return time(0)-m_creationTime;};
+ private:
+ NetManager *parentServer;
+ int m_fd;
+ //if something goes wrong close the connection after a timeout
+ time_t m_creationTime;
+ int m_done;
+ int m_closeOnDelete;
+};
+
+#endif
diff --git a/lanbrowsing/lisa/configfile.cpp b/lanbrowsing/lisa/configfile.cpp
new file mode 100644
index 00000000..5c1e4a65
--- /dev/null
+++ b/lanbrowsing/lisa/configfile.cpp
@@ -0,0 +1,136 @@
+/* configfile.cpp
+ *
+ * Copyright (c) 1998, 2000, Alexander Neundorf
+ * neundorf@kde.org
+ *
+ * You may distribute under the terms of the GNU General Public
+ * License as specified in the COPYING file.
+ *
+ * This program 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 General Public License for more details.
+ *
+ */
+
+#include "configfile.h"
+
+#include <iostream>
+#include <fstream>
+#include <ctype.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef LISA_DEBUG
+#undef LISA_DEBUG
+#endif
+#define LISA_DEBUG 0
+
+#ifdef dcerr
+#undef dcerr
+#endif
+
+#define dcerr if (LISA_DEBUG==1) std::cerr<<"Config::"
+
+
+#define CFGBUFSIZE 16*1024
+
+Config::Config(const MyString& name/*,String path*/)
+{
+ char buff[CFGBUFSIZE],c;
+/* String s,empty="#############################################################################################################################################################";
+ String home=getenv("HOME");
+
+ if (!home.empty()) home+=String("/")+name;
+ if (fexists(home)==0)
+ {
+ home=path+"/"+name;
+ if (fexists(home)==0)
+ {
+ home=name;
+ if (fexists(home)==0) return;
+ };
+ };*/
+ std::ifstream inf(name.data());
+ if (!inf)
+ {
+ std::cout<<"could not open file "<<name<<std::endl;
+ return;
+ }
+ dcerr<<"Config(): opened file "<<name<<std::endl;
+ //read the file
+ char key[CFGBUFSIZE], value[CFGBUFSIZE];
+ do
+ {
+ char* buffStart=buff;
+ //inf.getline(buff,16*1024,'\n');
+ int bufSize(CFGBUFSIZE);
+ int lineBroken(0);
+ do
+ {
+ lineBroken=0;
+ inf.get(buffStart,bufSize,'\n');
+ inf.get(c);
+ int l=strlen(buffStart);
+ if (l==0)
+ break;
+ if (buffStart[l-1]=='\\')
+ {
+ buffStart=buffStart+l-1;
+ bufSize=bufSize+1-l;
+ lineBroken=1;
+ }
+ } while ((lineBroken) && (!inf.eof()));
+ //make it ignore comments
+ char *theChar=strchr(buff,'#');
+ if (theChar!=0)
+ *theChar='\0';
+ //now divide the line into key and value
+ theChar=strchr(buff,'=');
+ if (theChar!=0)
+ {
+ *theChar='\0';
+ key[0]='\0';
+ sscanf(buff,"%8000s",key);
+ //do we have something valid ?
+ if (key[0]!='\0')
+ {
+ //the char behind the = should be at least the terminating \0
+ // so I can be sure to access valid memory here, IMO
+ value[0]='\0';
+
+ strncpy(value,theChar+1,CFGBUFSIZE);
+ if (value[0]!='\0')
+ {
+ //here we can be sure that the list will only contain
+ //strings which are at least one char long
+ dcerr<<"Config(): adding "<<key<<std::endl;
+ m_entries[key]=value;
+ }
+ }
+ }
+ }
+ while (!inf.eof());
+}
+
+MyString Config::getEntry(const char *key, const char* defaultValue)
+{
+ if ((key==0) || (key[0]=='\0'))
+ return defaultValue;
+ if (m_entries.find(key)==m_entries.end())
+ return defaultValue;
+ return m_entries[key];
+}
+
+int Config::getEntry(const char *key, int defaultValue)
+{
+ char def[100];
+ sprintf(def,"%d",defaultValue);
+ MyString tmp=stripWhiteSpace(getEntry(key,def));
+ int i(0);
+ int ok=sscanf(tmp.c_str(),"%d",&i);
+ if (ok==1) return i;
+ return defaultValue;
+}
+
diff --git a/lanbrowsing/lisa/configfile.h b/lanbrowsing/lisa/configfile.h
new file mode 100644
index 00000000..1879e3b9
--- /dev/null
+++ b/lanbrowsing/lisa/configfile.h
@@ -0,0 +1,33 @@
+/* configfile.h
+ *
+ * Copyright (c) 1998,2000 Alexander Neundorf
+ * neundorf@kde.org
+ *
+ * You may distribute under the terms of the GNU General Public
+ * License as specified in the COPYING file.
+ *
+ * This program 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 General Public License for more details.
+ *
+ */
+
+#ifndef CONFIGFILE_H
+#define CONFIGFILE_H
+
+#include <map>
+
+#include "mystring.h"
+
+class Config
+{
+ public:
+ Config(const MyString& name);
+ MyString getEntry(const char *key, const char* defaultValue);
+ int getEntry(const char *key, int defaultValue);
+ protected:
+ std::map<MyString, MyString> m_entries;
+};
+
+#endif
diff --git a/lanbrowsing/lisa/ipaddress.cpp b/lanbrowsing/lisa/ipaddress.cpp
new file mode 100644
index 00000000..8dc98194
--- /dev/null
+++ b/lanbrowsing/lisa/ipaddress.cpp
@@ -0,0 +1,97 @@
+/* ipaddress.cpp
+ *
+ * Copyright (c) 1998, 1999, Alexander Neundorf, Lukas Pustina
+ * alexander.neundorf@rz.tu-ilmenau.de
+ * lukas@tronet.de
+ *
+ * You may distribute under the terms of the GNU General Public
+ * License as specified in the COPYING file.
+ *
+ * This program 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 General Public License for more details.
+ *
+ */
+
+#include "ipaddress.h"
+
+#include <iostream>
+
+IPAddress::IPAddress()
+{
+}
+
+IPAddress::IPAddress(const MyString& ip)
+{
+ if (ip.length()==0)
+ s="0.0.0.0";
+ else s=ip;
+ i=string2Int(s);
+ n=string2Struct(s);
+}
+
+IPAddress::IPAddress(unsigned int ip)
+{
+ i=ip;
+ s=int2String(i);
+ n.s_addr=htonl(i);
+ //n=string2Struct(s);
+}
+
+IPAddress::IPAddress(struct in_addr ip)
+{
+ n=ip;
+ s=struct2String(n);
+ i=string2Int(s);
+}
+
+IPAddress::IPAddress(int b1, int b2, int b3, int b4)
+{
+ char tmp[30];
+ sprintf(tmp,"%i.%i.%i.%i",b1,b2,b3,b4);
+ s=tmp;
+ i=string2Int(s);
+ n=string2Struct(s);
+}
+
+
+MyString IPAddress::int2String(unsigned int ip)
+{
+ MyString tmp("");
+ struct in_addr addr;
+ addr.s_addr=htonl(ip);
+ tmp=inet_ntoa(addr);
+ return tmp;
+}
+
+MyString IPAddress::struct2String(struct in_addr ip)
+{
+ return MyString(inet_ntoa(ip));
+}
+
+unsigned int IPAddress::string2Int(MyString ip)
+{
+// struct in_addr addr;
+// inet_aton(ip.c_str(),&addr);
+// cout<<addr.s_addr<<endl;
+// return ntohl(addr.s_addr);
+ return ntohl(inet_addr(ip.c_str()));
+}
+
+struct in_addr IPAddress::string2Struct(MyString ip)
+{
+ struct in_addr tmp;
+// inet_aton(ip.c_str(),&tmp);
+ tmp.s_addr = inet_addr(ip.c_str());
+ return tmp;
+}
+
+void IPAddress::print()
+{
+ std::cout<<"address as string: "<<s<<std::endl;
+ std::cout<<"address in host byte order: "<<std::ios::hex<<i<<std::ios::dec<<std::endl;
+ std::cout<<"address in network byte order: "<<std::ios::hex<<n.s_addr<<std::ios::dec<<std::endl;
+}
+
+
diff --git a/lanbrowsing/lisa/ipaddress.h b/lanbrowsing/lisa/ipaddress.h
new file mode 100644
index 00000000..ecca928a
--- /dev/null
+++ b/lanbrowsing/lisa/ipaddress.h
@@ -0,0 +1,55 @@
+/* ipaddress.h
+ *
+ * Copyright (c) 1998, 1999, Alexander Neundorf, Lukas Pustina
+ * alexander.neundorf@rz.tu-ilmenau.de
+ * lukas@tronet.de
+ *
+ * You may distribute under the terms of the GNU General Public
+ * License as specified in the COPYING file.
+ *
+ * This program 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 General Public License for more details.
+ *
+ */
+
+#ifndef IPADDRESS_H
+#define IPADDRESS_H
+
+#include "lisadefines.h"
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include "mystring.h"
+
+class IPAddress
+{
+ public:
+ IPAddress();
+ IPAddress(const MyString& ip);
+ IPAddress(unsigned int ip);
+ IPAddress(struct in_addr ip);
+ IPAddress(int b1, int b2, int b3, int b4);
+ //you know
+ MyString asString() {return s;};
+ //in host byte order
+ unsigned int asInt() {return i;};
+ //in network byte order
+ struct in_addr asStruct() {return n;};
+ /*operator= (IPAddress ip);
+ operator+= (unsigned int add);*/
+ void print();
+ private:
+ MyString int2String(unsigned int ip);
+ MyString struct2String(struct in_addr ip);
+ unsigned int string2Int(MyString ip);
+ struct in_addr string2Struct(MyString ip);
+ MyString s;
+ unsigned int i;
+ struct in_addr n;
+};
+
+#endif
diff --git a/lanbrowsing/lisa/lisadefines.h b/lanbrowsing/lisa/lisadefines.h
new file mode 100644
index 00000000..ac15d2c5
--- /dev/null
+++ b/lanbrowsing/lisa/lisadefines.h
@@ -0,0 +1,19 @@
+#ifndef LISADEFINES_H
+#define LISADEFINES_H
+
+
+#define MYVERSION "0.2.3"
+#define MY_ID 7741
+#define MYPORT 7741
+#define MAX_SPECS 128
+#define SELECT_TIMEOUT 7
+
+#define EXTRACONFIGSTYLE 0
+#define UNIXCONFIGSTYLE 1
+
+#define CONFIGFILEBASENAME "lisarc"
+#define STRICTCONFIGFILEBASENAME "reslisarc"
+
+#define STRICTMODEMAXHOSTS 64
+
+#endif
diff --git a/lanbrowsing/lisa/main.cpp b/lanbrowsing/lisa/main.cpp
new file mode 100644
index 00000000..7de59389
--- /dev/null
+++ b/lanbrowsing/lisa/main.cpp
@@ -0,0 +1,290 @@
+/* main.cpp
+ *
+ * Copyright (c) 1998-2000 Alexander Neundorf
+ * neundorf@kde.org
+ *
+ * You may distribute under the terms of the GNU General Public
+ * License as specified in the COPYING file.
+ *
+ * This program 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 General Public License for more details.
+ *
+ */
+
+#include "lisadefines.h"
+#include "netmanager.h"
+
+#ifdef LISA_DEBUG
+#undef LISA_DEBUG
+#endif
+
+#ifdef dcerr
+#undef dcerr
+#endif
+
+#define LISA_DEBUG 0
+#define dcerr if (LISA_DEBUG==1) std::cerr<<"main "
+
+#include <iostream>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+// detect linux/glibc for the gnu style --args
+#if defined(__linux__) || defined(__linux) || defined(linux)
+# include <features.h>
+# ifdef __GLIBC__
+// only gnu libc has getopt.h... getopt(3) is defined to be in unistd.h
+// by POSIX.2
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+# include <getopt.h>
+# endif // __GLIBC__
+# define GNU_GETOPT
+#endif // linux
+
+
+void printVersion()
+{
+ const char * versionInfo=\
+ "\r\nThis is the LAN Information Server LISa "MYVERSION"\r\n"\
+ "It is free software according the GNU General Public License\r\n"\
+ "Copyright (c) 2000-2003 by Alexander Neundorf\r\n"\
+ "email: neundorf@kde.org\r\n";
+ std::cout<<versionInfo<<std::endl;
+}
+
+void usage()
+{
+ printVersion();
+ const char * usageInfo=\
+ "-v, --version prints out a short version info\n"\
+ "-u, --unix deprecated\n"\
+ "-k, --kde1 deprecated\n"\
+ "-K, --kde2 deprecated\n"\
+ " lisa now looks always first for $(HOME)/.lisarc, then for /etc/lisarc\n"\
+ "-c, --config=FILE read this and no other configuration file\n"\
+ "-q, --quiet start quiet without the greeting message\n"\
+ "-p, --port PORTNR start the server on this portnumber\n"\
+ " if you use this LISa won't be able to\n"\
+ " cooperate with other LISa's in the network\n"\
+ "-h, --help you are currently reading it ;-)\n";
+ std::cout<<usageInfo<<std::endl;
+//I thought this would be the way to check wether long options are supported...
+//#ifndef _GNU_SOURCE
+// std::cout<<"Please note that the long options are not supported on
+// this system"<<std::endl;
+//#endif
+}
+
+NetManager *manager(0);
+
+
+void destruct(int sigNumber)
+{
+ signal(sigNumber,SIG_IGN);
+ dcerr<<"signal caught: "<<sigNumber<<", exiting"<<std::endl;
+ //signal(sigNumber,&destruct);
+ if (manager!=0)
+ manager->~NetManager();
+ exit(0);
+}
+
+void readConfig(int sigNumber)
+{
+ dcerr<<"readConfig(): signal caught: "<<sigNumber<<std::endl;
+ signal(SIGHUP,SIG_IGN);
+ if (manager!=0)
+ manager->readConfig();
+ signal(SIGHUP,&readConfig);
+}
+
+void printState(int sigNumber)
+{
+ dcerr<<"printState(): signal caught: "<<sigNumber<<std::endl;
+ signal(SIGUSR1,SIG_IGN);
+ if (manager!=0)
+ manager->printState();
+ signal(SIGUSR1,&printState);
+}
+
+void setSignalHandler()
+{
+ signal(SIGHUP,&readConfig);
+ signal(SIGUSR1,&printState);
+
+ signal(SIGINT,&destruct);
+ signal(SIGQUIT,&destruct);
+ signal(SIGILL,&destruct);
+ signal(SIGTRAP,&destruct);
+ signal(SIGABRT,&destruct);
+ signal(SIGBUS,&destruct);
+ signal(SIGSEGV,&destruct);
+ signal(SIGUSR2,&destruct);
+ signal(SIGPIPE,&destruct);
+ signal(SIGALRM,&destruct);
+ signal(SIGTERM,&destruct);
+ signal(SIGFPE,&destruct);
+#ifdef SIGPOLL
+ signal(SIGPOLL, &destruct);
+#endif
+#ifdef SIGSYS
+ signal(SIGSYS, &destruct);
+#endif
+#ifdef SIGVTALRM
+ signal(SIGVTALRM, &destruct);
+#endif
+#ifdef SIGXCPU
+ signal(SIGXCPU, &destruct);
+#endif
+#ifdef SIGXFSZ
+ signal(SIGXFSZ, &destruct);
+#endif
+}
+
+#ifdef GNU_GETOPT
+static struct option const long_opts[] =
+{
+ {"version", no_argument, 0, 'v'},
+ {"quiet", no_argument, 0, 'q'},
+ {"unix", no_argument, 0, 'u'},
+ {"kde1", no_argument, 0, 'k'},
+ {"kde2", no_argument, 0, 'K'},
+ {"config", required_argument, 0, 'c'},
+ {"port", required_argument, 0, 'p'},
+ {"help", no_argument, 0, 'h'},
+ {0, 0, 0, 0}
+};
+#endif
+
+int main(int argc, char** argv)
+{
+ int quiet(0);
+ int c(0);
+ int configStyle(UNIXCONFIGSTYLE);
+ MyString configFile;
+ int portToUse(MYPORT);
+
+//I thought this would be the way to check wether long options are supported...
+#ifdef GNU_GETOPT
+ while ((c=getopt_long(argc, argv, "vqukKc:h", long_opts, 0))!=-1)
+#else
+ while ((c=getopt(argc, argv, "vqukKc:h"))!=-1)
+#endif
+
+ {
+ char *endp(0);
+ switch (c)
+ {
+ case 0:
+ break;
+ case 'v':
+ printVersion();
+ exit(0);
+ break;
+ case 'q':
+ quiet=1;
+ break;
+ case 'u':
+ case 'k':
+ case 'K':
+ std::cout<<"\a\nThe command line switches -k, -K, -u and \ntheir long versions "\
+ "--kde1, --kde2 and --unix are not supported anymore.\n"\
+ "Lisa will always first look for $(HOME)/.lisarc , then for /etc/lisarc.\n"\
+ "If your lisa configuration file was created using an older version of \n"\
+ "the KDE control center, copy the /root/.kde/share/config/lisarc to /etc and \n"\
+ "then start lisa without any command line options.\n"<<std::endl;
+ return 0;
+ break;
+
+ case 'c':
+ configFile = optarg;
+ configStyle = EXTRACONFIGSTYLE;
+ break;
+
+ case 'p':
+ portToUse=strtol(optarg,&endp,10);
+ if (endp!=0)
+ {
+ usage();
+ exit(0);
+ }
+ break;
+
+ case 'h':
+ default:
+ usage();
+ exit(0);
+ break;
+ }
+ }
+
+ //fork and let the parent exit
+ pid_t pid=fork();
+ if (pid>0)
+ {
+ //this is the parent
+ exit(0);
+ }
+ else if (pid<0)
+ {
+ std::cout<<"could not fork()"<<std::endl;
+ exit(0);
+ }
+ //we will only read/write to/from this socket in the child process
+ int rawSocket=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);
+ if (rawSocket==-1)
+ {
+ std::cout<<"could not create raw socket, root privileges required"<<std::endl;
+ std::cout<<"take a look at the README for more information"<<std::endl;
+ exit(0);
+ }
+ int bufferSize(60*1024);
+ int on(1);
+ setsockopt(rawSocket, SOL_SOCKET, SO_RCVBUF, (char*)&bufferSize,
+ sizeof(bufferSize));
+ int result=setsockopt(rawSocket, SOL_SOCKET, SO_BROADCAST, (char*)&on,
+ sizeof(on));
+ dcerr<<"setsockopt returns "<<result<<std::endl;
+ //dropping root privileges
+ //they will be regained once in the child process
+ //for creating a raw socket
+
+ //now dropping root privileges once and ever
+
+
+ setuid(getuid());
+ if (geteuid() != getuid())
+ _exit(255);
+
+ //according to R. Stevens the following three lines
+ //make daemons feel good :)
+ setsid();
+ chdir("/");
+ umask(0);
+
+ dcerr<<"starting, dropped root privileges"<<std::endl;
+ dcerr<<"port: "<<portToUse<<" file: "<<configFile<<std::endl;
+ NetManager netmanager(rawSocket,portToUse,configFile,configStyle,0);
+ manager=&netmanager;
+ dcerr<<"NetManager created"<<std::endl;
+ setSignalHandler();
+
+ netmanager.readConfig();
+ if (netmanager.prepare())
+ {
+ if (!quiet)
+ {
+ printVersion();
+ std::cout<<"\n\rrunning on port "<<portToUse<<"\n\rHave fun ! :-)"<<std::endl;
+ }
+ netmanager.run();
+ };
+ dcerr<<"server finished"<<std::endl;
+}
diff --git a/lanbrowsing/lisa/mystring.cpp b/lanbrowsing/lisa/mystring.cpp
new file mode 100644
index 00000000..2b7af2d2
--- /dev/null
+++ b/lanbrowsing/lisa/mystring.cpp
@@ -0,0 +1,52 @@
+#include "mystring.h"
+
+#include <ctype.h>
+
+//this one is taken from Qt/QCString
+
+MyString stripWhiteSpace(MyString str)
+{
+ if ( str.isEmpty() ) // nothing to do
+ return "";
+
+ char const *s = str.data();
+ MyString result = s;
+ int reslen = result.length();
+ if ( !isspace(s[0]) && !isspace(s[reslen-1]) )
+ return result; // returns a copy
+
+ s = result.data();
+ int start = 0;
+ int end = reslen - 1;
+ while ( isspace(s[start]) ) // skip white space from start
+ start++;
+ if ( s[start] == '\0' )
+ { // only white space
+ result.resize( 1 );
+ return "";
+ }
+
+ while ( end && isspace(s[end]) ) // skip white space from end
+ end--;
+
+ end -= start - 1;
+
+ result=str.mid(start,end);
+ //memmove( result.data(), &s[start], end );
+ //result.resize( end + 1 );
+ return result;
+}
+
+//mainly taken from qcstring
+int MyString::contains(char c)
+{
+ int count = 0;
+ char const *d = c_str();
+ if ( d==0 )
+ return 0;
+ while ( *d )
+ if ( *d++ == c )
+ count++;
+ return count;
+}
+
diff --git a/lanbrowsing/lisa/mystring.h b/lanbrowsing/lisa/mystring.h
new file mode 100644
index 00000000..20d40e59
--- /dev/null
+++ b/lanbrowsing/lisa/mystring.h
@@ -0,0 +1,42 @@
+#ifndef MYSTRING_H
+#define MYSTRING_H
+
+#include <string>
+#include <string.h>
+#include <strings.h>
+#include <stdio.h>
+
+class MyString: public std::string
+{
+ public:
+ MyString(const char c) : std::string(1,c) {};
+ MyString(const char* c)
+ : std::string(c==0?"":c)
+ {};
+ MyString(const std::string& s) : std::string(s) {};
+ MyString() : std::string() {};
+
+ int isEmpty() const {return empty();};
+ MyString mid(int pos, int length=-1) const {return substr(pos,length);};
+ MyString left(int len) const {return substr(0,len);};
+ MyString right(int len) const
+ {
+ if (len<1) return "";
+ else if (len<int(size())) return substr(size()-len);
+ else return (*this);
+ };
+
+ int contains(char c);
+ //char & operator[] (unsigned int i) {return ((string)(*this))[i];}
+ //operator const char* () const {return c_str();}
+ const char* data() const {return c_str();}
+ /*void setNum(int value) {char c[15]; bzero(c,15); sprintf(c,"%d",value); (*this)=c;};
+ void setNum(double value) {char c[25]; bzero(c,25); sprintf(c,"%g",value); (*this)=c;};
+ void simplifyWhiteSpace();*/
+};
+
+//taken from Qt/QCString
+MyString stripWhiteSpace(MyString str);
+
+#endif
+
diff --git a/lanbrowsing/lisa/netmanager.cpp b/lanbrowsing/lisa/netmanager.cpp
new file mode 100644
index 00000000..e652ce97
--- /dev/null
+++ b/lanbrowsing/lisa/netmanager.cpp
@@ -0,0 +1,1058 @@
+ /* netmanager.cpp
+ *
+ * Copyright (c) 2000, Alexander Neundorf
+ * neundorf@kde.org
+ *
+ * You may distribute under the terms of the GNU General Public
+ * License as specified in the COPYING file.
+ *
+ * This program 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 General Public License for more details.
+ *
+ */
+
+#include "config.h"
+
+#include "netmanager.h"
+#include "lisadefines.h"
+
+#include <iostream>
+#include <unistd.h>
+
+#include <sys/un.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <strings.h>
+#include <errno.h>
+#include <string.h>
+#include <signal.h>
+#include <pwd.h>
+
+#ifndef AF_LOCAL
+#define AF_LOCAL AF_UNIX
+#endif
+
+
+#ifdef LISA_DEBUG
+#undef LISA_DEBUG
+#endif
+
+#ifdef dcerr
+#undef dcerr
+#endif
+
+#ifdef mdcerr
+#undef mdcerr
+#endif
+
+#define LISA_DEBUG 0
+#define dcerr if (LISA_DEBUG==1) std::cerr<<"NetManager "
+#define mdcerr if (LISA_DEBUG==1) std::cerr<<procId<<" NetManager "
+
+static void sig_child_handler(int)
+{
+ int saved_errno = errno;
+
+ while (waitpid(-1, NULL, WNOHANG) > 0)
+ ; // repeat
+
+ errno = saved_errno;
+}
+
+NetManager::NetManager(int& rawSocketFD, int portToUse, MyString configFile, int configStyle, int strictMode)
+:NetScanner(rawSocketFD,strictMode)
+//,validator()
+,m_listenFD(-1)
+,m_bcFD(-1)
+,m_basePort(portToUse)
+,m_pipeFD(-1)
+,m_receiveBuffer(0)
+,m_receivedBytes(0)
+,m_childPid(0)
+,m_lastUpdate(0)
+
+,m_isInformed(0)
+,m_isBeingScanned(0)
+,m_firstRun(1)
+,m_serverServer(0)
+,m_servedThisPeriod(0)
+
+,m_serveCount(0)
+,m_refreshTime(60)
+,m_initialRefreshTime(60)
+,m_increasedRefreshTime(0)
+,m_broadcastAddress(0)
+,m_extraConfigFile(configFile)
+,m_configStyle(configStyle)
+,m_usedConfigFileName("")
+{
+ mdcerr<<"NetManager::NetManager"<<std::endl;
+ m_startedAt=time(0);
+
+ struct sigaction act;
+ act.sa_handler=sig_child_handler;
+ sigemptyset(&(act.sa_mask));
+ sigaddset(&(act.sa_mask), SIGCHLD);
+ // Make sure we don't block this signal. gdb tends to do that :-(
+ sigprocmask(SIG_UNBLOCK, &(act.sa_mask), 0);
+
+ act.sa_flags = SA_NOCLDSTOP;
+#ifdef SA_RESTART
+ act.sa_flags |= SA_RESTART;
+#endif
+
+ sigaction( SIGCHLD, &act, NULL );
+}
+
+NetManager::~NetManager()
+{
+ mdcerr<<"NetManager destructor ..."<<std::endl;
+ if (m_receiveBuffer!=0) delete [] m_receiveBuffer;
+ ::close(m_listenFD);
+ ::close(m_bcFD);
+}
+
+void NetManager::readConfig()
+{
+ m_usedConfigFileName=getConfigFileName();
+ if (m_usedConfigFileName.isEmpty())
+ {
+ std::cout<<"configfile not found"<<std::endl;
+ std::cout<<"use the command line option --help and \ntake a look at the README for more information"<<std::endl;
+ exit(1);
+ }
+
+ Config config(m_usedConfigFileName);
+ NetManager::configure(config);
+ NetScanner::configure(config);
+ validator.configure(config);
+ //after reading the new configuration we should really update
+ m_lastUpdate=0;
+}
+
+void NetManager::configure(Config& config)
+{
+ m_refreshTime=config.getEntry("UpdatePeriod",300);
+ MyString tmp=stripWhiteSpace(config.getEntry("BroadcastNetwork","0.0.0.0/255.255.255.255;"));
+ tmp=tmp+";";
+ mdcerr<<"NetManager::readConfig: "<<tmp<<std::endl;
+ MyString netAddressStr=tmp.left(tmp.find('/'));
+ tmp=tmp.mid(tmp.find('/')+1);
+ tmp=tmp.left(tmp.find(';'));
+ mdcerr<<"NetManager::readConfig: broadcastNet "<<netAddressStr<<" with mask "<<tmp<<std::endl;
+ int netMask=inet_addr(tmp.c_str());
+ int netAddress=inet_addr(netAddressStr.c_str());
+ m_broadcastAddress= netAddress | (~netMask);
+ mdcerr<<"NetManager::readConfig: net "<<std::ios::hex<<netAddress<<" with mask "<<netMask<<" gives "<<m_broadcastAddress<<std::endl;
+
+ //maybe this way we can avoid that all servers on the net send
+ //their requests synchronously, since now the refreshtime isn't
+ //always the eact value of m_refreshTime, but differs always slightly
+ if ((m_refreshTime%SELECT_TIMEOUT)==0) m_refreshTime+=2;
+ //some limits from half a minute to half an hour
+ if (m_refreshTime<30) m_refreshTime=30;
+ if (m_refreshTime>1800) m_refreshTime=1800;
+ m_initialRefreshTime=m_refreshTime;
+}
+
+int NetManager::prepare()
+{
+ mdcerr<<"NetManager::prepare"<<std::endl;
+
+ ::close(m_listenFD);
+ ::close(m_bcFD);
+ int result(0);
+ if (m_strictMode)
+ {
+ m_listenFD=::socket(AF_LOCAL, SOCK_STREAM, 0);
+ //m_listenFD=::socket(AF_LOCAL, SOCK_STREAM, IPPROTO_TCP);
+ MyString socketName("/tmp/resLisa-");
+ struct passwd *user = getpwuid( getuid() );
+ if ( user )
+ socketName+=user->pw_name;
+ else
+ //should never happen
+ socketName+="???";
+ ::unlink(socketName.data());
+ sockaddr_un serverAddr;
+ if (socketName.length() >= sizeof(serverAddr.sun_path))
+ {
+ std::cout<<"NetManager::prepare: your user name \""<<user->pw_name<<"\" is too long, exiting."<<std::endl;
+ return 0;
+ }
+ memset((void*)&serverAddr, 0, sizeof(serverAddr));
+ serverAddr.sun_family=AF_LOCAL;
+ strncpy(serverAddr.sun_path,socketName.data(),sizeof(serverAddr.sun_path));
+ result=::bind(m_listenFD,(sockaddr*) &serverAddr,sizeof(serverAddr));
+ if (result!=0)
+ {
+ std::cout<<"NetManager::prepare: bind (UNIX socket) failed, errno: "<<errno<<std::endl;
+ return 0;
+ }
+ }
+ else
+ {
+ //create a listening port and listen
+ m_listenFD = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (m_listenFD==-1)
+ {
+ std::cout<<"NetManager::prepare: socket(TCP) failed, errno: "<<errno<<std::endl;
+ return 0;
+ }
+
+ sockaddr_in serverAddress;
+// bzero((char*)&serverAddress, sizeof(serverAddress));
+ memset((void*)&serverAddress, 0, sizeof(serverAddress));
+ serverAddress.sin_family = AF_INET;
+ serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
+ serverAddress.sin_port = htons(m_basePort);
+
+ int on(1);
+ result=setsockopt(m_listenFD, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on));
+ if (result!=0)
+ {
+ std::cout<<"NetManager::prepare: setsockopt(SO_REUSEADDR) failed"<<std::endl;
+ return 0;
+ }
+ result=::bind(m_listenFD, (struct sockaddr *) &serverAddress, sizeof(serverAddress));
+ if (result!=0)
+ {
+ std::cout<<"NetManager::prepare: bind (TCP) failed, errno: "<<errno<<std::endl;
+ return 0;
+ }
+ }
+ result=::listen(m_listenFD, 32);
+ if (result!=0)
+ {
+ std::cout<<"NetManager::prepare: listen failed"<<std::endl;
+ return 0;
+ }
+ mdcerr<<"NetManager::prepare: listening on port "<<m_basePort<<"..."<<std::endl;
+
+ return 1;
+}
+
+void NetManager::generateFDset(fd_set *tmpFDs)
+{
+ mdcerr<<"NetManager::generateFDset"<<std::endl;
+
+ FD_ZERO(tmpFDs);
+ FD_SET(m_listenFD,tmpFDs);
+ mdcerr<<"NetManager::generateFDset: adding listen FD="<<m_listenFD<<std::endl;
+// for (Client* tmpClient=clients.first(); tmpClient!=0; tmpClient=clients.next())
+ for (std::list<Client>::iterator tmpClient=clients.begin(); tmpClient != clients.end(); tmpClient++)
+ if (tmpClient->fd()!=-1)
+ {
+ mdcerr<<"NetManager::generateFDset: adding client FD="<<tmpClient->fd()<<std::endl;
+ FD_SET(tmpClient->fd(),tmpFDs);
+ }
+
+ if (m_pipeFD!=-1)
+ {
+ mdcerr<<"NetManager::generateFDset: adding pipeFD="<<m_pipeFD<<std::endl;
+ FD_SET(m_pipeFD,tmpFDs);
+ }
+
+ if ((m_bcFD!=-1) && (!m_strictMode))
+ {
+ mdcerr<<"NetManager::generateFDset: adding m_bcFD="<<m_bcFD<<std::endl;
+ FD_SET(m_bcFD,tmpFDs);
+ }
+}
+
+int NetManager::waitForSomethingToHappen(fd_set *tmpFDs)
+{
+ mdcerr<<"NetManager::waitForSomethingToHappen for 10 seconds"<<std::endl;
+ if (m_firstRun)
+ {
+ tv.tv_sec = 1;
+ m_firstRun=0;
+ }
+ else
+ tv.tv_sec = SELECT_TIMEOUT;
+
+ tv.tv_usec = 0;
+ //generateFDset(tmpFDs);
+ int result=select(getMaxFD(),tmpFDs,0,0,&tv);
+ if (result>0) return 1;
+ else return 0;
+}
+
+int NetManager::getMaxFD()
+{
+ int maxFD(m_listenFD);
+// for (Client* tmpClient=clients.first(); tmpClient!=0; tmpClient=clients.next())
+ for (std::list<Client>::iterator tmpClient=clients.begin(); tmpClient != clients.end(); tmpClient++)
+ if (tmpClient->fd()>maxFD)
+ maxFD=tmpClient->fd();
+
+ if (m_pipeFD>maxFD) maxFD=m_pipeFD;
+ if (m_bcFD>maxFD) maxFD=m_bcFD;
+
+ mdcerr<<"NetManager::getMaxFD()="<<maxFD+1<<std::endl;
+ return maxFD+1;
+}
+
+int fileReadable(const MyString& filename)
+{
+ FILE *file=::fopen(filename.data(), "r");
+ if (file==0)
+ return 0;
+ fclose(file);
+ return 1;
+}
+
+MyString NetManager::getConfigFileName()
+{
+ MyString tmpBase(CONFIGFILEBASENAME);
+
+ if (m_strictMode)
+ tmpBase=STRICTCONFIGFILEBASENAME;
+
+ if (!m_extraConfigFile.isEmpty())
+ m_configStyle=EXTRACONFIGSTYLE;
+
+ MyString tmpFilename;
+ if (m_configStyle==EXTRACONFIGSTYLE)
+ {
+ tmpFilename=m_extraConfigFile;
+ if (fileReadable(tmpFilename))
+ return tmpFilename;
+ return "";
+ }
+ else if (m_configStyle==UNIXCONFIGSTYLE)
+ {
+ tmpFilename=getenv("HOME");
+ tmpFilename+=MyString("/.")+tmpBase;
+ if (fileReadable(tmpFilename))
+ return tmpFilename;
+ tmpFilename="/etc/";
+ tmpFilename+=tmpBase;
+ if (fileReadable(tmpFilename))
+ return tmpFilename;
+ return "";
+ }
+/* else if (m_configStyle==KDE1CONFIGSTYLE)
+ {
+ tmpFilename=getenv("HOME");
+ tmpFilename+=MyString("/.kde/share/config/")+tmpBase;
+ if (fileReadable(tmpFilename))
+ return tmpFilename;
+ tmpFilename=getenv("KDEDIR");
+ tmpFilename+=MyString("/share/config/")+tmpBase;
+ if (fileReadable(tmpFilename))
+ return tmpFilename;
+ return "";
+ }
+ else if (m_configStyle==KDE2CONFIGSTYLE)
+ {
+ FILE *kdeConfig=popen("kde-config --path config","r");
+ if (kdeConfig==0)
+ {
+ std::cout<<"could not execute kde-config, check your KDE 2 installation\n"<<std::endl;
+ return "";
+ };
+ //this should be large enough
+ char buf[4*1024];
+ memset(buf,0,4*1024);
+ fgets(buf,4*1024-1,kdeConfig);
+ // Warning: The return value of plcose may be incorrect due to the
+ // SIGCHLD handler that is installed. Ignore it!
+ pclose(kdeConfig);
+ int length=strlen(buf);
+ if (buf[length-1]=='\n') buf[length-1]='\0';
+ MyString kdeDirs(buf);
+ while (kdeDirs.contains(':'))
+ {
+ MyString nextDir=kdeDirs.left(kdeDirs.find(':'));
+ kdeDirs=kdeDirs.mid(kdeDirs.find(':')+1);
+ nextDir=nextDir+tmpBase;
+ mdcerr<<"trying to open "<<nextDir<<std::endl;
+ if (fileReadable(nextDir))
+ return nextDir;
+ };
+ kdeDirs=kdeDirs+tmpBase;
+ mdcerr<<"trying to open "<<kdeDirs<<std::endl;
+ if (fileReadable(kdeDirs))
+ return kdeDirs;
+ kdeDirs="/etc/";
+ kdeDirs=kdeDirs+tmpBase;
+ if (fileReadable(kdeDirs))
+ return kdeDirs;
+ return "";
+ }*/
+ return "";
+}
+
+int NetManager::run()
+{
+ int continueMainLoop(1);
+ //not forever
+ while(continueMainLoop)
+ {
+ mdcerr<<"\nNetManager::run: next loop: "<<clients.size()<<" clients"<<std::endl;
+ fd_set tmpFDs;
+ generateFDset(&tmpFDs);
+
+ int result=waitForSomethingToHappen(&tmpFDs);
+ mdcerr<<"NetManager::run: something happened..."<<std::endl;
+ //timeout
+ if (result==0)
+ {
+ mdcerr<<"NetManager::run: serverServer=="<<m_serverServer<<std::endl;
+ mdcerr<<"NetManager::run: scanning after timeout"<<std::endl;
+ scan();
+ }
+ else
+ {
+ //a new connection ?
+ if (FD_ISSET(m_listenFD,&tmpFDs))
+ {
+ mdcerr<<"NetManager::run: on m_listenFD"<<std::endl;
+ struct sockaddr_in clientAddress;
+ socklen_t clilen(sizeof(clientAddress));
+// bzero((char*)&clientAddress, clilen);
+ memset((void*)&clientAddress,0,sizeof(clientAddress));
+ int connectionFD=::accept(m_listenFD,(struct sockaddr *) &clientAddress, &clilen);
+ if ((validator.isValid(clientAddress.sin_addr.s_addr)) || (m_strictMode))
+ {
+ mdcerr<<"NetManager::run: adding client"<<std::endl;
+ addClient(connectionFD);
+ m_servedThisPeriod=1;
+ m_refreshTime=m_initialRefreshTime;
+ m_increasedRefreshTime=0;
+ }
+ else
+ {
+ mdcerr<<"NetManager::run: kicking client"<<std::endl;
+ ::close(connectionFD);
+ }
+ }
+ checkClientsAndPipes(&tmpFDs);
+ }
+ serveAndClean();
+ }
+ return 1;
+}
+
+void NetManager::addClient(int socketFD)
+{
+ mdcerr<<"NetManager::addClient on FD="<<socketFD<<std::endl;
+ if (socketFD==-1) return;
+ Client c(this,socketFD,0);
+ clients.push_back(c);
+}
+
+void NetManager::checkClientsAndPipes(fd_set *tmpFDs)
+{
+ mdcerr<<"NetManager::checkClientsAndPipes()"<<std::endl;
+ //actually the clients should not send anything
+// for (Client *tmpClient=clients.first(); tmpClient!=0; tmpClient=clients.next())
+ for (std::list<Client>::iterator tmpClient=clients.begin(); tmpClient != clients.end(); tmpClient++)
+ {
+ mdcerr<<"NetManager::checkClientsAndPipes: checking client"<<std::endl;
+ if (FD_ISSET(tmpClient->fd(),tmpFDs))
+ {
+ mdcerr<<"NetManager::checkClientsAndPipes: client sent something"<<std::endl;
+ tmpClient->read();
+ }
+ }
+
+ //now check wether we received a broadcast
+ //m_bcFD should always be -1 in strictMode
+ if ((m_bcFD!=-1) && (!m_strictMode))
+ {
+ mdcerr<<"NetManager::checkClientsAndPipe: checking bcFD"<<std::endl;
+ //yes !
+ if (FD_ISSET(m_bcFD,tmpFDs))
+ answerBroadcast();
+ }
+
+ //read the stuff from the forked pipe
+ if (m_pipeFD!=-1)
+ {
+ mdcerr<<"NetManager::checkClientsAndPipe: checking pipe"<<std::endl;
+ if (FD_ISSET(m_pipeFD,tmpFDs))
+ {
+ mdcerr<<"NetManager::checkClientsAndPipes: pipe sent something"<<std::endl;
+ int result=readDataFromFD(m_pipeFD);
+ if (result!=1)
+ {
+ ::close(m_pipeFD);
+ m_pipeFD=-1;
+ mdcerr<<"NetManager::checkClientsAndPipes: everything read from pipe from proc "<<m_childPid<<std::endl;
+ processScanResults();
+ }
+ }
+ }
+}
+
+void NetManager::answerBroadcast()
+{
+ //actually we should never get here in strictMode
+ if (m_strictMode) return;
+
+ //this one is called only in checkClientsAndPipes()
+ //if we are sure that we received something on m_bcFD
+ //so we don't need to check here again
+
+ mdcerr<<"NetManager::answerBroadcast: received BC"<<std::endl;
+ struct sockaddr_in sAddr;
+ socklen_t length(sizeof(sockaddr_in));
+ char buf[1024];
+ int result=recvfrom(m_bcFD, (char*)buf, 1024, 0, (sockaddr*)&sAddr,&length);
+ mdcerr<<"NetManager::answerBroadcast: received successfully"<<std::endl;
+ //did recvfrom() succeed ?
+ //our frame is exactly MYFRAMELENGTH bytes big, if the received one has a different size,
+ //it must be something different
+ if (result!=MYFRAMELENGTH) return;
+ //if it has the correct size, it also must have the correct identifier
+ MyFrameType *frame=(MyFrameType*)(void*)buf;
+ if ((ntohl(frame->id)!=MY_ID) ||
+ ((ntohl(frame->unused1)==getpid()) && (ntohl(frame->unused2)==m_startedAt)))
+ {
+ mdcerr<<"NetManager::answerBroadcast: must be the same machine"<<std::endl;
+ return;
+ }
+
+ //mdcerr<<"received "<<ntohl(buf[0])<<" from "<<inet_ntoa(sAddr.sin_addr)<<hex<<" ";
+ //mdcerr<<sAddr.sin_addr.s_addr<<" //"<<ntohl(sAddr.sin_addr.s_addr)<<dec<<std::endl;
+ //will we answer this request ?
+ if (!validator.isValid(sAddr.sin_addr.s_addr))
+ {
+ mdcerr<<"NetManager::answerBroadcast: invalid sender"<<std::endl;
+ return;
+ }
+
+ //create the answering socket
+
+ int answerFD=::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (answerFD==-1)
+ {
+ mdcerr<<"NetManager::answerBroadcast: could not create answering socket"<<std::endl;
+ return;
+ }
+
+ sAddr.sin_family=AF_INET;
+ sAddr.sin_port=htons(m_basePort+1);
+ MyFrameType answerFrame;
+ answerFrame.id=htonl(MY_ID);
+ answerFrame.unused1=0;
+ answerFrame.unused2=0;
+ //don't care about the result
+ mdcerr<<"NetManager::answerBroadcast: sending answer"<<std::endl;
+
+ result=::sendto(answerFD,(char*)&answerFrame,sizeof(answerFrame),0,(sockaddr*)&sAddr,length);
+ mdcerr<<"sent "<<result<<" byte using sendto"<<std::endl;
+ ::close(answerFD);
+ //sent answer
+}
+
+void NetManager::serveAndClean()
+{
+ //try to serve the request
+// for (Client *tmpClient=clients.first(); tmpClient!=0; tmpClient=clients.next())
+ for (std::list<Client>::iterator tmpClient=clients.begin(); tmpClient != clients.end(); tmpClient++)
+ {
+ mdcerr<<"NetManager::serveAndClean: trying to get info"<<std::endl;
+ tmpClient->tryToGetInfo();
+ }
+
+ //try to delete served the clients
+ /** PM: substituted STL code
+ for (Client* tmpClient=clients.first();tmpClient!=0; tmpClient=clients.next())
+ {
+ //if we served the client or if he's already half a minute
+ //connected remove it
+ //this way we get rid of clients if something went wrong and
+ //maybe it's even a security point, I don't know
+ if ((tmpClient->done()) || (tmpClient->age()>30))
+ {
+ mdcerr<<"NetManager::serveAndClean: removing Client"<<std::endl;
+ clients.remove(tmpClient);
+ tmpClient=clients.first();
+ }
+ }*/
+ clients.remove_if(client_is_done());
+}
+
+void NetManager::scan()
+{
+ mdcerr<<"NetManager::scan()"<<std::endl;
+ if (isBeingScanned()) return;
+
+ time_t currentTime=time(0);
+ mdcerr<<"currentTime: "<<currentTime<<" lastUpdate: "<<m_lastUpdate<<std::endl;
+ if ((currentTime-m_lastUpdate)<m_refreshTime) return;
+ mdcerr<<"NetManager::scan: scanning..."<<std::endl;
+
+ m_isBeingScanned=1;
+ int fileDescr[2];
+ ::pipe(fileDescr);
+ mdcerr<<"NetScanner::scan: file-descr[0]: "<<fileDescr[0]<<std::endl;
+ mdcerr<<"NetScanner::scan: file-descr[1]: "<<fileDescr[1]<<std::endl;
+ int pid=fork();
+ if (pid==-1)
+ {
+ mdcerr<<"NetScanner::scan: error occurred"<<std::endl;
+ return;
+ }
+ else if (pid!=0)
+ {
+ //parent
+ ::close(fileDescr[1]);
+ m_pipeFD=fileDescr[0];
+ m_childPid=pid;
+ return;
+ }
+ //child
+ procId="** child ** ";
+ mdcerr<<" NetManager::scan: a child was born"<<std::endl;
+ if (m_strictMode)
+ {
+ mdcerr<<" NetManager::scan: scanning myself in strict mode, becoming serverServer"<<std::endl;
+ doScan();
+ //in the child we don't have to call setServerServer()
+ //since this opens the listening socket, what has to be done
+ //in the parent process
+ m_serverServer=1;
+ }
+ else
+ {
+ int serverAddress=findServerServer();
+ if (serverAddress==0)
+ {
+ mdcerr<<" NetManager::scan: scanning myself, becoming serverServer"<<std::endl;
+ doScan();
+ //in the child we don't have to call setServerServer()
+ //since this opens the listening socket, what has to be done
+ //in the parent process
+ m_serverServer=1;
+ }
+ else
+ {
+ mdcerr<<" NetManager::scan: getting list from serverServer"<<std::endl;
+ getListFromServerServer(serverAddress);
+ m_serverServer=0;
+ }
+ }
+ mdcerr<<" NetScanner::scan: sending information to parent process"<<std::endl;
+ writeDataToFD(fileDescr[1],m_serverServer);
+ mdcerr<<" NetScanner::scan: closed FD: "<<::close(fileDescr[1])<<std::endl;
+ mdcerr<<" NetScanner::scan: exiting now"<<std::endl;
+ ::exit(0);
+}
+
+int NetManager::writeDataToFD(int fd, int serverServer)
+{
+ mdcerr<<" NetManager::writeDataToFD fd="<<fd<<std::endl;
+ m_serveCount++;
+ char buffer[1024];
+
+ int length;
+// for (Node* tmpNode=hostList->first(); tmpNode!=0; tmpNode=hostList->next())
+ for (std::list<Node>::iterator tmpNode=hostList->begin(); tmpNode!=hostList->end(); tmpNode++)
+ {
+ sprintf(buffer,"%u %s\n",tmpNode->ip,tmpNode->name.left(1000).c_str());
+ length=strlen(buffer)+1;
+ const char *currentBuf=buffer;
+ //make sure that everything is written
+ while (length>0)
+ {
+ int result=::write(fd,currentBuf,length);
+ mdcerr<<"NetManager::writeDataToFD: wrote "<<result<<" bytes"<<std::endl;
+ if (result==-1)
+ {
+ perror("hmmpf: ");
+ return 0;
+ }
+ length-=result;
+ currentBuf+=result;
+ }
+ }
+ //and a last line
+ sprintf(buffer,"%d succeeded\n",serverServer);
+ length=strlen(buffer)+1;
+ const char *currentBuf=buffer;
+ //make sure that everything is written
+ while (length>0)
+ {
+ int result=::write(fd,currentBuf,length);
+ if (result==-1) return 0;
+ length-=result;
+ currentBuf+=result;
+ }
+ return 1;
+}
+
+int NetManager::readDataFromFD(int fd)
+{
+ mdcerr<<"NetManager::readDataFromFD"<<std::endl;
+ char tmpBuf[64*1024];
+ int result=::read(fd,tmpBuf,64*1024);
+ mdcerr<<"NetManager::readDataFromFD: read "<<result<<" bytes"<<std::endl;
+ if (result==-1) return -1;
+ if (result==0)
+ {
+ mdcerr<<"NetManager::readDataFromFD: FD was closed"<<std::endl;
+ return 0;
+ }
+ char *newBuf=new char[m_receivedBytes+result];
+ if (m_receiveBuffer!=0) memcpy(newBuf,m_receiveBuffer,m_receivedBytes);
+ memcpy(newBuf+m_receivedBytes,tmpBuf,result);
+ m_receivedBytes+=result;
+ if (m_receiveBuffer!=0) delete [] m_receiveBuffer;
+ m_receiveBuffer=newBuf;
+ // too much data - abort at 2MB to avoid memory exhaustion
+ if (m_receivedBytes>2*1024*1024)
+ return 0;
+
+ return 1;
+}
+
+int NetManager::processScanResults()
+{
+ mdcerr<<"NetManager::processScanResults"<<std::endl;
+ if (m_receiveBuffer==0) return 0;
+ std::list<Node> *newNodes=new std::list<Node>;
+
+ char *tmpBuf=m_receiveBuffer;
+ int bytesLeft=m_receivedBytes;
+ mdcerr<<"m_receivedBytes: "<<m_receivedBytes<<" bytesLeft: "<<bytesLeft<<std::endl;
+ //this should be large enough for a name
+ //and the stuff which is inserted into the buffer
+ //comes only from ourselves ... or attackers :-(
+ char tmpName[1024*4];
+ while (bytesLeft>0)
+ {
+ int tmpIP=2; // well, some impossible IP address, 0 and 1 are already used for the last line of output
+ tmpName[0]='\0';
+ if ((memchr(tmpBuf,0,bytesLeft)==0) || (memchr(tmpBuf,int('\n'),bytesLeft)==0))
+ {
+ delete newNodes;
+ hostList->clear();
+
+ m_lastUpdate=time(0);
+ delete [] m_receiveBuffer;
+ m_receiveBuffer=0;
+ m_receivedBytes=0;
+ m_isInformed=1;
+ m_isBeingScanned=0;
+ return 0;
+ }
+ //mdcerr<<"NetManager::processScanResults: processing -"<<tmpBuf;
+ //since we check for 0 and \n with memchr() we can be sure
+ //at this point that tmpBuf is correctly terminated
+ int length=strlen(tmpBuf)+1;
+ if (length<(4*1024))
+ sscanf(tmpBuf,"%u %s\n",&tmpIP,tmpName);
+
+ bytesLeft-=length;
+ tmpBuf+=length;
+ mdcerr<<"length: "<<length<<" bytesLeft: "<<bytesLeft<<std::endl;
+ if ((bytesLeft==0) && ((tmpIP==0) ||(tmpIP==1)) && (strstr(tmpName,"succeeded")!=0))
+ {
+ mdcerr<<"NetManager::processScanResults: succeeded :-)"<<std::endl;
+ delete hostList;
+ hostList=newNodes;
+
+ m_lastUpdate=time(0);
+ delete [] m_receiveBuffer;
+ m_receiveBuffer=0;
+ m_receivedBytes=0;
+ m_isInformed=1;
+ m_isBeingScanned=0;
+ adjustRefreshTime(tmpIP);
+ enableServerServer(tmpIP);
+ //m_serverServer=tmpIP;
+
+ return 1;
+ }
+ else if (tmpIP!=2)
+ {
+ //mdcerr<<"NetManager::processScanResults: adding host: "<<tmpName<<" with ip: "<<tmpIP<<std::endl;
+ newNodes->push_back(Node(tmpName,tmpIP));
+ }
+ }
+ //something failed :-(
+ delete newNodes;
+ hostList->clear();
+
+ m_lastUpdate=time(0);
+ delete [] m_receiveBuffer;
+ m_receiveBuffer=0;
+ m_receivedBytes=0;
+ m_isInformed=1;
+ m_isBeingScanned=0;
+
+ mdcerr<<"NetScanner::processScanResult: finished"<<std::endl;
+ return 0;
+}
+
+void NetManager::adjustRefreshTime(int serverServer)
+{
+ //we are becoming server server
+ if (((m_serverServer==0) && (serverServer)) || (m_servedThisPeriod))
+ {
+ m_increasedRefreshTime=0;
+ m_refreshTime=m_initialRefreshTime;
+ }
+ //nobody accessed the server since the last update
+ //so increase the refresh time
+ //this should happen more seldom to the serverServer
+ //than to others
+ else
+ {
+ //up to the 16 times refresh time
+ if (m_increasedRefreshTime<4)
+ {
+ m_increasedRefreshTime++;
+ m_refreshTime*=2;
+ };
+ };
+ m_servedThisPeriod=0;
+
+}
+
+void NetManager::enableServerServer(int on)
+{
+ mdcerr<<"NetManager::enableServerServer: "<<on<<std::endl;
+ //in strictMode we don't listen to broadcasts from the network
+ if (m_strictMode) return;
+
+ m_serverServer=on;
+ if (on)
+ {
+ //nothing has to be done
+ if (m_bcFD!=-1) return;
+ // otherwise create the socket which will listen for broadcasts
+ sockaddr_in my_addr;
+ my_addr.sin_family=AF_INET;
+ my_addr.sin_port=htons(m_basePort);
+ my_addr.sin_addr.s_addr=0;
+
+ m_bcFD=::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (m_bcFD==-1)
+ {
+ mdcerr<<"NetManager::enableServerServer: socket() failed"<<std::endl;
+ m_serverServer=0;
+ return;
+ };
+ int on(1);
+ int result=setsockopt(m_bcFD, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on));
+ if (result!=0)
+ {
+ mdcerr<<"NetManager::enableServerServer: setsockopt(SO_REUSEADDR) failed"<<std::endl;
+ m_serverServer=0;
+ ::close(m_bcFD);
+ m_bcFD=-1;
+ return;
+ };
+ result=::bind(m_bcFD, (struct sockaddr *) &my_addr, sizeof(my_addr));
+ if (result!=0)
+ {
+ mdcerr<<"NetManager::enableServerServer: bind (UDP) failed"<<std::endl;
+ m_serverServer=0;
+ ::close(m_bcFD);
+ m_bcFD=-1;
+ return;
+ };
+ }
+ else
+ {
+ ::close(m_bcFD);
+ m_bcFD=-1;
+ };
+}
+
+int NetManager::findServerServer()
+{
+ mdcerr<<" NetManager::findServerServer"<<std::endl;
+ //actually this should never be called in strictMode
+ if (m_strictMode) return 0;
+ if (!validator.isValid(m_broadcastAddress))
+ {
+ mdcerr<<" NetManager::findServerServer: invalid broadcastAddress"<<std::endl;
+ return 0;
+ };
+ //create a socket for sending the broadcast
+ //we don't have to set SO_REUSEADDR, since we don't call bind()
+ //to this socket
+ int requestFD=::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (requestFD==-1)
+ {
+ mdcerr<<" NetManager::findServerServer: could not create request socket"<<std::endl;
+ return 0;
+ };
+
+ int on(1);
+ //this is actually the only socket which will send broacasts
+ int result=setsockopt(requestFD, SOL_SOCKET, SO_BROADCAST,(char*)&on, sizeof(on));
+ if (result!=0)
+ {
+ mdcerr<<"setsockopt(SO_BROADCAST) failed"<<std::endl;
+ ::close(requestFD);
+ return 0;
+ };
+
+ //create a socket for receiving the answers
+ int answerFD=::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (answerFD==-1)
+ {
+ mdcerr<<" NetManager::findServerServer"<<std::endl;
+ ::close(requestFD);
+ return 0;
+ };
+
+ //since this socket will be bound, we have to set SO_REUSEADDR
+ result=setsockopt(answerFD, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on));
+ if (result!=0)
+ {
+ mdcerr<<"setsockopt(SO_REUSEADDR) failed"<<std::endl;
+ ::close(answerFD);
+ ::close(requestFD);
+ return 0;
+ };
+
+ sockaddr_in my_addr;
+ my_addr.sin_family=AF_INET;
+ my_addr.sin_port=htons(m_basePort+1);
+ my_addr.sin_addr.s_addr=0;
+ //this one has to be bound
+ result=::bind(answerFD, (struct sockaddr *) &my_addr, sizeof(my_addr));
+ if (result!=0)
+ {
+ mdcerr<<"bind (UDP) failed"<<std::endl;
+ ::close(answerFD);
+ ::close(requestFD);
+ return 0;
+ };
+
+ //now send the broadcast
+ struct sockaddr_in sAddr;
+ sAddr.sin_addr.s_addr=m_broadcastAddress;
+ sAddr.sin_family=AF_INET;
+ sAddr.sin_port=htons(m_basePort);
+ socklen_t length(sizeof(sockaddr_in));
+ mdcerr<<" NetManager::findServerServer: broadcasting to: "
+ <<std::ios::hex<<m_broadcastAddress<<std::ios::dec<<std::endl;
+
+ MyFrameType requestFrame;
+ requestFrame.id=htonl(MY_ID);
+ requestFrame.unused1=htonl(getppid());
+ requestFrame.unused2=htonl(m_startedAt);
+
+ result=::sendto(requestFD,(char*)&requestFrame,sizeof(requestFrame),0,(sockaddr*)&sAddr,length);
+ ::close(requestFD);
+ if (result!=MYFRAMELENGTH)
+ {
+ mdcerr<<" NetManager::findServerServer: sent wrong number of bytes: "<<result<<std::endl;
+ ::close(answerFD);
+ return 0;
+ };
+ //wait for an answer
+ struct timeval tv;
+ tv.tv_sec=0;
+ tv.tv_usec=1000*250; //0.1 sec
+ fd_set fdSet;
+ FD_ZERO(&fdSet);
+ FD_SET(answerFD,&fdSet);
+ result=select(answerFD+1,&fdSet,0,0,&tv);
+ if (result<0)
+ {
+ mdcerr<<" NetManager::findServerServer: select() failed: "<<result<<std::endl;
+ mdcerr<<" NetManager::findServerServer: answerFD="<<answerFD<<std::endl;
+ perror("select:");
+ ::close(answerFD);
+ return 0;
+ }
+ if (result==0)
+ {
+ mdcerr<<" NetManager::findServerServer: nobody answered "<<std::endl;
+ ::close(answerFD);
+ return 0;
+ }
+ mdcerr<<"received offer "<<std::endl;
+ struct sockaddr_in addr;
+ length=sizeof(sockaddr_in);
+ char buf[1024];
+ result=recvfrom(answerFD, (char*)buf, 1024, 0, (sockaddr*) &addr,&length);
+ if (result!=MYFRAMELENGTH)
+ {
+ mdcerr<<" NetManager::findServerServer: wrong number of bytes: "<<result<<std::endl;
+ ::close(answerFD);
+ return 0;
+ };
+ MyFrameType *frame=(MyFrameType*)(void*)buf;
+ //wrong identifier ?
+ if (ntohl(frame->id)!=MY_ID)
+ {
+ mdcerr<<" NetManager::findServerServer: wrong id"<<std::endl;
+ ::close(answerFD);
+ return 0;
+ };
+
+ mdcerr<<"received from "<<inet_ntoa(addr.sin_addr)<<std::endl;
+
+ ::close(answerFD);
+ //return the ip of the server server in network byte order
+ return addr.sin_addr.s_addr;
+}
+
+void NetManager::getListFromServerServer( int address)
+{
+ mdcerr<<"NetManager::getListFromServerServer"<<std::endl;
+ //actually we should never get here in strictMode
+ if (m_strictMode) return;
+ //open a tcp socket to the serverserver
+ int serverServerFD=::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (serverServerFD==-1)
+ return;
+ sockaddr_in addr;
+ //we get the address already in network byte order
+ addr.sin_addr.s_addr=address;
+ addr.sin_family=AF_INET;
+ addr.sin_port=htons(m_basePort);
+ int result=::connect(serverServerFD,(sockaddr*)&addr,sizeof(addr));
+ if (result!=0)
+ {
+ ::close(serverServerFD);
+ return;
+ };
+ do
+ {
+ result=readDataFromFD(serverServerFD);
+ } while (result==1);
+ ::close(serverServerFD);
+ processScanResults();
+ mdcerr<<"NetManager::getListFromServerServer succeeded"<<std::endl;
+}
+
+void NetManager::printState()
+{
+ std::cerr<<"LAN Information Server Lisa "MYVERSION"\nAlexander Neundorf <neundorf@kde.org>\n";
+ std::cerr<<"Reading options from config file: "<<m_usedConfigFileName<<std::endl;
+ std::cerr<<"StrictMode: "<<m_strictMode<<std::endl;
+ std::cerr<<"ServerServer: "<<m_serverServer<<std::endl;
+ std::cerr<<"UseNmblookup: "<<m_useNmblookup<<std::endl;
+ std::cerr<<"Pinging: "<<ipRangeStr<<std::endl;
+ std::cerr<<"Allowed hosts: "<<validator.validAddresses()<<std::endl;
+ std::cerr<<"Broadcasting to: "<<std::ios::hex<<ntohl(m_broadcastAddress)<<std::ios::dec<<std::endl;
+ std::cerr<<"Initial update period: "<<m_initialRefreshTime<<" seconds"<<std::endl;
+ std::cerr<<"Current update period: "<<m_refreshTime<<" seconds"<<std::endl;
+ std::cerr<<"Last update: "<<time(0)-m_lastUpdate<<" seconds over"<<std::endl;
+ std::cerr<<"Waiting "<<m_firstWait<<" 1/100th seconds for echo answers on the first try"<<std::endl;
+ std::cerr<<"Waiting "<<m_secondWait<<" 1/100th seconds for echo answers on the second try"<<std::endl;
+ std::cerr<<"Sending "<<m_maxPings<<" echo requests at once"<<std::endl;
+ std::cerr<<"Publishing unnamed hosts: "<<m_deliverUnnamedHosts<<std::endl;
+ std::cerr<<"Already served "<<m_serveCount<<" times"<<std::endl;
+}
+
+//this one is not used at the moment
+/*int NetManager::uptime()
+{
+ return (time(0)-m_startedAt);
+};*/
diff --git a/lanbrowsing/lisa/netmanager.h b/lanbrowsing/lisa/netmanager.h
new file mode 100644
index 00000000..dee5fb27
--- /dev/null
+++ b/lanbrowsing/lisa/netmanager.h
@@ -0,0 +1,109 @@
+/* netmanager.h
+ *
+ * Copyright (c) 1998, 1999, Alexander Neundorf
+ * alexander.neundorf@rz.tu-ilmenau.de
+ *
+ * You may distribute under the terms of the GNU General Public
+ * License as specified in the COPYING file.
+ *
+ * This program 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 General Public License for more details.
+ *
+ */
+
+#ifndef NETMANAGER_H
+#define NETMANAGER_H
+
+#include <list>
+
+#include "netscanner.h"
+#include "client.h"
+#include "mystring.h"
+#include "configfile.h"
+#include "lisadefines.h"
+
+struct MyFrameType
+{
+ int id;
+ //keep some room for later extensions
+ int unused1;
+ int unused2;
+ int unused3;
+};
+
+#define MYFRAMELENGTH 16
+
+class NetManager:public NetScanner
+{
+ public:
+ NetManager(int& rawSocketFD, int portToUse, MyString configFile, int configStyle=UNIXCONFIGSTYLE, int strictMode=0);
+ ~NetManager();
+
+ int prepare();
+ int run();
+ int writeDataToFD(int fd, int serverServer);
+
+ void readConfig();
+ void configure(Config& config);
+ int isBeingScanned() {return m_isBeingScanned;};
+ int isInformed() {return m_isInformed;};
+ //int uptime();
+ void printState();
+ protected:
+ int m_listenFD;
+ int m_bcFD;
+ int m_basePort;
+
+ int m_pipeFD;
+ char *m_receiveBuffer;
+ size_t m_receivedBytes;
+
+ struct timeval tv;
+ pid_t m_childPid;
+ time_t m_lastUpdate;
+ time_t m_startedAt;
+
+ int m_isInformed;
+ int m_isBeingScanned;
+ int m_firstRun;
+ int m_serverServer;
+ int m_servedThisPeriod;
+
+ int m_serveCount;
+ int m_refreshTime;
+ int m_initialRefreshTime;
+ int m_increasedRefreshTime;
+ int m_broadcastAddress;
+ std::list<Client> clients;
+ struct client_is_done : std::unary_function<Client, bool>
+ {
+ bool operator() (Client& c)
+ {
+ return (c.done() != 0 || c.age() > 30);
+ }
+ };
+
+ int getMaxFD();
+ void generateFDset(fd_set *tmpFDs);
+ //returns 0 on timeout, otherwise 1
+ int waitForSomethingToHappen(fd_set *tmpFDs);
+ void scan();
+ void addClient(int socketFD);
+ void checkClientsAndPipes(fd_set *tmpFDs);
+ int readDataFromFD(int fd);
+ int processScanResults();
+ int findServerServer();
+ void getListFromServerServer(int address);
+ void enableServerServer(int on);
+ void serveAndClean();
+ void answerBroadcast();
+ void adjustRefreshTime(int serverServer);
+
+ MyString m_extraConfigFile;
+ int m_configStyle;
+ MyString getConfigFileName();
+ MyString m_usedConfigFileName;
+};
+#endif
diff --git a/lanbrowsing/lisa/netscanner.cpp b/lanbrowsing/lisa/netscanner.cpp
new file mode 100644
index 00000000..acf0515c
--- /dev/null
+++ b/lanbrowsing/lisa/netscanner.cpp
@@ -0,0 +1,663 @@
+/* netscanner.cpp
+ *
+ * Copyright (c) 2000, Alexander Neundorf,
+ * neundorf@kde.org
+ *
+ * You may distribute under the terms of the GNU General Public
+ * License as specified in the COPYING file.
+ *
+ * This program 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 General Public License for more details.
+ *
+ */
+
+#include "config.h"
+#include "netscanner.h"
+#include "ipaddress.h"
+#include "lisadefines.h"
+#include <iostream>
+
+#ifdef LISA_DEBUG
+#undef LISA_DEBUG
+#endif
+#define LISA_DEBUG 0
+
+#ifdef dcerr
+#undef dcerr
+#endif
+
+#ifdef mdcerr
+#undef mdcerr
+#endif
+
+#define dcerr if (LISA_DEBUG==1) std::cerr<<"NetScanner::"
+#define mdcerr if (LISA_DEBUG==1) std::cerr<<procId<<" NetScanner::"
+
+#include <stdio.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#ifdef __osf__
+#undef BYTE_ORDER
+#define _OSF_SOURCE
+#undef _MACHINE_ENDIAN_H_
+#undef __STDC__
+#define __STDC__ 0
+#include <netinet/ip.h>
+#undef __STDC__
+#define __STDC__ 1
+#endif
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+
+#ifndef INADDR_NONE
+#define INADDR_NONE -1
+#endif
+
+struct ICMPEchoRequest
+{
+ unsigned char type;
+ unsigned char code;
+ unsigned short int checkSum;
+ unsigned short id;
+ unsigned short seqNumber;
+};
+
+unsigned short in_cksum(unsigned short *addr, int len)
+{
+ int nleft = len;
+ int sum(0);
+ unsigned short *w = addr;
+ unsigned short answer = 0;
+
+ /*
+ * Our algorithm is simple, using a 32 bit accumulator (sum), we add
+ * sequential 16 bit words to it, and at the end, fold back all the
+ * carry bits from the top 16 bits into the lower 16 bits.
+ */
+ while (nleft > 1)
+ {
+ sum += *w++;
+ nleft -= 2;
+ }
+
+ /* 4mop up an odd byte, if necessary */
+ if (nleft == 1)
+ {
+ *(unsigned char *)(&answer) = *(unsigned char *)w ;
+ sum += answer;
+ }
+
+ /* 4add back carry outs from top 16 bits to low 16 bits */
+ sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
+ sum += (sum >> 16); /* add carry */
+ answer = ~sum; /* truncate to 16 bits */
+ return(answer);
+}
+
+
+NetScanner::NetScanner(int& rawSocketFD, int strictMode)
+:procId("")
+,m_firstWait(5)
+,m_secondWait(15)
+,m_strictMode(strictMode)
+,m_rawSocketFD(rawSocketFD)
+,validator()
+,ipRangeStr(";")
+,m_maxPings(256)
+,m_deliverUnnamedHosts(0)
+,m_useNmblookup(0)
+,hostList(0)
+,tmpIPRange("")
+{}
+
+NetScanner::~NetScanner()
+{
+// std::cerr<<"----------- Netscanner dtor "<<std::endl;
+ delete hostList;
+ ::close(m_rawSocketFD);
+}
+
+void addMissingSemicolon(MyString& text)
+{
+ if (text.isEmpty()) return;
+ if (text[text.length()-1]!=';')
+ text+=';';
+}
+
+void NetScanner::configure(Config& config)
+{
+ //ranges are not allowed in strict mode
+ if (!m_strictMode)
+ {
+ ipRangeStr=stripWhiteSpace(config.getEntry("PingAddresses",""));
+ addMissingSemicolon(ipRangeStr);
+ }
+ MyString pingNames=stripWhiteSpace(config.getEntry("PingNames",""));
+ addMissingSemicolon(pingNames);
+ MyString nextName;
+ int semicolonPos=pingNames.find(';');
+ int hostsAdded(0);
+ while (semicolonPos!=-1)
+ {
+ nextName=pingNames.left(semicolonPos);
+ mdcerr<<"configure(): looking up -"<<nextName<<"-"<<std::endl;
+ //now the name lookup
+ in_addr server_addr;
+ hostent *hp=gethostbyname(nextName.data());
+ if (hp!=0)
+ {
+ if ((m_strictMode) && (hostsAdded>=STRICTMODEMAXHOSTS))
+ break;
+ memcpy(&server_addr, hp->h_addr, sizeof(server_addr));
+ char *ip=inet_ntoa(server_addr);
+ mdcerr<<"configure(): looking up "<<nextName<<" gives -"<<ip<<"-"<<std::endl;
+ ipRangeStr=ipRangeStr+ip+';';
+ hostsAdded++;
+ }
+
+ pingNames=pingNames.mid(semicolonPos+1);
+ semicolonPos=pingNames.find(';');
+ }
+ if ((!ipRangeStr.isEmpty()) && (ipRangeStr[0]==';'))
+ ipRangeStr=ipRangeStr.mid(1);
+ m_deliverUnnamedHosts=config.getEntry("DeliverUnnamedHosts",0);
+ m_useNmblookup=config.getEntry("SearchUsingNmblookup",0);
+ m_maxPings=config.getEntry("MaxPingsAtOnce",256);
+ m_firstWait=config.getEntry("FirstWait",5);
+ m_secondWait=config.getEntry("SecondWait",15);
+ if (m_firstWait<1) m_firstWait=1;
+ if (m_maxPings<8) m_maxPings=8;
+ if (m_maxPings>1024) m_maxPings=1024;
+ //on some systems (Solaris ?) select() doesn't work correctly
+ // if the microseconds are more than 1.000.000
+ if (m_firstWait>99) m_firstWait=99;
+ if (m_secondWait>99) m_secondWait=99;
+ mdcerr<<"configure(): "<<ipRangeStr<<std::endl;
+}
+
+struct in_addr NetScanner::getIPfromArray(unsigned int index)
+{
+ //mdcerr<<std::endl<<"*** start ***"<<std::endl;
+ unsigned int tmpIndex(0),indexLeft(index);
+ resetIPRange();
+ MyString tmp(getNextIPRange());
+// mdcerr<<"NetScanner::getIPFromArray: -"<<tmp<<"-"<<std::endl;
+ while (!tmp.isEmpty())
+ {
+ if (tmp.contains('/'))
+ {
+ //mdcerr<<"net/mask combination detected"<<std::endl;
+ MyString netStr(tmp.left(tmp.find("/")));
+ MyString maskStr(tmp.mid(tmp.find("/")+1));
+ unsigned int mask(IPAddress(maskStr).asInt());
+ unsigned int net(IPAddress(netStr).asInt()&mask);
+ if ((~mask)<indexLeft)
+ {
+ indexLeft=indexLeft-(~mask+1);
+ tmpIndex+=(~mask)+1;
+ //mdcerr<<"i: "<<tmpIndex<<" left: "<<indexLeft<<std::endl;
+ }
+ else
+ {
+ net+=indexLeft;
+ return IPAddress(net).asStruct();
+ //return string2Struct(ipInt2String(net));
+ }
+ }
+ else if (tmp.contains('-')==1)
+ {
+ //mdcerr<<"single range detected"<<std::endl;
+ MyString fromIPStr(tmp.left(tmp.find("-")));
+ MyString toIPStr(tmp.mid(tmp.find("-")+1));
+ //mdcerr<<"fromIPStr: "<<fromIPStr<<std::endl;
+ //mdcerr<<"toIPStr: "<<toIPStr<<std::endl;
+ unsigned int fromIP(IPAddress(fromIPStr).asInt());
+ unsigned int toIP(IPAddress(toIPStr).asInt());
+ //unsigned int fromIP(ipString2Int(fromIPStr)), toIP(ipString2Int(toIPStr));
+ //index hinter diesem bereich
+ if ((fromIP+indexLeft)>toIP)
+ {
+ tmpIndex+=1+toIP-fromIP;
+ indexLeft=indexLeft-(1+toIP-fromIP);
+ //mdcerr<<"i: "<<tmpIndex<<" left: "<<indexLeft<<std::endl;
+ }
+ //index in diesem bereich
+ else
+ {
+ fromIP+=indexLeft;
+ return IPAddress(fromIP).asStruct();
+ //return string2Struct(ipInt2String(fromIP));
+ }
+
+ }
+ else if (tmp.contains('-')==4)
+ {
+ //mdcerr<<"multiple range detected"<<std::endl;
+ int cp(tmp.find('-'));
+ int from1(atoi(tmp.left(cp).data()));
+ tmp=tmp.mid(cp+1);
+
+ cp=tmp.find('.');
+ int to1(atoi(tmp.left(cp).data()));
+ tmp=tmp.mid(cp+1);
+
+ cp=tmp.find('-');
+ int from2(atoi(tmp.left(cp).data()));
+ tmp=tmp.mid(cp+1);
+
+ cp=tmp.find('.');
+ int to2(atoi(tmp.left(cp).data()));
+ tmp=tmp.mid(cp+1);
+
+ cp=tmp.find('-');
+ int from3(atoi(tmp.left(cp).data()));
+ tmp=tmp.mid(cp+1);
+
+ cp=tmp.find('.');
+ int to3(atoi(tmp.left(cp).data()));
+ tmp=tmp.mid(cp+1);
+
+ cp=tmp.find('-');
+ int from4(atoi(tmp.left(cp).data()));
+ tmp=tmp.mid(cp+1);
+
+ int to4(atoi(tmp.data()));
+
+ unsigned int count((1+to4-from4)*(1+to3-from3)*(1+to2-from2)*(1+to1-from1));
+ if (count<indexLeft)
+ {
+ tmpIndex+=count;
+ indexLeft-=count;
+ //mdcerr<<"i: "<<tmpIndex<<" left: "<<indexLeft<<std::endl;
+ }
+ else
+ {
+ for (int b1=from1; b1<=to1; b1++)
+ for (int b2=from2; b2<=to2; b2++)
+ for (int b3=from3; b3<=to3; b3++)
+ for (int b4=from4; b4<=to4; b4++)
+ {
+ if (tmpIndex==index)
+ {
+ return IPAddress(b1,b2,b3,b4).asStruct();
+ };
+ tmpIndex++;
+ indexLeft--;
+ //mdcerr<<"i: "<<tmpIndex<<" left:"<<indexLeft<<std::endl;
+ }
+ }
+ }
+ //single IP address
+ else if (tmp.contains('.')==3)
+ {
+ //mdcerr<<"single IP address detected"<<std::endl;
+ //if (tmpIndex==index) return string2Struct(tmp);
+ if (tmpIndex==index) return IPAddress(tmp).asStruct();
+ else
+ {
+ tmpIndex++;
+ indexLeft--;
+ //mdcerr<<"i: "<<tmpIndex<<" left: "<<indexLeft<<std::endl;
+ }
+ }
+ //mdcerr<<"nextIPRange: *"<<tmp<<"*"<<std::endl;
+ tmp=getNextIPRange();
+ }
+ return IPAddress("0.0.0.0").asStruct();
+}
+
+void NetScanner::resetIPRange()
+{
+ tmpIPRange=ipRangeStr;
+}
+
+MyString NetScanner::getNextIPRange()
+{
+ if (tmpIPRange.contains(';')<1) return "";
+ int cp(tmpIPRange.find(';'));
+ MyString tmp(tmpIPRange.left(cp));
+ tmpIPRange=tmpIPRange.mid(cp+1);
+ return tmp;
+}
+
+char* NetScanner::ip2Name(struct in_addr ip)
+{
+ struct hostent *hostname=0;
+ // Set the hostname of node
+ if ( ( hostname = gethostbyaddr( (char *) &ip.s_addr, 4, AF_INET ) ) == 0 )
+ {
+ mdcerr << "ip2Name gethostbyname* error" << std::endl;
+ return inet_ntoa( ip );
+ }
+ mdcerr<<"ip2name -"<<hostname->h_name<<std::endl;
+ return hostname->h_name;
+}
+
+void NetScanner::nmblookupScan(std::list<Node>* newList)
+{
+ mdcerr<<"nmblookupScan()"<<std::endl;
+ //newList->clear();
+ FILE * nmblookupFile=popen("nmblookup \"*\"","r");
+ //no success
+ if (nmblookupFile==0)
+ {
+ mdcerr<<"nmblookupScan(): could not start nmblookup"<<std::endl;
+ return;
+ };
+ MyString dummy("");
+ char *receiveBuffer=0;
+ int bufferSize(0);
+ int nmblookupFd=fileno(nmblookupFile);
+ struct timeval tv;
+ fd_set fds;
+ int done(0);
+ int timeOuts(0);
+ char *tmpBuf=new char[16*1024];
+ do
+ {
+ FD_ZERO(&fds);
+ FD_SET(nmblookupFd,&fds);
+ tv.tv_sec=10;
+ tv.tv_usec=0;
+ int result=select(nmblookupFd+1,&fds,0,0,&tv);
+ //error
+ if (result<0)
+ done=1;
+ //timeout
+ else if (result==0)
+ {
+ timeOuts++;
+ //3 time outs make 30 seconds, this should be *much* more than enough
+ if (timeOuts>=3)
+ done=1;
+ }
+ else if (result>0)
+ {
+ //read stuff
+ int bytesRead=::read(nmblookupFd,tmpBuf,16*1024);
+ //pipe closed
+ if (bytesRead==0)
+ done=1;
+ else
+ {
+ char *newBuf=new char[bufferSize+bytesRead];
+ if (receiveBuffer!=0)
+ {
+ memcpy(newBuf,receiveBuffer,bufferSize);
+ delete [] receiveBuffer;
+ }
+ memcpy(newBuf+bufferSize,tmpBuf,bytesRead);
+ receiveBuffer=newBuf;
+ bufferSize+=bytesRead;
+ }
+ }
+ } while (!done);
+
+ // Warning: The return value of pclose may be incorrect due to the
+ // SIGCHLD handler that is installed. Ignore it!
+ pclose(nmblookupFile);
+
+ delete [] tmpBuf;
+ //we received nothing
+ if (receiveBuffer==0)
+ return;
+
+ //check for a terrminating '\0'
+ if (receiveBuffer[bufferSize-1]=='\0')
+ receiveBuffer[bufferSize-1]='\0';
+
+ //std::cerr<<receiveBuffer<<std::endl;
+
+ tmpBuf=receiveBuffer;
+ int bytesLeft=bufferSize;
+
+ int bufferState=0;
+ while (bytesLeft>0)
+ {
+ //mdcerr<<"bytesLeft: "<<bytesLeft<<" received: "<<bufferSize<<std::endl;
+ //since we added a terminating \0 we can be sure here
+ char *endOfLine=(char*)memchr(tmpBuf,'\n',bytesLeft);
+ //point to the last character
+ if (endOfLine==0)
+ endOfLine=receiveBuffer+bufferSize-1;
+
+ //0-terminate the string
+ *endOfLine='\0';
+ //now tmpBuf to endOfLine is a 0-terminated string
+ int strLength=strlen(tmpBuf);
+ //hmm, if this happens, there must be something really wrong
+ if (strLength>1000)
+ break;
+
+ bytesLeft=bytesLeft-strLength-1;
+
+ if (bufferState==0)
+ {
+ if (isdigit(tmpBuf[0]))
+ bufferState=1;
+ }
+ //yes, no else !
+ if (bufferState==1)
+ {
+ char tmpIP[1024];
+ //std::cerr<<"tmpBuf: -"<<tmpBuf<<"-"<<std::endl;
+ if (sscanf(tmpBuf,"%s *<00>\n",tmpIP) == 1) {
+ mdcerr<<"nmblookupScan: tmpIP: -"<<tmpIP<<"-"<<std::endl;
+ struct sockaddr_in addr;
+ if ((addr.sin_addr.s_addr = inet_addr(tmpIP)) != INADDR_NONE)
+ if (!hostAlreadyInList(addr.sin_addr.s_addr,newList))
+ {
+ if (validator.isValid(addr.sin_addr.s_addr))
+ {
+ mdcerr<<"nmblookupScan: adding "<<inet_ntoa(addr.sin_addr)<<std::endl;
+ newList->push_back(Node(dummy,addr.sin_addr.s_addr));
+ }
+ }
+ }
+ }
+ tmpBuf=endOfLine+1;
+ };
+ mdcerr<<"nmblookupScan: finished"<<std::endl;
+ delete [] receiveBuffer;
+}
+
+void NetScanner::pingScan(std::list<Node>* newList) //the ping-version
+{
+ mdcerr<<"pingScan()"<<std::endl;
+ //newList->clear();
+ MyString dummy("");
+ mdcerr<<"pingScan: m_maxPings: "<<m_maxPings<<std::endl;
+
+ pid_t pid=getpid();
+ ICMPEchoRequest echo;
+ echo.type=ICMP_ECHO;
+ echo.code=0;
+ echo.id=pid;
+ echo.seqNumber=0;
+ echo.checkSum=0;
+ echo.checkSum=in_cksum((unsigned short *)&echo,8);
+
+ char receiveBuf[16*1024];
+ //before we start first read everything what might be in the receive buffer
+ //of the raw socket
+
+ timeval tv1;
+ //wait a moment for answers
+ tv1.tv_sec = 0;
+ tv1.tv_usec = 0;
+ fd_set clearSet;
+ FD_ZERO(&clearSet);
+ FD_SET(m_rawSocketFD,&clearSet);
+ while(select(m_rawSocketFD,&clearSet,0,0,&tv1)>0)
+ {
+ ::recvfrom(m_rawSocketFD,(char*)&receiveBuf,16*1024,0,0,0);
+ tv1.tv_sec = 0;
+ tv1.tv_usec = 0;
+ FD_ZERO(&clearSet);
+ FD_SET(m_rawSocketFD,&clearSet);
+ }
+ //now the buffer should be empty
+
+ //wait a moment for answers
+ tv1.tv_sec = 0;
+ tv1.tv_usec = m_firstWait*10*1000;//0.5 sec
+
+ int loopCount(2);
+ if (m_secondWait<0)
+ loopCount=1;
+ for (int repeatOnce=0; repeatOnce<loopCount; repeatOnce++)
+ {
+ mdcerr<<"******************** starting loop *****************"<<std::endl;
+ unsigned int current(0);
+ int finished(0);
+ while (!finished)
+ {
+ for (int con=0; con<m_maxPings; con++)
+ {
+ struct in_addr tmpIP;
+ do
+ {
+ tmpIP=getIPfromArray(current);
+ current++;
+// mdcerr<<"pingScan(): trying "<<inet_ntoa(tmpIP)<<std::endl;
+ if (hostAlreadyInList(tmpIP.s_addr,newList))
+ mdcerr<<"already in list :-)"<<std::endl;
+ if (!validator.isValid(tmpIP.s_addr))
+ mdcerr<<"pingScan(): invalid IP :-("<<std::endl;
+ //ping only hosts which are allowed to receive the results
+ //and which are not in the list
+ } while ( (tmpIP.s_addr!=0)
+ && ((!validator.isValid(tmpIP.s_addr))
+ || (hostAlreadyInList(tmpIP.s_addr,newList))));
+
+ finished=(tmpIP.s_addr==0);
+ if (!finished)
+ {
+ //send the icmp echo request
+ struct sockaddr_in toAddr;
+ toAddr.sin_family = AF_INET;
+ toAddr.sin_addr = tmpIP;
+ toAddr.sin_port = 0;
+ (void)sendto(m_rawSocketFD,(char*)&echo,sizeof(echo),0,(sockaddr*)&toAddr,sizeof(toAddr));
+ //int sb=sendto(sockFD,(char*)&echo,sizeof(echo),0,(sockaddr*)&toAddr,sizeof(toAddr));
+// mdcerr<<"pingScan: pinging "<<inet_ntoa(toAddr.sin_addr)<<std::endl;
+ }
+ else break;
+ }
+ select(0,0,0,0,&tv1);
+ //now read the answers, hopefully
+ struct sockaddr_in fromAddr;
+ socklen_t length(sizeof(fromAddr));
+ int received(0);
+
+ fd_set sockFDset;
+ FD_ZERO(&sockFDset);
+ FD_SET(m_rawSocketFD,&sockFDset);
+ tv1.tv_sec=0;
+ tv1.tv_usec=0;
+ while(select(m_rawSocketFD+1,&sockFDset,0,0,&tv1)>0)
+ {
+ received=recvfrom(m_rawSocketFD, (char*)&receiveBuf, 16*1024, 0,
+ (sockaddr*)&fromAddr, &length);
+ if (received!=-1)
+ {
+// mdcerr<<"pingScan: received from "<<inet_ntoa(fromAddr.sin_addr)<<" "<<received<<" b, ";
+ struct ip *ipFrame=(ip*)&receiveBuf;
+ int icmpOffset=(ipFrame->ip_hl)*4;
+ icmp *recIcmpFrame=(icmp*)(receiveBuf+icmpOffset);
+ int iType=recIcmpFrame->icmp_type;
+ //if its a ICMP echo reply
+ if ((iType==ICMP_ECHOREPLY)
+ //to an echo request we sent
+ && (recIcmpFrame->icmp_id==pid)
+ //and the host is not yet in the list
+ && (!hostAlreadyInList(fromAddr.sin_addr.s_addr,newList)))
+ {
+ //this is an answer to our request :-)
+// mdcerr<<"pingScan: adding "<<inet_ntoa(fromAddr.sin_addr)<<std::endl;
+ newList->push_back(Node(dummy,fromAddr.sin_addr.s_addr));
+ }
+ }
+ tv1.tv_sec=0;
+ tv1.tv_usec=0;
+ FD_ZERO(&sockFDset);
+ FD_SET(m_rawSocketFD,&sockFDset);
+ //FD_SET(sockFD,&sockFDset);
+ }
+ }
+ tv1.tv_sec = 0;
+ tv1.tv_usec = m_secondWait*10*1000;//0.5 sec
+ }
+ mdcerr<<"pingScan() ends"<<std::endl;
+}
+
+void NetScanner::doScan()
+{
+ mdcerr<<"doScan"<<std::endl;
+ //child
+ std::list<Node>* tmpPingList=new std::list<Node>;
+ mdcerr<<"doScan: created list"<<std::endl;
+ if (m_useNmblookup)
+ nmblookupScan(tmpPingList);
+ pingScan(tmpPingList);
+ // get the names from cache or lookup
+ completeNames(tmpPingList);
+ mdcerr<<"doScan: completed names"<<std::endl;
+ if (m_deliverUnnamedHosts==0)
+ removeUnnamedHosts(tmpPingList);
+
+ mdcerr<<"doScan: added hosts"<<std::endl;
+
+ delete hostList;
+ hostList=tmpPingList;
+}
+
+int NetScanner::hostAlreadyInList(int ip, std::list<Node>* nodes)
+{
+ for (std::list<Node>::iterator node = nodes->begin(); node != nodes->end(); node++)
+ {
+ if (node->ip==ip)
+ return 1;
+ }
+ return 0;
+}
+
+void NetScanner::removeUnnamedHosts(std::list<Node>* nodes)
+{
+ nodes->remove_if(is_unnamed_node());
+}
+
+void NetScanner::completeNames(std::list<Node>* nodes)
+{
+ struct sockaddr_in tmpAddr;
+ //for every host
+ for (std::list<Node>::iterator node = nodes->begin(); node != nodes->end(); node++)
+ {
+ tmpAddr.sin_addr.s_addr=node->ip;
+ mdcerr<<"completeNames: looking up "<<inet_ntoa(tmpAddr.sin_addr)<<std::endl;
+ int done(0);
+ //first look wether we have the name already
+ if (hostList!=0) for (std::list<Node>::iterator oldNode=hostList->begin(); oldNode!=hostList->end(); oldNode++)
+ {
+ if (node->ip==oldNode->ip)
+ {
+ mdcerr<<"completeNames: cached: "<<oldNode->name<<" :-)"<<std::endl;
+ node->name=oldNode->name;
+ done=1;
+ break;
+ }
+ }
+ //otherwise do a name lookup
+ if (!done)
+ {
+ //IPAddress tmpAddress(node->ip);
+ //mdcerr<<"NetScanner::completeNames: doing actual lookup"<<std::endl;
+ node->name=ip2Name(tmpAddr.sin_addr);
+ mdcerr<<"completeNames: resolved: "<<node->name<<std::endl;
+ }
+ }
+}
+
diff --git a/lanbrowsing/lisa/netscanner.h b/lanbrowsing/lisa/netscanner.h
new file mode 100644
index 00000000..a93bf3ee
--- /dev/null
+++ b/lanbrowsing/lisa/netscanner.h
@@ -0,0 +1,102 @@
+/* netscanner.h
+ *
+ * Copyright (c) 1998, 1999, 2000 Alexander Neundorf
+ * neundorf@kde.org
+ *
+ * You may distribute under the terms of the GNU General Public
+ * License as specified in the COPYING file.
+ *
+ * This program 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 General Public License for more details.
+ *
+ */
+
+#ifndef NETSCANNER_H
+#define NETSCANNER_H
+
+#include <list>
+
+#include "mystring.h"
+#include "addressvalidator.h"
+#include "tcpnode.h"
+#include "configfile.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <time.h>
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/time.h>
+
+#include <stdio.h>
+
+class NetScanner
+{
+ public:
+ NetScanner(int& rawSocket, int strictMode);
+ ~NetScanner();
+
+ void doScan();
+
+ void completeNames(std::list<Node>* nodes);
+
+ //using nmblookup to determine the ip-address
+ //MyString ip2NetbiosName(const MyString& target, MyString& groupName);
+
+ char* ip2Name(struct in_addr ip);
+
+ MyString procId;
+ int m_firstWait;
+ int m_secondWait;
+ void configure(Config& config);
+ protected:
+ int m_strictMode;
+ int& m_rawSocketFD;
+ AddressValidator validator;
+ MyString ipRangeStr;
+ MyString nameMask;
+
+ int m_maxPings;
+ int m_deliverUnnamedHosts;
+ int m_useNmblookup;
+ //return ip-address with number index from a virtual array
+ //with all ip-addresses according to ipRangeStr
+ struct in_addr getIPfromArray(unsigned int index);
+
+ std::list<Node>* hostList;
+
+ //needed for getIPfromArray()
+ //contains the part of ipRangeStr, which is not yet parsed
+ MyString tmpIPRange;
+ //has to be called before every first call of getNextIPRange
+ void resetIPRange();
+ //returns the next range/part from tmpIPRange before the next semicolon
+ MyString getNextIPRange();
+
+ void pingScan(std::list<Node>* newList); //the ping-version
+ void nmblookupScan(std::list<Node>* newList); //the nmblookup "*"-version
+ int hostAlreadyInList(int ip, std::list<Node>* nodes);
+ void removeUnnamedHosts(std::list<Node>* nodes);
+
+ struct is_unnamed_node : std::unary_function<Node&, bool>
+ {
+ bool operator() (Node& n)
+ {
+ struct in_addr tmpAddr;
+ tmpAddr.s_addr = n.ip;
+ return (strcmp(inet_ntoa(tmpAddr), n.name.data()) == 0);
+ }
+ };
+};
+
+#endif
diff --git a/lanbrowsing/lisa/strictmain.cpp b/lanbrowsing/lisa/strictmain.cpp
new file mode 100644
index 00000000..a948d6df
--- /dev/null
+++ b/lanbrowsing/lisa/strictmain.cpp
@@ -0,0 +1,261 @@
+/* strictmain.cpp
+ *
+ * Copyright (c) 1998-2000 Alexander Neundorf
+ * neundorf@kde.org
+ *
+ * You may distribute under the terms of the GNU General Public
+ * License as specified in the COPYING file.
+ *
+ * This program 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 General Public License for more details.
+ *
+ */
+
+#include "lisadefines.h"
+#include "netmanager.h"
+
+#include <iostream>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+// detect linux/glibc for the gnu style --args
+#if defined(__linux__) || defined(__linux) || defined(linux)
+# include <features.h>
+# ifdef __GLIBC__
+// only gnu libc has getopt.h... getopt(3) is defined to be in unistd.h
+// by POSIX.2
+# ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+# endif
+# include <getopt.h>
+# endif // __GLIBC__
+# define GNU_GETOPT
+#endif // linux
+
+#ifdef LISA_DEBUG
+#undef LISA_DEBUG
+#endif
+#define LISA_DEBUG 0
+
+#ifdef dcerr
+#undef dcerr
+#endif
+
+#define dcerr if (LISA_DEBUG==1) std::cerr<<"strictmain "
+
+void printVersion()
+{
+ const char * versionInfo=\
+ "\r\nThis is the restricted LAN Information Server resLISa "MYVERSION"\r\n"\
+ "It is free software according the GNU General Public License\r\n"\
+ "Copyright (c) 2000-2003 by Alexander Neundorf\r\n"\
+ "email: neundorf@kde.org\r\n";
+ std::cout<<versionInfo<<std::endl;
+}
+
+void usage()
+{
+ printVersion();
+ const char * usageInfo=\
+ "-v, --version prints out a short version info\n"\
+ "-u, --unix deprecated\n"\
+ "-k, --kde1 deprecated\n"\
+ "-K, --kde2 deprecated\n"\
+ " reslisa now always looks first for $(HOME)/.reslisarc, then for /etc/reslisarc\"\n"\
+ "-c, --config=FILE read this and no other configuration file\n"\
+ "-q, --quiet start quiet without the greeting message\n"\
+ "-h, --help you are currently reading it ;-)\n";
+ std::cout<<usageInfo<<std::endl;
+//I thought this would be the way to check wether long options are supported...
+//#ifndef _GNU_SOURCE
+// cout<<"Please note that the long options are not supported on this system"<<endl;
+//#endif
+}
+
+void destruct(int sigNumber)
+{
+ signal(sigNumber,SIG_IGN);
+ std::cout<<"signal caught: "<<sigNumber<<", exiting"<<std::endl;
+ //signal(sigNumber,&destruct);
+ exit(0);
+}
+
+NetManager *manager(0);
+
+void readConfig(int sigNumber)
+{
+ std::cout<<"readConfig(): signal caught: "<<sigNumber<<std::endl;
+ signal(SIGHUP,SIG_IGN);
+ if (manager!=0)
+ manager->readConfig();
+ signal(SIGHUP,&readConfig);
+}
+
+void printState(int sigNumber)
+{
+ std::cout<<"printState(): signal caught: "<<sigNumber<<std::endl;
+ signal(SIGUSR1,SIG_IGN);
+ if (manager!=0)
+ manager->printState();
+ signal(SIGUSR1,&printState);
+}
+
+void setSignalHandler()
+{
+ signal(SIGHUP,&readConfig);
+ signal(SIGUSR1,&printState);
+
+ signal(SIGINT,&destruct);
+ signal(SIGQUIT,&destruct);
+ signal(SIGILL,&destruct);
+ signal(SIGTRAP,&destruct);
+ signal(SIGABRT,&destruct);
+ signal(SIGBUS,&destruct);
+ signal(SIGSEGV,&destruct);
+ signal(SIGUSR2,&destruct);
+ signal(SIGPIPE,&destruct);
+ signal(SIGALRM,&destruct);
+ signal(SIGTERM,&destruct);
+ signal(SIGFPE,&destruct);
+#ifdef SIGPOLL
+ signal(SIGPOLL, &destruct);
+#endif
+#ifdef SIGSYS
+ signal(SIGSYS, &destruct);
+#endif
+#ifdef SIGVTALRM
+ signal(SIGVTALRM, &destruct);
+#endif
+#ifdef SIGXCPU
+ signal(SIGXCPU, &destruct);
+#endif
+#ifdef SIGXFSZ
+ signal(SIGXFSZ, &destruct);
+#endif
+}
+
+#ifdef GNU_GETOPT
+static struct option const long_opts[] =
+{
+ {"version", no_argument, 0, 'v'},
+ {"quiet", no_argument, 0, 'q'},
+ {"unix", no_argument, 0, 'u'},
+ {"kde1", no_argument, 0, 'k'},
+ {"kde2", no_argument, 0, 'K'},
+ {"config", required_argument, 0, 'c'},
+ {"help", no_argument, 0, 'h'},
+ {0, 0, 0, 0}
+};
+#endif
+
+int main(int argc, char** argv)
+{
+ int quiet(0);
+ int c(0);
+ int configStyle(UNIXCONFIGSTYLE);
+ MyString configFile;
+ int portToUse(MYPORT);
+
+//I thought this would be the way to check wether long options are supported...
+#ifdef GNU_GETOPT
+ while ((c=getopt_long(argc, argv, "vqukKc:h", long_opts, 0))!=-1)
+#else
+ while ((c=getopt(argc, argv, "vqukKc:h"))!=-1)
+#endif
+ {
+ switch (c)
+ {
+ case 0:
+ break;
+ case 'v':
+ printVersion();
+ exit(0);
+ break;
+ case 'q':
+ quiet=1;
+ break;
+ case 'u':
+ case 'k':
+ case 'K':
+ std::cerr<<"\a\nThe command line switches -k, -K, -u and \ntheir long versions "\
+ "--kde1, --kde2 and --unix are not supported anymore.\n"\
+ "ResLisa will always first look for $(HOME)/.reslisarc , then for /etc/reslisarc.\n"\
+ "If your lisa configuration file was created using an older version of \n"\
+ "the KDE control center, copy the $(HOME)/.kde/share/config/reslisarc to $(HOME)/.reslisarc.\n"<<std::endl;
+ break;
+
+ case 'c':
+ configFile = optarg;
+ configStyle = EXTRACONFIGSTYLE;
+ break;
+
+ case 'h':
+ default:
+ usage();
+ exit(0);
+ break;
+ }
+ }
+
+ //fork and let the parent exit
+ pid_t pid=fork();
+ if (pid>0)
+ {
+ //this is the parent
+ exit(0);
+ }
+ else if (pid<0)
+ {
+ dcerr<<"could not fork()"<<std::endl;
+ exit(0);
+ }
+ //we will only read/write to/from this socket in the child process
+ int rawSocket=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);
+ if (rawSocket==-1)
+ {
+ std::cout<<"could not create raw socket, root privileges required"<<std::endl;
+ std::cout<<"take a look at the README for more information"<<std::endl;
+ exit(0);
+ }
+ int bufferSize(60*1024);
+ int on(1);
+ setsockopt(rawSocket, SOL_SOCKET, SO_RCVBUF, (char*)&bufferSize,
+ sizeof(bufferSize));
+ int result=setsockopt(rawSocket, SOL_SOCKET, SO_BROADCAST, (char*)&on,
+ sizeof(on));
+ dcerr<<"setsockopt returns "<<result<<std::endl;
+ //dropping root privileges
+ //they will be regained once in the child process
+ //for creating a raw socket
+
+ //now dropping root privileges once and ever
+ setuid(getuid());
+
+ //according to R. Stevens the following three lines
+ //make daemons feel good :)
+ setsid();
+ chdir("/");
+ umask(0);
+
+ dcerr<<"starting, dropped root privileges"<<std::endl;
+ dcerr<<"port: "<<portToUse<<" file: "<<configFile<<std::endl;
+ NetManager netmanager(rawSocket,portToUse,configFile,configStyle,1);
+ manager=&netmanager;
+ dcerr<<"NetManager created"<<std::endl;
+ setSignalHandler();
+
+ netmanager.readConfig();
+ if (netmanager.prepare())
+ {
+ if (!quiet)
+ printVersion();
+ netmanager.run();
+ }
+ dcerr<<"server finished"<<std::endl;
+}
diff --git a/lanbrowsing/lisa/stringlist.cpp b/lanbrowsing/lisa/stringlist.cpp
new file mode 100644
index 00000000..3bf82f9c
--- /dev/null
+++ b/lanbrowsing/lisa/stringlist.cpp
@@ -0,0 +1,110 @@
+#include "simplelist.h"
+
+template <class T>
+SimpleList<T>::SimpleList()
+ :m_list(0)
+ ,m_current(0)
+ ,m_last(0)
+ ,m_size(0)
+{};
+
+template <class T>
+SimpleList<T>::~SimpleList()
+{
+ clear();
+};
+
+template <class T>
+void SimpleList<T>::append(const T& text)
+{
+ if (m_list==0)
+ {
+ m_list=new TemplNode<T>(text);
+ m_last=m_list;
+ }
+ else
+ {
+ m_last->m_next=new TemplNode<T>(text);
+ m_last=m_last->m_next;
+ };
+ m_size++;
+};
+
+template <class T>
+void SimpleList<T>::removeFirst()
+{
+ if (m_list==0) return;
+ TemplNode<T> *first=m_list;
+ m_list=m_list->m_next;
+ m_size--;
+ if (m_list==0)
+ m_last=0;
+ m_current=0;
+ delete first;
+};
+
+template <class T>
+void SimpleList<T>::clear()
+{
+ while (m_list!=0)
+ removeFirst();
+ m_current=0;
+ m_last=0;
+ m_list=0;
+ m_size=0;
+};
+
+template <class T>
+void SimpleList<T>::remove(T* item)
+{
+ if (item==0) return;
+ TemplNode<T>* pre(0);
+ for (T* tmp=first(); tmp!=0; tmp=next())
+ {
+ if (tmp==item)
+ {
+ if (m_current==m_list)
+ {
+ removeFirst();
+ return;
+ }
+ else
+ {
+ TemplNode<T> *succ=m_current->m_next;
+ if (m_current==m_last)
+ m_last=pre;
+ delete m_current;
+ pre->m_next=succ;
+ m_size--;
+ m_current=0;
+
+ };
+ };
+ pre=m_current;
+ };
+
+};
+
+template <class T>
+T* SimpleList<T>::first()
+{
+ m_current=m_list;
+ if (m_list==0)
+ return 0;
+ return &m_current->m_item;
+};
+
+template <class T>
+T* SimpleList<T>::next()
+{
+ if (m_current==0) return 0;
+ m_current=m_current->m_next;
+ if (m_current==0) return 0;
+ return &m_current->m_item;
+};
+
+template <class T>
+int SimpleList<T>::size()
+{
+ return m_size;
+}
diff --git a/lanbrowsing/lisa/stringlist.h b/lanbrowsing/lisa/stringlist.h
new file mode 100644
index 00000000..44f0d0d3
--- /dev/null
+++ b/lanbrowsing/lisa/stringlist.h
@@ -0,0 +1,40 @@
+#ifndef SIMPLELIST_H
+#define SIMPLELIST_H
+
+#include "mystring.h"
+
+template <class T>
+struct TemplNode
+{
+ TemplNode(const T& text)
+ :m_item(text),m_next(0) {};
+ T m_item;
+ TemplNode* m_next;
+};
+
+
+template <class T>
+class SimpleList
+{
+ public:
+ SimpleList();
+ ~SimpleList();
+ void append(const T& item);
+ void clear();
+ int size();
+ T* first();
+ T* next();
+ void removeFirst();
+ void remove(T* item);
+ protected:
+ TemplNode<T>* m_list;
+ TemplNode<T>* m_current;
+ TemplNode<T>* m_last;
+ int m_size;
+};
+
+
+template class SimpleList<int>;
+
+#endif
+
diff --git a/lanbrowsing/lisa/tcpnode.h b/lanbrowsing/lisa/tcpnode.h
new file mode 100644
index 00000000..394ca928
--- /dev/null
+++ b/lanbrowsing/lisa/tcpnode.h
@@ -0,0 +1,29 @@
+/* tcpnode.h
+ *
+ * Copyright (c) 2000 Alexander Neundorf
+ * neundorf@kde.org
+ *
+ * You may distribute under the terms of the GNU General Public
+ * License as specified in the COPYING file.
+ *
+ * This program 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 General Public License for more details.
+ *
+ */
+
+#ifndef _TCPNODE_H_
+#define _TCPNODE_H_
+
+#include "mystring.h"
+
+struct Node
+{
+ Node(const MyString& n, int ipAddress)
+ :name(n),ip(ipAddress) {};
+ MyString name;
+ unsigned int ip;
+};
+
+#endif