Files correlati : ba1.exe Ricompilazione Demo : [ ] Commento : 0001036: installazione cd patch 180 Installando ex novo ed indicando una società esistente di dati su una cartella diversa viene segnalato l'errore ba1.exe in fase di conversione archivi, richiamando da manutenzione archivi la conversione vengono generati gli errori allegati. Nell'area ftp di Aga, cartella Ilaria allego l'area dati SIDA per il test. git-svn-id: svn://10.65.10.50/trunk@17971 c028cbd2-c16b-5b4b-a496-9718f37d4682
1239 lines
28 KiB
C++
Executable File
1239 lines
28 KiB
C++
Executable File
#define XVT_INCL_NATIVE
|
||
#include <xvt.h>
|
||
|
||
#include <agasys.h>
|
||
#include <diction.h>
|
||
#include <progind.h>
|
||
#include <real.h>
|
||
#include <utility.h>
|
||
|
||
// skstream.h
|
||
// Copyright (C) 1995, 1996 by John C. Wang. All Rights Reserved.
|
||
//
|
||
// You may distribute this file with your product in either of two ways:
|
||
// IN SOURCE CODE FORM: You must include this file in its entirety.
|
||
// IN OBJECT CODE FORM: You must give proper acknowledgements to the author(s)
|
||
// of this program. This may take the form of credits on the start-up screen.
|
||
//
|
||
// IN ANYCASE, THIS SOFTWARE IS DISTRIBUTED WITHOUT ANY KIND OF EXPLICIT OR
|
||
// IMPLICIT WARRANTIES AND THE AUTHORS ARE NOT RESPONSIBLE FOR ANY EVENTS THAT
|
||
// OCCURS AS A RESULT OF USING THIS SOFTWARE.
|
||
//
|
||
// History:
|
||
// [JCW 95-Dec-04] created
|
||
// [JCW 95-Dec-20] comments added for distribution 95a
|
||
// [JCW 96-Jan-01] removed UDP capabilities from skstream
|
||
|
||
#ifdef INCSTR_H
|
||
#include <incstr.h>
|
||
#endif
|
||
|
||
#ifdef WIN32
|
||
#include "winsock.h"
|
||
#else
|
||
#include <sys/types.h>
|
||
#include <sys/socket.h>
|
||
#include <netinet/in.h>
|
||
#include <arpa/inet.h>
|
||
#include <netdb.h>
|
||
#include <unistd.h>
|
||
#define SOCKET int
|
||
#define INVALID_SOCKET -1
|
||
#define SOCKET_ERROR -1
|
||
#define SOCKADDR_IN sockaddr_in
|
||
#define closesocket close
|
||
#define BYTE byte
|
||
#endif
|
||
|
||
//
|
||
// sockbuf
|
||
//
|
||
class sockbuf : public streambuf
|
||
{
|
||
public:
|
||
sockbuf( SOCKET & );
|
||
sockbuf( SOCKET &, char *, int );
|
||
|
||
virtual ~sockbuf();
|
||
|
||
virtual int overflow(int =EOF) ;
|
||
virtual int underflow() ;
|
||
|
||
virtual int sync();
|
||
|
||
protected:
|
||
char *_buffer ;
|
||
|
||
// sockbuf specific
|
||
SOCKET &_socket ;
|
||
} ;
|
||
|
||
|
||
//
|
||
// skstream
|
||
//
|
||
class skstream : public iostream
|
||
{
|
||
public:
|
||
// constants
|
||
enum service
|
||
{
|
||
ftp = 21, //tcp
|
||
telnet = 23, //tcp
|
||
smtp = 25, //tcp mail
|
||
time = 37, //tcp timserver
|
||
name = 42, //tcp nameserver
|
||
nameserver = 53, //tcp domain # name-domain server
|
||
finger = 79, //tcp
|
||
http = 80, //tcp
|
||
pop = 109, //tcp postoffice
|
||
pop2 = 109, //tcp # Post Office
|
||
pop3 = 110, //tcp postoffice
|
||
nntp = 119 //tcp usenet # Network News Transfer
|
||
} ;
|
||
|
||
enum role
|
||
{
|
||
server ,
|
||
client
|
||
} ;
|
||
|
||
// methods
|
||
skstream( void );
|
||
skstream( const char *addr, const service, const role = client ) ;
|
||
skstream( SOCKET );
|
||
~skstream( void );
|
||
|
||
void open( const char *addr, const service, const role = client ) ;
|
||
void close( void ) ;
|
||
int is_open( void ) const ;
|
||
void attach( SOCKET = NULL );
|
||
SOCKET getsocket() const ;
|
||
|
||
char *getpeername( char *, int ) const ;
|
||
unsigned short getport( void ) const ;
|
||
protected:
|
||
SOCKET _socket ;
|
||
sockbuf _sockbuf ;
|
||
|
||
// platform dependent library housekeeping
|
||
int init( void ) ;
|
||
int shutdown( void ) ;
|
||
};
|
||
|
||
// skstream.cpp
|
||
// Copyright (C) 1996, 1995 by John C. Wang <jcwang@csie.ntu.edu.tw>
|
||
// All Rights Reserved.
|
||
//
|
||
// You may distribute this file with your product in either of two ways:
|
||
// IN SOURCE CODE FORM: You must include this file in its entirety.
|
||
// IN OBJECT CODE FORM: You must give proper acknowledgements to the author(s)
|
||
// of this program. This may take the form of credits on the start-up screen.
|
||
//
|
||
// IN ANYCASE, THIS SOFTWARE IS DISTRIBUTED WITHOUT ANY KIND OF EXPLICIT OR
|
||
// IMPLICIT WARRANTY AND THE AUTHOR(S) ARE NOT RESPONSIBLE FOR ANY EVENT THAT
|
||
// OCCURS DUE TO THE USE OR MISUSE OF THIS SOFTWARE.
|
||
//
|
||
// History:
|
||
// [JCW 95-Dec-04] created.
|
||
// [JCW 95-Dec-20] comments added for distribution 95a.
|
||
// [JCW 96-Jan-01] removed UDP capabilities from skstream.
|
||
// [JCW 96-Mar-14] exceptions made optional.
|
||
// [JCW 96-Oct-20] protected skstream::init and ::shutdown changed.
|
||
// char( 255 ) == EOF bug fixed.
|
||
|
||
#ifdef _UNIX
|
||
#define INVALID_SOCKET -1
|
||
// Add definitions here
|
||
#endif
|
||
|
||
// Machine independent macros
|
||
#ifdef DBG
|
||
#define dassert(x) assert(x)
|
||
#define debug(x) x
|
||
#else
|
||
#define dassert(x)
|
||
#define debug(x)
|
||
#endif //def _DEBUG
|
||
|
||
//
|
||
// skstream
|
||
//
|
||
|
||
int skstream::init( void )
|
||
{
|
||
// platform dependent initialization
|
||
#ifdef WIN32
|
||
const WORD wMinVer = 0x0101; // request WinSock v1.1 (at least)
|
||
WSADATA wsaData;
|
||
if( 0 == WSAStartup( wMinVer, &wsaData ) )
|
||
return TRUE ;
|
||
return FALSE ;
|
||
#else
|
||
return TRUE;
|
||
#endif
|
||
}
|
||
|
||
int skstream::shutdown( void )
|
||
{
|
||
// platform dependent shutdown
|
||
#ifdef WIN32
|
||
if( 0 == WSACleanup() )
|
||
return TRUE ;
|
||
return FALSE ;
|
||
#else
|
||
return TRUE;
|
||
#endif
|
||
}
|
||
|
||
skstream::skstream( void ) : iostream( &_sockbuf ), _sockbuf( _socket )
|
||
{
|
||
if( init() )
|
||
attach( INVALID_SOCKET ) ;
|
||
}
|
||
|
||
skstream::skstream( const char *addr, const service port, const role side )
|
||
: iostream( &_sockbuf ), _sockbuf( _socket )
|
||
{
|
||
if( init() )
|
||
{
|
||
attach( INVALID_SOCKET ) ;
|
||
open( addr, port, side ) ;
|
||
}
|
||
}
|
||
|
||
skstream::skstream( SOCKET sock ) : iostream( &_sockbuf ), _sockbuf( _socket )
|
||
{
|
||
if( init() )
|
||
attach( sock ) ;
|
||
}
|
||
|
||
skstream::~skstream( void )
|
||
{
|
||
close() ;
|
||
shutdown() ;
|
||
}
|
||
|
||
int skstream::is_open( void ) const
|
||
{
|
||
return ( INVALID_SOCKET != getsocket() ) ;
|
||
}
|
||
|
||
void skstream::open( const char *addr, const service port, const role side )
|
||
{
|
||
// in case of error condition, user finds out by testing is_open()
|
||
|
||
if( is_open() )
|
||
close() ;
|
||
|
||
// 1. Create socket
|
||
if( INVALID_SOCKET == ( _socket = ::socket( PF_INET, SOCK_STREAM, 0 ) ) )
|
||
// Cannot create socket
|
||
return ;
|
||
|
||
// 2. Bind
|
||
SOCKADDR_IN sa ;
|
||
sa.sin_family = AF_INET ;
|
||
#ifdef WIN32
|
||
sa.sin_addr.S_un.S_addr = INADDR_ANY ;
|
||
#else
|
||
sa.sin_addr.s_addr = INADDR_ANY ;
|
||
#endif
|
||
sa.sin_port = side == client ? 0 : htons( (unsigned short)port ) ;
|
||
// rationale: no client requires fixed port number, so let system assign
|
||
if( SOCKET_ERROR == ::bind( _socket, (sockaddr *)&sa, sizeof( sa ) ) )
|
||
{
|
||
// Cannot bind to the chosen port
|
||
close() ;
|
||
return ;
|
||
}
|
||
|
||
// From now on the two sides are very much different
|
||
if( side == skstream::client )
|
||
{
|
||
// 3(cli). Connect
|
||
SOCKADDR_IN sa ; memset(&sa,0,sizeof(sa));
|
||
sa.sin_family = AF_INET ;
|
||
|
||
unsigned long indirizzo = 0xFFFFFFFF;
|
||
|
||
int ip[4];
|
||
//e' un indirizzo numerico?
|
||
//si...
|
||
if (sscanf( addr, "%d.%d.%d.%d", &ip[0], &ip[1], &ip[2], &ip[3]) == 4)
|
||
{
|
||
indirizzo = ::inet_addr(addr);
|
||
}
|
||
//no...
|
||
else
|
||
{
|
||
hostent* he = ::gethostbyname( addr );
|
||
if( NULL != he )
|
||
indirizzo = *(unsigned long *)( he->h_addr_list[ 0 ] );
|
||
}
|
||
|
||
if (indirizzo == 0 || indirizzo == 0xFFFFFFFF)
|
||
{
|
||
close();
|
||
return;
|
||
}
|
||
|
||
#ifdef WIN32
|
||
sa.sin_addr.S_un.S_addr = indirizzo;
|
||
sa.sin_port = ::htons( port ) ;
|
||
#else
|
||
sa.sin_addr.s_addr = indirizzo;
|
||
sa.sin_port = htons( port ) ;
|
||
#endif
|
||
|
||
if( SOCKET_ERROR == ::connect( _socket, (sockaddr *)&sa, sizeof( sa ) ) )
|
||
{
|
||
// Connection error
|
||
close() ;
|
||
return ;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// 3(svr). Listen
|
||
if( SOCKET_ERROR == ::listen( _socket, 5 ) ) // max backlog
|
||
{
|
||
// Error listening
|
||
close() ;
|
||
return ;
|
||
}
|
||
|
||
// 4. Accept
|
||
SOCKET commsock ;
|
||
if( INVALID_SOCKET == ( commsock = ::accept( _socket, NULL, NULL ) ) )
|
||
{
|
||
// Accepting error
|
||
close() ;
|
||
return ;
|
||
}
|
||
|
||
// rationale: after we accept a connection, close the server port
|
||
// so another process may become a server
|
||
if( SOCKET_ERROR == ::closesocket( _socket ) )
|
||
{
|
||
// Cannot close service port, resource may be occupied
|
||
close() ;
|
||
return ;
|
||
}
|
||
_socket = commsock ;
|
||
}
|
||
// success!
|
||
}
|
||
|
||
void skstream::close( void )
|
||
{
|
||
if( is_open() )
|
||
{
|
||
_sockbuf.sync() ;
|
||
if( SOCKET_ERROR == ::closesocket( _socket ) )
|
||
// Cannot close. Leave _socket as it was
|
||
return ;
|
||
}
|
||
|
||
_socket = INVALID_SOCKET ;
|
||
}
|
||
|
||
void skstream::attach( SOCKET sock )
|
||
{
|
||
_socket = sock ;
|
||
}
|
||
|
||
SOCKET skstream::getsocket() const
|
||
{
|
||
return _socket ;
|
||
}
|
||
|
||
char *skstream::getpeername( char *buf, int size ) const
|
||
{
|
||
SOCKADDR_IN sa ;
|
||
int sasize = sizeof( sa ) ;
|
||
#ifdef WIN32
|
||
if( SOCKET_ERROR ==::getpeername( getsocket(), (sockaddr *)&sa, &sasize ) )
|
||
#else
|
||
if( SOCKET_ERROR ==::getpeername( getsocket(), (sockaddr *)&sa, (socklen_t *) &sasize ) )
|
||
#endif
|
||
// Cannot get peer name
|
||
return NULL ;
|
||
strncpy( buf, ::inet_ntoa( sa.sin_addr ), size - 1 ) ;
|
||
return buf ;
|
||
}
|
||
|
||
unsigned short skstream::getport( void ) const
|
||
{
|
||
SOCKADDR_IN sa ;
|
||
int sasize = sizeof( sa ) ;
|
||
#ifdef WIN32
|
||
if( SOCKET_ERROR ==::getpeername( getsocket(), (sockaddr *)&sa, &sasize ) )
|
||
// Cannot get peer port
|
||
return ::ntohs( IPPORT_RESERVED );
|
||
return ::ntohs( sa.sin_port ) ;
|
||
#else
|
||
if( SOCKET_ERROR ==::getpeername( getsocket(), (sockaddr *)&sa, (socklen_t *) &sasize ) )
|
||
// Cannot get peer port
|
||
return ntohs( IPPORT_RESERVED );
|
||
return ntohs( sa.sin_port ) ;
|
||
#endif
|
||
}
|
||
|
||
//
|
||
// sockbuf
|
||
//
|
||
sockbuf::sockbuf( SOCKET &sock ) : _socket( sock )
|
||
{
|
||
const int insize = 0x2000 ; // allocate 16k buffer each for input and output
|
||
const int outsize = 0x2000 ;
|
||
const int bufsize = insize + outsize ;
|
||
|
||
_buffer = new char [ bufsize ] ;
|
||
|
||
if( this != setbuf( _buffer, bufsize ) )
|
||
_buffer = NULL ;
|
||
else
|
||
{
|
||
setp( _buffer, _buffer + insize ) ;
|
||
setg( _buffer + insize, _buffer + bufsize, _buffer + bufsize ) ;
|
||
}
|
||
}
|
||
|
||
sockbuf::sockbuf( SOCKET &sock, char *buf, int length ) : _socket( sock )
|
||
{
|
||
_buffer = NULL ;
|
||
|
||
if( this == setbuf( buf, length ) )
|
||
{
|
||
setp( buf, buf + length / 2 ) ;
|
||
setg( buf + length / 2, buf + length, buf + length ) ;
|
||
}
|
||
}
|
||
|
||
sockbuf::~sockbuf()
|
||
{
|
||
delete[] _buffer ;
|
||
_buffer = NULL ;
|
||
}
|
||
|
||
int sockbuf::overflow( int nCh )
|
||
{
|
||
// in case of error, user finds out by testing fail()
|
||
if( _socket == INVALID_SOCKET )
|
||
// Invalid socket
|
||
return EOF ;
|
||
|
||
if( pptr() - pbase() <= 0 )
|
||
// nothing to send
|
||
return 0 ;
|
||
|
||
int size ;
|
||
if( SOCKET_ERROR == ( size = ::send( _socket, pbase(), pptr() - pbase(), 0 ) ) )
|
||
// (TCP) Cannot send
|
||
return EOF ;
|
||
|
||
if( size == 0 )
|
||
// remote site has closed this connection
|
||
return EOF ;
|
||
|
||
if( nCh != EOF ) // size >= 1 at this point
|
||
{
|
||
size-- ;
|
||
*( pbase() + size ) = nCh ;
|
||
}
|
||
|
||
// move remaining pbase() + size .. pptr() - 1 => pbase() .. pptr() - size - 1
|
||
for( char *p = pbase() + size; p < pptr(); p++ )
|
||
*( p - size ) = *p ;
|
||
const int newlen = ( pptr() - pbase() ) - size ;
|
||
|
||
setp( pbase(), epptr() ) ;
|
||
pbump( newlen ) ;
|
||
|
||
return 0 ;
|
||
}
|
||
|
||
int sockbuf::underflow()
|
||
{
|
||
// if get area not empty, return first character
|
||
// else fill up get area and return 1st character
|
||
|
||
// in case of error, user finds out by testing eof()
|
||
|
||
if( _socket == INVALID_SOCKET )
|
||
// Invalid socket!
|
||
return EOF ;
|
||
|
||
if( egptr() - gptr() > 0 )
|
||
return (int)(unsigned char)(*gptr()) ;
|
||
|
||
// fill up from eback to egptr
|
||
int size ;
|
||
if( SOCKET_ERROR == ( size = ::recv( _socket, eback(), egptr() - eback(), 0 ) ) )
|
||
// (TCP) Receive error
|
||
return EOF ;
|
||
|
||
if( size == 0 )
|
||
// remote site has closed this connection
|
||
return EOF ;
|
||
|
||
// move rcvd data from eback() .. eback() + size to egptr() - size .. egptr()
|
||
const int delta = egptr() - ( eback() + size ) ;
|
||
for( char *p = eback() + size - 1; p >= eback(); p-- )
|
||
{
|
||
CHECK( p + delta >= eback(), "Socket underflow" ) ;
|
||
CHECK( p + delta < egptr(), "Socket underflow" ) ;
|
||
*( p + delta ) = *p ;
|
||
}
|
||
|
||
setg( eback(), egptr() - size, egptr() ) ;
|
||
|
||
return (int)(unsigned char)(*gptr()) ;
|
||
}
|
||
|
||
int sockbuf::sync()
|
||
{
|
||
if( EOF == overflow() )
|
||
return EOF ; // ios will set the fail bit
|
||
else
|
||
{
|
||
// empty put and get areas
|
||
setp( pbase(), epptr() ) ;
|
||
setg( eback(), egptr(), egptr() ) ;
|
||
|
||
return 0 ;
|
||
}
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// end of skstreams
|
||
///////////////////////////////////////////////////////////
|
||
|
||
#include "netsock.h"
|
||
|
||
class TSocket_connection : public TConnection
|
||
{
|
||
TString _server;
|
||
skstream::service _service;
|
||
|
||
skstream* _socket;
|
||
|
||
protected:
|
||
bool connect();
|
||
|
||
public:
|
||
const TString & Server() const { return _server; }
|
||
virtual bool Execute(const char* cmd);
|
||
|
||
bool WriteLine(const char* cmd);
|
||
bool ReadLine(TString& str);
|
||
bool Read(byte* buf, size_t size);
|
||
|
||
skstream* GetSocket();
|
||
|
||
TSocket_connection(TLanManager* lm, const char* service, const char* server);
|
||
~TSocket_connection();
|
||
};
|
||
|
||
bool TSocket_connection::Execute(const char* cmd)
|
||
{
|
||
skstream* calza = GetSocket();
|
||
bool ok = calza != NULL;
|
||
if (ok)
|
||
{
|
||
const size_t buflen = strlen(cmd)+1;
|
||
calza->sync();
|
||
calza->write(cmd, buflen);
|
||
calza->flush();
|
||
ok = calza->good() != 0;
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
bool TSocket_connection::WriteLine(const char* cmd)
|
||
{
|
||
skstream* calza = GetSocket();
|
||
bool ok = calza != NULL;
|
||
if (ok)
|
||
{
|
||
const size_t buflen = strlen(cmd); // Unica differenza da Execute
|
||
calza->sync();
|
||
calza->write(cmd, buflen);
|
||
calza->flush();
|
||
ok = calza->good() != 0;
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
bool TSocket_connection::ReadLine(TString& str)
|
||
{
|
||
skstream* calza = GetSocket();
|
||
bool ok = calza != NULL;
|
||
if (ok)
|
||
{
|
||
char *buf = str.get_buffer(4096);
|
||
calza->getline(buf, str.size(), '\n');
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
bool TSocket_connection::Read(byte* buf, size_t size)
|
||
{
|
||
skstream* calza = GetSocket();
|
||
bool ok = calza != NULL;
|
||
if (ok)
|
||
{
|
||
calza->read((char *)buf, size);
|
||
ok = calza->good() != 0;
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
bool TSocket_connection::connect()
|
||
{
|
||
if (_socket != NULL)
|
||
delete _socket;
|
||
_socket = new skstream(_server, _service);
|
||
if (_socket->is_open())
|
||
SetId((CONNID)_socket);
|
||
else
|
||
{
|
||
delete _socket;
|
||
_socket = NULL;
|
||
SetId(0);
|
||
}
|
||
|
||
return _socket != NULL;
|
||
}
|
||
|
||
skstream* TSocket_connection::GetSocket()
|
||
{
|
||
if (_socket == NULL || !_socket->is_open())
|
||
connect();
|
||
return _socket;
|
||
}
|
||
|
||
TSocket_connection::TSocket_connection(TLanManager* lm,
|
||
const char* service, const char* server)
|
||
: TConnection(lm, 0), _socket(NULL)
|
||
{
|
||
_service = (skstream::service)((service && *service) ? atoi(service) : 0);
|
||
|
||
_server = server;
|
||
int pos = _server.find("://");
|
||
if (pos > 0)
|
||
_server.ltrim(pos+3);
|
||
|
||
pos = _server.rfind(':');
|
||
if (pos >= 0)
|
||
{
|
||
_service = (skstream::service)atoi(_server.mid(pos+1));
|
||
_server.cut(pos);
|
||
}
|
||
|
||
if (_server.blank() || xvt_str_compare_ignoring_case(_server, "localhost") == 0)
|
||
_server = "127.0.0.1";
|
||
|
||
connect();
|
||
}
|
||
|
||
TSocket_connection::~TSocket_connection()
|
||
{
|
||
if (_socket)
|
||
delete _socket;
|
||
}
|
||
|
||
TSocketClient::TSocketClient()
|
||
: m_pData(NULL), m_dwSize(0)
|
||
{ }
|
||
|
||
TSocketClient::~TSocketClient()
|
||
{
|
||
ReleaseBuffer();
|
||
RemoveAllConnections();
|
||
}
|
||
|
||
TConnection* TSocketClient::OnQueryConnection(const char* service, const char* server)
|
||
{
|
||
TSocket_connection* pConnection = new TSocket_connection(this, service, server);
|
||
if (pConnection->Id() == 0)
|
||
{
|
||
delete pConnection;
|
||
pConnection = NULL;
|
||
}
|
||
|
||
|
||
return pConnection;
|
||
}
|
||
|
||
bool TSocketClient::Request(CONNID id, const char* cmd)
|
||
{
|
||
static bool semaphore = FALSE;
|
||
bool ok = FALSE;
|
||
|
||
if (!semaphore)
|
||
{
|
||
semaphore = TRUE;
|
||
|
||
ReleaseBuffer();
|
||
ok = Execute(id, cmd);
|
||
if (ok)
|
||
{
|
||
TSocket_connection* conn = (TSocket_connection*)GetConnection(id);
|
||
m_dwSize = 0;
|
||
conn->Read((byte*)&m_dwSize, sizeof(m_dwSize));
|
||
ok = m_dwSize > 0;
|
||
if (ok)
|
||
{
|
||
m_pData = new byte[m_dwSize];
|
||
ok = conn->Read(m_pData, m_dwSize);
|
||
}
|
||
}
|
||
|
||
semaphore = FALSE;
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
byte* TSocketClient::GetBuffer(size_t& dwSize)
|
||
{
|
||
dwSize = m_dwSize;
|
||
return m_pData;
|
||
}
|
||
|
||
bool TSocketClient::WriteLine(CONNID id, const char* str)
|
||
{
|
||
TSocket_connection* conn = (TSocket_connection*)GetConnection(id);
|
||
if (conn)
|
||
return conn->WriteLine(str);
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
bool TSocketClient::ReadLine(CONNID id, TString& str)
|
||
{
|
||
TSocket_connection* conn = (TSocket_connection*)GetConnection(id);
|
||
if (conn)
|
||
return conn->ReadLine(str);
|
||
return false;
|
||
}
|
||
|
||
void TSocketClient::ReleaseBuffer()
|
||
{
|
||
if (m_pData)
|
||
{
|
||
delete m_pData;
|
||
m_pData = NULL;
|
||
m_dwSize = 0;
|
||
}
|
||
}
|
||
int TSocketClient::HttpGetHeader(CONNID id, const char* remote, const char* authorization,
|
||
TString_array& header)
|
||
{
|
||
int ret = 0;
|
||
|
||
TSocket_connection* conn = (TSocket_connection*)GetConnection(id);
|
||
TString buf(4*1024);
|
||
buf << "GET " << remote << " HTTP/1.1\r\n"
|
||
<< "User-Agent: Campo\r\n"
|
||
<< "Host: " << conn->Server() << "\r\n";
|
||
|
||
if (authorization && *authorization)
|
||
buf << "Authorization: " << authorization << "\r\n";
|
||
|
||
const TFixed_string rem(remote);
|
||
buf << "Connection: " << (rem.ends_with("/") ? "Close" : "Keep-Alive") << "\r\n";
|
||
|
||
buf << "\r\n";
|
||
|
||
header.destroy();
|
||
if (WriteLine(id, buf))
|
||
{
|
||
for (int r = 0; ; r++)
|
||
{
|
||
ReadLine(id, buf);
|
||
if (buf.blank())
|
||
break;
|
||
if (r == 0)
|
||
ret = atoi(buf.after(' '));
|
||
header.add(buf);
|
||
}
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
bool TSocketClient::HttpIsRedirectedServer(CONNID id, TString & http_server, TFilename & remote, const char* authorization)
|
||
{
|
||
TString_array header;
|
||
const bool redirected = HttpGetHeader(id, remote, NULL, header) == 302;
|
||
if (redirected)
|
||
{
|
||
FOR_EACH_ARRAY_ROW(header, r, row)
|
||
{
|
||
TString& buf = *row;
|
||
if (buf.starts_with("Location:", true))
|
||
{
|
||
buf = buf.after(':');
|
||
if (buf.full())
|
||
{
|
||
buf.trim();
|
||
if (buf.starts_with("http://", true))
|
||
buf.ltrim(7);
|
||
const int slash = buf.find('/');
|
||
if (slash > 0)
|
||
{
|
||
remote = buf.mid(slash);
|
||
if (!remote.ends_with("/"))
|
||
remote << '/';
|
||
http_server = buf.left(slash);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return redirected;
|
||
}
|
||
|
||
static const TString& bytes2str(long b)
|
||
{
|
||
TString& tmp = get_tmp_string(24);
|
||
if (b > 0)
|
||
{
|
||
const long mega = 1024*1024;
|
||
if (b >= mega)
|
||
{
|
||
real m(b); m /= mega;
|
||
tmp = m.stringe(-1, 2); // Numero in formato digeribile da Excel (segue impostazionei internazionali)
|
||
tmp << " MBytes";
|
||
}
|
||
else
|
||
{
|
||
const long kappa = 1024;
|
||
if (b >= kappa)
|
||
tmp.format("%ld KBytes", (b+kappa/2)/kappa);
|
||
else
|
||
tmp.format("%ld Bytes", b);
|
||
}
|
||
}
|
||
else
|
||
tmp = TR("Dimensione sconosciuta");
|
||
return tmp;
|
||
}
|
||
|
||
bool TSocketClient::HttpGetFile(CONNID id, const char* remote, const char* local, const char* authorization)
|
||
{
|
||
bool ok = false;
|
||
|
||
TString_array header;
|
||
const int ret = HttpGetHeader(id, remote, authorization, header);
|
||
if (ret == 200)
|
||
{
|
||
long size = -1; // Unknown size
|
||
FOR_EACH_ARRAY_ROW(header, r, row)
|
||
{
|
||
if (row->starts_with("Content-length:", true))
|
||
{
|
||
size = atol(row->after(':'));
|
||
break;
|
||
}
|
||
}
|
||
if (size == 0) // File not found
|
||
return false;
|
||
|
||
ofstream outfile(local, ios::out | ios::binary);
|
||
if (outfile.good())
|
||
{
|
||
TString buf(16*1024);
|
||
|
||
TToken_string strpi(256, '\n');
|
||
strpi << remote << " - " << bytes2str(size);
|
||
strpi.add(TR("Trasferiti"));
|
||
long total = 0;
|
||
|
||
TSocket_connection* conn = (TSocket_connection*)GetConnection(id);
|
||
skstream* cur_socket = conn->GetSocket();
|
||
|
||
if (size > 0) // Dimensione nota
|
||
{
|
||
if (size <= buf.size()) // File piccolo: Niente barra di progresso
|
||
{
|
||
TWait_cursor hourglass;
|
||
while (total < size && !cur_socket->eof())
|
||
{
|
||
const int nchars = min(buf.size(), size - total);
|
||
cur_socket->read(buf.get_buffer(), nchars);
|
||
const int count = cur_socket->gcount();
|
||
if (count > 0)
|
||
{
|
||
total += count;
|
||
outfile.write(buf, count);
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
TProgind pi(size, strpi, true, true);
|
||
pi.set_caption(TR("Trasferimento in corso..."));
|
||
while (!cur_socket->eof() && !pi.iscancelled())
|
||
{
|
||
const int nchars = min(buf.size(), size - total);
|
||
cur_socket->read(buf.get_buffer(), nchars);
|
||
const int count = cur_socket->gcount();
|
||
if (count > 0)
|
||
{
|
||
outfile.write(buf, count);
|
||
total += count;
|
||
if (total >= size || !pi.setstatus(total)) // Controllo se ormai ho finito
|
||
break;
|
||
strpi.add(TR("Trasferiti"), 1);
|
||
strpi << ' ' << bytes2str(total);
|
||
pi.set_text(strpi);
|
||
}
|
||
}
|
||
}
|
||
ok = total >= size; // Ho finito per bene?
|
||
}
|
||
else // Dimensione ignota
|
||
{
|
||
TIndwin pi(100, strpi, true, false);
|
||
while (!cur_socket->eof() && !pi.iscancelled())
|
||
{
|
||
cur_socket->read(buf.get_buffer(), buf.size());
|
||
const int count = cur_socket->gcount();
|
||
if (count > 0)
|
||
{
|
||
outfile.write(buf, count);
|
||
total += count;
|
||
strpi.add(TR("Trasferiti"), 1);
|
||
strpi << ' ' << bytes2str(total);
|
||
pi.set_text(strpi);
|
||
}
|
||
}
|
||
ok = total > 0 && !pi.iscancelled(); // Ho finito per bene?
|
||
}
|
||
}
|
||
else
|
||
error_box(FR("Impossibile scrivere il file %s"), local);
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
HIDDEN int find_href(const TString& riga, int from, TString& filename)
|
||
{
|
||
while (from >= 0)
|
||
{
|
||
int href = riga.find("<a href=\"", from);
|
||
if (href >= 0)
|
||
{
|
||
href += 9;
|
||
const int quotes = riga.find('"', href);
|
||
if (quotes > 0)
|
||
{
|
||
filename = riga.sub(href, quotes);
|
||
from = quotes+1;
|
||
}
|
||
else
|
||
{
|
||
filename = riga.mid(href);
|
||
from = -1;
|
||
}
|
||
filename.trim();
|
||
if (filename.match("*.*"))
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
from = -1;
|
||
break;
|
||
}
|
||
}
|
||
return from;
|
||
}
|
||
|
||
bool TSocketClient::HttpGetDir(CONNID id, const char* remote, TString_array& list)
|
||
{
|
||
TFilename local; local.temp();
|
||
const bool ok = HttpGetFile(id, remote, local);
|
||
if (ok)
|
||
{
|
||
TString riga(512);
|
||
TFilename name;
|
||
ifstream s(local);
|
||
while (!s.eof())
|
||
{
|
||
s.getline(riga.get_buffer(), riga.size());
|
||
riga.lower();
|
||
for (int href = find_href(riga, 0, name); href >= 0; href = find_href(riga, href, name))
|
||
list.add(name);
|
||
}
|
||
s.close();
|
||
xvt_fsys_remove_file(local);
|
||
}
|
||
|
||
return ok;
|
||
}
|
||
|
||
bool TSocketClient::HttpSoap(CONNID id, const char* cmd)
|
||
{
|
||
bool ok = false;
|
||
|
||
TSocket_connection* conn = (TSocket_connection*)GetConnection(id);
|
||
if (conn == NULL)
|
||
return ok;
|
||
|
||
if (cmd == NULL || *cmd == '\0')
|
||
return ok;
|
||
|
||
char hostname[256];
|
||
xvt_sys_get_host_name(hostname, sizeof(hostname));
|
||
|
||
TString content(256);
|
||
content = cmd;
|
||
if (content.find("<SOAP-ENV") < 0) // Controllo se c'<27> tutto
|
||
{
|
||
content.insert("<SOAP-ENV:Envelope>\n<SOAP-ENV:Body>\n");
|
||
content << "</SOAP-ENV:Body>\n</SOAP-ENV:Envelope>\r\n\r\n";
|
||
}
|
||
|
||
TString buf(4096);
|
||
buf << "POST / HTTP/1.1\n"
|
||
<< "User-Agent: Campo\n"
|
||
<< "Host: " << hostname << "\n"
|
||
<< "Content-Type: text/xml; charset=utf-8\n"
|
||
<< "Content-length: " << content.len() << "\n"
|
||
<< "SOAPAction: \"/\"\r\n\r\n"
|
||
<< content;
|
||
|
||
if (conn->WriteLine(buf))
|
||
{
|
||
skstream* cur_socket = conn->GetSocket();
|
||
|
||
unsigned long size = 0;
|
||
for (int r = 0; !cur_socket->eof(); r++)
|
||
{
|
||
conn->ReadLine(buf);
|
||
if (buf.blank())
|
||
break;
|
||
if (buf.compare("Content-length:", 15, TRUE) == 0)
|
||
{
|
||
const int colon = buf.find(':');
|
||
size = atol(buf.mid(colon+1));
|
||
}
|
||
}
|
||
if (size > 0)
|
||
{
|
||
if (size >= m_dwSize)
|
||
{
|
||
ReleaseBuffer();
|
||
m_dwSize = size+1;
|
||
m_pData = new BYTE[m_dwSize];
|
||
}
|
||
memset(m_pData, 0, m_dwSize);
|
||
cur_socket->read((char *) m_pData, size);
|
||
ok = true;
|
||
}
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
static const char* const eol = "\r\n";
|
||
|
||
bool TSocketClient::HttpPostFile(CONNID id, const char* remote, const char* local, const char* authorization)
|
||
{
|
||
bool ok = false;
|
||
|
||
TSocket_connection* conn = (TSocket_connection*)GetConnection(id);
|
||
if (conn == NULL)
|
||
return ok;
|
||
|
||
char peer[MAX_PATH];
|
||
conn->GetSocket()->getpeername(peer, sizeof(peer));
|
||
|
||
TString buf(4096);
|
||
buf << "POST " << remote << " HTTP/1.1" << eol
|
||
<< "Host: " << peer << eol
|
||
<< "User-Agent: Campo" << eol
|
||
<< "Content-Type: text/plain" << eol
|
||
<< "Content-Length: " << fsize(local) << eol;
|
||
if (authorization && *authorization)
|
||
buf << "Authorization: " << authorization << eol;
|
||
buf << eol;
|
||
|
||
ok = conn->WriteLine(buf);
|
||
if (ok)
|
||
{
|
||
ifstream input(local, ios::binary);
|
||
|
||
while (!input.eof())
|
||
{
|
||
input.read(buf.get_buffer(), buf.size());
|
||
const size_t count = input.gcount();
|
||
if (count > 0)
|
||
{
|
||
skstream* cur_socket = conn->GetSocket();
|
||
|
||
cur_socket->sync();
|
||
cur_socket->write(buf, count);
|
||
cur_socket->flush();
|
||
}
|
||
else
|
||
break;
|
||
}
|
||
conn->ReadLine(buf);
|
||
ok = buf.find("200 OK") >= 0;
|
||
|
||
if (ok)
|
||
{
|
||
skstream* cur_socket = conn->GetSocket();
|
||
unsigned long size = 0;
|
||
for (int r = 0; !cur_socket->eof(); r++)
|
||
{
|
||
cur_socket->getline(buf.get_buffer(), buf.size(), '\n');
|
||
if (buf.blank())
|
||
break;
|
||
if (buf.starts_with("Content-length:", true) == 0)
|
||
{
|
||
const int colon = buf.find(':');
|
||
size = atol(buf.mid(colon+1));
|
||
}
|
||
}
|
||
ReleaseBuffer();
|
||
ok = size > 0;
|
||
if (ok)
|
||
{
|
||
m_dwSize = size;
|
||
m_pData = new BYTE[m_dwSize+1];
|
||
memset(m_pData, 0, size_t(m_dwSize+1));
|
||
cur_socket->read((char *) m_pData, (size_t)m_dwSize);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
ReleaseBuffer();
|
||
m_dwSize = buf.len()+1;
|
||
m_pData = new BYTE[m_dwSize];
|
||
memcpy(m_pData, buf, (size_t)m_dwSize);
|
||
}
|
||
}
|
||
|
||
return ok;
|
||
}
|
||
|
||
static bool FtpSendCommand(TSocket_connection& conn, const char* cmd, const char* param, TString* line)
|
||
{
|
||
TString command = cmd;
|
||
if (param && *param)
|
||
command << ' ' << param;
|
||
command << "\r\n";
|
||
|
||
if (!conn.WriteLine(command))
|
||
return false;
|
||
|
||
if (line != NULL)
|
||
{
|
||
line->cut(0);
|
||
if (!conn.ReadLine(*line))
|
||
return false;
|
||
line->rtrim();
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
bool TSocketClient::FtpSendFile(CONNID id, const char* remote, const char* local, const char* user, const char* pass)
|
||
{
|
||
bool ok = false;
|
||
|
||
if (!fexist(local))
|
||
return ok;
|
||
|
||
TString response;
|
||
if (!ReadLine(id, response)) // 220 Welcome
|
||
return ok;
|
||
|
||
TSocket_connection& conn = *(TSocket_connection*)GetConnection(id);
|
||
if (user==NULL || !*user)
|
||
user = "anonimous";
|
||
ok = FtpSendCommand(conn, "USER", user, &response); // 331 Please specify the password.
|
||
if (!ok || response[0] != '3')
|
||
return false;
|
||
|
||
if (pass==NULL || !*pass)
|
||
pass = "user@campo.it";
|
||
|
||
ok = FtpSendCommand(conn, "PASS", pass, &response); // 230 Login successful.
|
||
if (!ok || response[0] != '2')
|
||
return false;
|
||
|
||
ok = FtpSendCommand(conn, "TYPE", "I", &response); // 200 Switching to Binary mode.
|
||
if (!ok || response[0] != '2')
|
||
return false;
|
||
|
||
FtpSendCommand(conn, "PASV", NULL, &response); // 227 Entering Passive Mode (192,168,4,3,4,82)
|
||
const TString& address = response.after("(").before(")");
|
||
int a[6];
|
||
if (sscanf(address, "%d,%d,%d,%d,%d,%d", &a[0], &a[1], &a[2], &a[3], &a[4], &a[5]) != 6)
|
||
return false;
|
||
|
||
ok = FtpSendCommand(conn, "STOR", remote, NULL);
|
||
if (!ok)
|
||
return false;
|
||
|
||
TString16 addr; addr.format("%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
|
||
const skstream::service port = skstream::service((a[4] << 8) | a[5]);
|
||
skstream outstream(addr, port) ;
|
||
|
||
ifstream input(local, ios::binary);
|
||
while (!input.eof())
|
||
{
|
||
input.read(response.get_buffer(), 1024*4);
|
||
const size_t count = input.gcount();
|
||
if (count > 0)
|
||
{
|
||
outstream.sync();
|
||
outstream.write(response, count);
|
||
outstream.flush();
|
||
}
|
||
else
|
||
break;
|
||
}
|
||
ok = conn.ReadLine(response); // 150 Ok to send data.
|
||
if (ok)
|
||
ok = response[0] == '1';
|
||
|
||
FtpSendCommand(conn, "QUIT", NULL, NULL);
|
||
return ok;
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TDDEClient
|
||
///////////////////////////////////////////////////////////
|
||
|
||
TConnection* TDDEClient::OnQueryConnection(const char* service, const char* server)
|
||
{
|
||
TConnection* conn = NULL;
|
||
CONNID id = aga_dde_connect(server, service, "");
|
||
if (id != 0)
|
||
conn = new TConnection(this, id);
|
||
return conn;
|
||
}
|
||
|
||
bool TDDEClient::OnRemoveConnection(CONNID id)
|
||
{
|
||
aga_dde_terminate(id);
|
||
return true;
|
||
}
|
||
|
||
|
||
byte* TDDEClient::GetBuffer(unsigned int& dwSize)
|
||
{ return NULL; }
|
||
|
||
void TDDEClient::ReleaseBuffer()
|
||
{ }
|
||
|
||
bool TDDEClient::Execute(CONNID id, const char* cmd)
|
||
{
|
||
return aga_dde_execute(id, cmd) == 0;
|
||
}
|