#define XVT_INCL_NATIVE #include #include #include #include #include // 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 #endif #ifdef WIN32 #include "winsock.h" #else #include #include #include #include #include #include #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 // 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(); if (b > 0) { const long mega = 1024*1024; if (b >= mega) tmp.format("%ld MBytes", (b+mega/2)/mega); 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(8*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 { 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); 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) { int href = -1; int img = riga.find("= 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(512); while (!s.eof()) { s.getline(riga.get_buffer(), riga.size()); riga.lower(); for (int href = find_href(riga, 0); href > 0; href = find_href(riga, href+5)) { const int start = riga.find('"', href) + 1; if (start > href) { const int stop = riga.find('"', start); if (stop > start) { const TString& name = riga.sub(start, stop); if (isdigit(name[0]) || (name[0]>='a' && name[0]<='z')) // isalnum non funziona! 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[256]; xvt_sys_get_host_name(hostname, sizeof(hostname)); TString content(256); content = cmd; if (content.find("\n\n"); content << "\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; } 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" << 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; }