Files correlati : Ricompilazione Demo : [ ] Commento : Aggiunte utili per gestione dizionario assoc.cpp Aggiunta possibilita' di selezionare un elemento causale di un assoc controls.cpp Corretta gestione scrollbar dei listbox diction.cpp Migliorata selezione caratteri da trimmare dalle traduzioni isam.cpp Corretto azzeramento dei memo (non azzerava il TString_array corrispondente) msksheet.cpp Resa personalizzabile la larghezza della colonna col numero di riga netsock.cpp Migliorata gestione "a capo" in protocollo soap progind.cpp Corretto posizionamento progind sovrapposte relapp.cpp Cambiato un messaggio di richiesta annullamento git-svn-id: svn://10.65.10.50/trunk@11651 c028cbd2-c16b-5b4b-a496-9718f37d4682
929 lines
21 KiB
C++
Executable File
929 lines
21 KiB
C++
Executable File
#define XVT_INCL_NATIVE
|
||
#include <progind.h>
|
||
#include <config.h>
|
||
#include <agasys.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
|
||
|
||
#include <fstream.h>
|
||
|
||
#include "winsock.h"
|
||
|
||
//
|
||
// 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
|
||
const WORD wMinVer = 0x0101; // request WinSock v1.1 (at least)
|
||
WSADATA wsaData;
|
||
if( 0 == WSAStartup( wMinVer, &wsaData ) )
|
||
return TRUE ;
|
||
return FALSE ;
|
||
}
|
||
|
||
int skstream::shutdown( void )
|
||
{
|
||
// platform dependent shutdown
|
||
if( 0 == WSACleanup() )
|
||
return TRUE ;
|
||
return FALSE ;
|
||
}
|
||
|
||
skstream::skstream( void ) : _sockbuf( _socket ), iostream( &_sockbuf )
|
||
{
|
||
if( init() )
|
||
attach( INVALID_SOCKET ) ;
|
||
}
|
||
|
||
skstream::skstream( const char *addr, const service port, const role side )
|
||
: _sockbuf( _socket ), iostream( &_sockbuf )
|
||
{
|
||
if( init() )
|
||
{
|
||
attach( INVALID_SOCKET ) ;
|
||
open( addr, port, side ) ;
|
||
}
|
||
}
|
||
|
||
skstream::skstream( SOCKET sock ) : _sockbuf( _socket ), iostream( &_sockbuf )
|
||
{
|
||
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 ;
|
||
sa.sin_addr.S_un.S_addr = INADDR_ANY ;
|
||
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;
|
||
}
|
||
|
||
sa.sin_addr.S_un.S_addr = indirizzo;
|
||
sa.sin_port = ::htons( port ) ;
|
||
|
||
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 ) ;
|
||
if( SOCKET_ERROR ==::getpeername( getsocket(), (sockaddr *)&sa, &sasize ) )
|
||
// 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 ) ;
|
||
if( SOCKET_ERROR ==::getpeername( getsocket(), (sockaddr *)&sa, &sasize ) )
|
||
// Cannot get peer port
|
||
return ::ntohs( IPPORT_RESERVED ) ;
|
||
return ::ntohs( sa.sin_port ) ;
|
||
}
|
||
|
||
//
|
||
// sockbuf
|
||
//
|
||
sockbuf::sockbuf( SOCKET &sock ) : _socket( sock ), streambuf( NULL, 0 )
|
||
{
|
||
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 ), streambuf( buf, length )
|
||
{
|
||
_buffer = NULL ;
|
||
|
||
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:
|
||
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(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() || stricmp(_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;
|
||
}
|
||
}
|
||
|
||
bool TSocketClient::HttpGetFile(CONNID id, const char* remote, const char* local, const char* authorization)
|
||
|
||
{
|
||
bool ok = FALSE;
|
||
|
||
TString buf(4096);
|
||
buf << "GET " << remote << " HTTP/1.0\r\n"
|
||
<< "User-Agent: Campo\r\n";
|
||
if (authorization && *authorization)
|
||
buf << "Authorization: " << authorization << "\r\n";
|
||
buf << "\r\n";
|
||
|
||
if (WriteLine(id, buf))
|
||
|
||
|
||
{
|
||
const clock_t start = clock();
|
||
|
||
long size = 0;
|
||
for (int r = 0; ; r++)
|
||
{
|
||
ReadLine(id, buf);
|
||
if (buf.blank())
|
||
break;
|
||
if (r == 0 && buf.find("200 OK") < 0)
|
||
return FALSE; // File not found
|
||
if (buf.compare("Content-length:", 15, TRUE) == 0)
|
||
{
|
||
const int colon = buf.find(':');
|
||
size = atol(buf.mid(colon+1));
|
||
}
|
||
}
|
||
ofstream outfile(local, ios::out | ios::binary);
|
||
if (outfile.good())
|
||
{
|
||
buf.cut(0) << remote << " - " << (size / 1024 + 1) << " KBytes";
|
||
TProgind pi(size, buf, TRUE, TRUE);
|
||
|
||
long total = 0;
|
||
|
||
skstream* cur_socket = ((TSocket_connection*)GetConnection(id))->GetSocket();
|
||
while (!cur_socket->eof())
|
||
{
|
||
cur_socket->read(buf.get_buffer(), buf.size());
|
||
const int count = cur_socket->gcount();
|
||
if (count > 0)
|
||
{
|
||
outfile.write(buf, count);
|
||
total += count;
|
||
pi.setstatus(total);
|
||
if (pi.iscancelled())
|
||
break;
|
||
}
|
||
}
|
||
ok = pi.isfinished();
|
||
}
|
||
else
|
||
error_box("Impossibile scrivere il file %s", local);
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
HIDDEN int find_href(const TString& riga)
|
||
{
|
||
int href = -1;
|
||
int img = riga.find("<img");
|
||
if (img >= 0)
|
||
href = riga.find("href=", img+4);
|
||
else
|
||
{
|
||
img = riga.find("<IMG");
|
||
if (img >= 0)
|
||
href = riga.find("HREF=", img+4);
|
||
}
|
||
return href;
|
||
}
|
||
|
||
bool TSocketClient::HttpGetDir(CONNID id, const char* remote, TString_array& list)
|
||
{
|
||
TFilename local; local.temp();
|
||
const bool ok = HttpGetFile(id, remote, local);
|
||
if (ok)
|
||
{
|
||
ifstream s(local);
|
||
TString riga(256);
|
||
while (!s.eof())
|
||
{
|
||
s.getline(riga.get_buffer(), riga.size());
|
||
const int href = find_href(riga);
|
||
if (href > 0)
|
||
{
|
||
const int start = riga.find('"', href) + 1;
|
||
if (start > href && isalnum(riga[start + 1]))
|
||
{
|
||
const int stop = riga.find('"', start);
|
||
if (stop > start)
|
||
{
|
||
const TString& name = riga.sub(start, stop);
|
||
list.add(name);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
s.close();
|
||
::remove(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[64];
|
||
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";
|
||
}
|
||
|
||
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(m_pData, size);
|
||
ok = true;
|
||
}
|
||
}
|
||
return ok;
|
||
}
|
||
|
||
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;
|
||
const char* const eol = "\r\n";
|
||
|
||
TString buf(4096);
|
||
buf << "POST " << remote << " HTTP/1.0" << eol
|
||
<< "User-Agent: Campo/1.7" << 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::nocreate | 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(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;
|
||
}
|