|
|
|
/* 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., 51 Franklin Street, Fifth Floor,
|
|
|
|
Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include <config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <tdelocale.h>
|
|
|
|
#include <kinstance.h>
|
|
|
|
#include <tdeconfig.h>
|
|
|
|
#include <tdeglobal.h>
|
|
|
|
#include <kprocess.h>
|
|
|
|
|
|
|
|
#include <tqfile.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 "tdeio_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 TDEIO;
|
|
|
|
|
|
|
|
#ifndef SHUT_RDWR
|
|
|
|
#define SHUT_RDWR 2
|
|
|
|
#endif
|
|
|
|
|
|
|
|
extern "C" { TDE_EXPORT int kdemain(int argc, char **argv); }
|
|
|
|
|
|
|
|
int kdemain( int argc, char **argv )
|
|
|
|
{
|
|
|
|
TDEInstance instance( "tdeio_lan" );
|
|
|
|
|
|
|
|
if (argc != 4)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Usage: tdeio_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)TDEGlobal::dirs();
|
|
|
|
(void)TDEGlobal::locale();
|
|
|
|
(void)TDEGlobal::config();
|
|
|
|
|
|
|
|
kdDebug(7101) << "LAN: kdemain: starting" << endl;
|
|
|
|
|
|
|
|
LANProtocol slave(isLanIoslave, argv[2], argv[3]);
|
|
|
|
slave.dispatchLoop();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
LANProtocol::LANProtocol(int isLanIoslave, const TQCString &pool, const TQCString &app )
|
|
|
|
:TCPSlaveBase(7741,isLanIoslave?"lan":"rlan", pool, app)
|
|
|
|
,m_currentHost("")
|
|
|
|
,m_port(7741)
|
|
|
|
,m_maxAge(15*60)
|
|
|
|
,m_isLanIoslave(isLanIoslave?true:false)
|
|
|
|
{
|
|
|
|
TDEConfig *config=TDEGlobal::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 = TDEIO::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 = TDEIO::UDS_SIZE;
|
|
|
|
atom.m_long = 1024;
|
|
|
|
entry.append(atom);
|
|
|
|
atom.m_uds = TDEIO::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 = TDEIO::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;
|
|
|
|
TQCString 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);
|
|
|
|
TDEProcess proc;
|
|
|
|
proc<<"reslisa";
|
|
|
|
|
|
|
|
bool ok=proc.start(TDEProcess::DontCare);
|
|
|
|
if (!ok)
|
|
|
|
{
|
|
|
|
error( ERR_CANNOT_LAUNCH_PROCESS, "reslisa" );
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
//wait a moment
|
|
|
|
//reslisa starts tde-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.data()));
|
|
|
|
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 = TDEIO::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 = TDEIO::UDS_SIZE;
|
|
|
|
atom.m_long = 1024;
|
|
|
|
entry.append(atom);
|
|
|
|
atom.m_uds = TDEIO::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 = TDEIO::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 TQString& host)
|
|
|
|
{
|
|
|
|
kdDebug(7101)<<"LAN::checkHost() "<<host<<endl;
|
|
|
|
|
|
|
|
TQString 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 = TDEIO::UDS_NAME;
|
|
|
|
atom.m_str = m_protocolInfo[i].name;
|
|
|
|
entry.append( atom );
|
|
|
|
// size
|
|
|
|
atom.m_uds = TDEIO::UDS_SIZE;
|
|
|
|
atom.m_long = 1024;
|
|
|
|
entry.append(atom);
|
|
|
|
// access permissions
|
|
|
|
atom.m_uds = TDEIO::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 = TDEIO::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 = TDEIO::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 = TDEIO::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( TQValueVector<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 (TQValueVector<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 TQString& host, int port, const TQString& , const TQString& )
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
TQString path( TQFile::encodeName(url.path()));
|
|
|
|
TQStringList pathList=TQStringList::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);
|
|
|
|
TQString path( TQFile::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;
|
|
|
|
TQStringList pathList=TQStringList::split("/", path);
|
|
|
|
kdDebug(7101)<<"parts are: "<<endl;
|
|
|
|
for (TQStringList::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 = TDEIO::UDS_NAME;
|
|
|
|
atom.m_str = url.path();
|
|
|
|
entry.append( atom );
|
|
|
|
atom.m_uds = TDEIO::UDS_SIZE;
|
|
|
|
atom.m_long = 1024;
|
|
|
|
entry.append(atom);
|
|
|
|
|
|
|
|
atom.m_uds = TDEIO::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);
|
|
|
|
|
|
|
|
|
|
|
|
TQString path( TQFile::encodeName(url.path()));
|
|
|
|
TQStringList pathList=TQStringList::split( "/",path);
|
|
|
|
if ((pathList.count()==2) && (pathList[1].upper()=="HTTP"))
|
|
|
|
{
|
|
|
|
atom.m_uds = TDEIO::UDS_FILE_TYPE;
|
|
|
|
atom.m_long=S_IFREG;
|
|
|
|
entry.append(atom);
|
|
|
|
atom.m_uds = TDEIO::UDS_MIME_TYPE;
|
|
|
|
atom.m_str="text/html";
|
|
|
|
//kdDebug(7101)<<"LANProtocol::stat: http is reg file"<<endl;
|
|
|
|
entry.append( atom );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
atom.m_uds = TDEIO::UDS_FILE_TYPE;
|
|
|
|
atom.m_long = S_IFDIR; // it is always a directory
|
|
|
|
entry.append(atom);
|
|
|
|
atom.m_uds = TDEIO::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 )
|
|
|
|
{
|
|
|
|
TQString path(TQFile::encodeName(url.path()));
|
|
|
|
|
|
|
|
kdDebug(7101)<<"LANProtocol::get: "<<path<<endl;
|
|
|
|
TQStringList pathList=TQStringList::split("/", path);
|
|
|
|
kdDebug(7101)<<"parts are: "<<endl;
|
|
|
|
for (TQStringList::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;
|
|
|
|
}
|