campo-sirio/include/netsock.cpp
guy e580a22a67 Patch level : 10.0
Files correlati     : agalib, mg3
Ricompilazione Demo : [ ]
Commento            :
0001561: 002177 Pharmatex - excel da mastrini
Con la patch 634 l'esportazione mastrini in excell non ha più l'intestazione colonne


git-svn-id: svn://10.65.10.50/trunk@20177 c028cbd2-c16b-5b4b-a496-9718f37d4682
2010-03-02 11:23:20 +00:00

1269 lines
29 KiB
C++
Executable File
Raw Blame History

#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);
bool ReadTimeout(byte* buf, size_t size, int timeout);
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[4096]; memset(buf, 0, sizeof(buf));
calza->getline(buf, sizeof(buf)-1, '\n');
str = buf;
}
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::ReadTimeout(byte* buf, size_t size, int timeout)
{
if (timeout <= 0)
return Read(buf, size);
skstream* calza = GetSocket();
bool ok = calza != NULL && calza->good();
if (ok)
{
clock_t cWaited = 0; // msec waited so far
clock_t cToWait = 67; // next time slice to wait 67+134+268+536=1005
ok = false;
while (!ok && cWaited < timeout*1000)
{
xvt_sys_sleep(cToWait); // wait a bit
cWaited += cToWait; // increment waited time
cToWait = min(cToWait*2, 1000); // compute next waiting slice
ok = ::recv(calza->getsocket(), (char*)buf, 1, MSG_PEEK)>0; // Peek for incoming data
}
if (ok)
{
calza->read((char*)buf, size);
ok = calza->gcount() == size;
}
}
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), m_nTimeout(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;
if (m_nTimeout > 0)
conn->ReadTimeout((byte*)&m_dwSize, sizeof(m_dwSize), m_nTimeout);
else
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 size_t count = (size_t)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 size_t count = (size_t)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 size_t count = (size_t)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 = (size_t)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(4096), 4096);
const size_t count = (size_t)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;
}