diff options
Diffstat (limited to 'lanbrowsing')
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 |