wxBase:
+- wxSocket support
- wxDateTime replaces and extends old wxDate and wxTime classes (still
available but strongly deprecated) with many new features
- wxLongLong class provides support for (signed) 64 bit integers
% ----------------------------------------------------------------------------
\membersection{wxFTP::GetList}
-\func{wxList *}{GetList}{\param{const wxString\&}{ wildcard}}
+\func{bool}{GetList}{\param{wxArrayString\& }{files}, \param{const wxString\&}{ wildcard = ""}}
The GetList function is quite low-level. It returns the list of the files in
the current directory. The list can be filtered using the {\it wildcard} string.
-If {\it wildcard} is a NULL string, it will return all files in directory.
+If {\it wildcard} is empty (default), it will return all files in directory.
The form of the list can change from one peer system to another. For example,
for a UNIX peer system, it will look like this:
1 file(s) 520 196 bytes
\end{verbatim}
-The list is a string list and one node corresponds to a line sent by the peer.
+Return value: TRUE if the file list was successfully retrieved, FALSE
+otherwise.
% ----------------------------------------------------------------------------
// Copyright: (c) 1997, 1998 Guilhem Lavaux
// Licence: wxWindows license
/////////////////////////////////////////////////////////////////////////////
+
#ifndef __WX_FTP_H__
#define __WX_FTP_H__
#include "wx/protocol/protocol.h"
#include "wx/url.h"
-class WXDLLEXPORT wxFTP : public wxProtocol {
- DECLARE_DYNAMIC_CLASS(wxFTP)
- DECLARE_PROTOCOL(wxFTP)
+class WXDLLEXPORT wxFTP : public wxProtocol
+{
public:
typedef enum { ASCII, BINARY } wxFTPmode;
wxFTP();
- ~wxFTP();
+ virtual ~wxFTP();
- bool Close();
bool Connect(wxSockAddress& addr, bool wait = TRUE);
bool Connect(const wxString& host);
+ // [forcibly] close the connection
+ bool Close(bool force = FALSE);
+
void SetUser(const wxString& user) { m_user = user; }
void SetPassword(const wxString& passwd) { m_passwd = passwd; }
- // Low-level methods
- bool SendCommand(const wxString& command, char exp_ret);
- inline virtual wxProtocolError GetError()
- { return m_lastError; }
- const wxString& GetLastResult(); // Get the complete return
-
// Filesystem commands
bool ChDir(const wxString& dir);
bool MkDir(const wxString& dir);
wxOutputStream *GetOutputStream(const wxString& path);
// List method
+ bool GetList(wxArrayString& files, const wxString& wildcard = wxEmptyString);
+
+ // Low-level methods
+ bool SendCommand(const wxString& command, char exp_ret);
+ virtual wxProtocolError GetError() { return m_lastError; }
+ const wxString& GetLastResult(); // Get the complete return
+
+ // deprecated
wxList *GetList(const wxString& wildcard);
protected:
wxSocketClient *GetPort();
bool GetResult(char exp);
+
+ DECLARE_DYNAMIC_CLASS(wxFTP)
+ DECLARE_PROTOCOL(wxFTP)
};
-#endif
+#endif // __WX_FTP_H__
/////////////////////////////////////////////////////////////////////////////
-// Name: protocol.h
+// Name: wx/protocol/protocol.h
// Purpose: Protocol base class
// Author: Guilhem Lavaux
// Modified by:
// Copyright: (c) 1997, 1998 Guilhem Lavaux
// Licence: wxWindows license
/////////////////////////////////////////////////////////////////////////////
+
#ifndef _WX_PROTOCOL_PROTOCOL_H
#define _WX_PROTOCOL_PROTOCOL_H
#include "wx/defs.h"
-
#include "wx/object.h"
#include "wx/string.h"
#include "wx/stream.h"
#if wxUSE_SOCKETS
-#include "wx/socket.h"
+ #include "wx/socket.h"
#endif
-typedef enum {
- wxPROTO_NOERR = 0,
- wxPROTO_NETERR,
- wxPROTO_PROTERR,
- wxPROTO_CONNERR,
- wxPROTO_INVVAL,
- wxPROTO_NOHNDLR,
- wxPROTO_NOFILE,
- wxPROTO_ABRT,
- wxPROTO_RCNCT,
- wxPROTO_STREAMING
-} wxProtocolError;
-
-// For protocols
-#define DECLARE_PROTOCOL(class) \
-public: \
- static wxProtoInfo g_proto_##class;
+// ----------------------------------------------------------------------------
+// constants
+// ----------------------------------------------------------------------------
-#define IMPLEMENT_PROTOCOL(class, name, serv, host) \
-wxProtoInfo class::g_proto_##class(name, serv, host, CLASSINFO(class));
+typedef enum
+{
+ wxPROTO_NOERR = 0,
+ wxPROTO_NETERR,
+ wxPROTO_PROTERR,
+ wxPROTO_CONNERR,
+ wxPROTO_INVVAL,
+ wxPROTO_NOHNDLR,
+ wxPROTO_NOFILE,
+ wxPROTO_ABRT,
+ wxPROTO_RCNCT,
+ wxPROTO_STREAMING
+} wxProtocolError;
-class WXDLLEXPORT wxProtoInfo : public wxObject {
- DECLARE_DYNAMIC_CLASS(wxProtoInfo)
-protected:
- wxProtoInfo *next;
- wxString m_protoname;
- wxString prefix;
- wxString m_servname;
- wxClassInfo *m_cinfo;
- bool m_needhost;
-
- friend class wxURL;
-public:
- wxProtoInfo(const wxChar *name, const wxChar *serv_name, const bool need_host1,
- wxClassInfo *info);
-};
+// ----------------------------------------------------------------------------
+// wxProtocol: abstract base class for all protocols
+// ----------------------------------------------------------------------------
class WXDLLEXPORT wxProtocol
#if wxUSE_SOCKETS
- : public wxSocketClient {
+ : public wxSocketClient
#else
- : public wxObject {
+ : public wxObject
#endif
- DECLARE_ABSTRACT_CLASS(wxProtocol)
+{
public:
- wxProtocol();
+ wxProtocol();
#if wxUSE_SOCKETS
- bool Reconnect();
- virtual bool Connect( const wxString& WXUNUSED(host) ) { return FALSE; }
- virtual bool Connect( wxSockAddress& addr, bool WXUNUSED(wait) = TRUE) { return wxSocketClient::Connect(addr); }
-#endif
+ bool Reconnect();
+ virtual bool Connect( const wxString& WXUNUSED(host) ) { return FALSE; }
+ virtual bool Connect( wxSockAddress& addr, bool WXUNUSED(wait) = TRUE) { return wxSocketClient::Connect(addr); }
+
+ // read a '\r\n' terminated line from the given socket and put it in
+ // result (without the terminators)
+ static wxProtocolError ReadLine(wxSocketBase *socket, wxString& result);
+
+ // read a line from this socket - this one can be overridden in the
+ // derived classes if different line termination convention is to be used
+ virtual wxProtocolError ReadLine(wxString& result);
+#endif // wxUSE_SOCKETS
- virtual bool Abort() = 0;
- virtual wxInputStream *GetInputStream(const wxString& path) = 0;
- virtual wxProtocolError GetError() = 0;
- virtual wxString GetContentType() { return wxEmptyString; }
- virtual void SetUser(const wxString& WXUNUSED(user)) {}
- virtual void SetPassword(const wxString& WXUNUSED(passwd) ) {}
+ virtual bool Abort() = 0;
+ virtual wxInputStream *GetInputStream(const wxString& path) = 0;
+ virtual wxProtocolError GetError() = 0;
+ virtual wxString GetContentType() { return wxEmptyString; }
+ virtual void SetUser(const wxString& WXUNUSED(user)) {}
+ virtual void SetPassword(const wxString& WXUNUSED(passwd) ) {}
+
+private:
+ DECLARE_ABSTRACT_CLASS(wxProtocol)
};
#if wxUSE_SOCKETS
wxProtocolError WXDLLEXPORT GetLine(wxSocketBase *sock, wxString& result);
#endif
+// ----------------------------------------------------------------------------
+// macros for protocol classes
+// ----------------------------------------------------------------------------
+
+#define DECLARE_PROTOCOL(class) \
+public: \
+ static wxProtoInfo g_proto_##class;
+
+#define IMPLEMENT_PROTOCOL(class, name, serv, host) \
+wxProtoInfo class::g_proto_##class(name, serv, host, CLASSINFO(class));
+
+class WXDLLEXPORT wxProtoInfo : public wxObject
+{
+public:
+ wxProtoInfo(const wxChar *name,
+ const wxChar *serv_name,
+ const bool need_host1,
+ wxClassInfo *info);
+
+protected:
+ wxProtoInfo *next;
+ wxString m_protoname;
+ wxString prefix;
+ wxString m_servname;
+ wxClassInfo *m_cinfo;
+ bool m_needhost;
+
+ friend class wxURL;
+
+ DECLARE_DYNAMIC_CLASS(wxProtoInfo)
+};
+
#endif // _WX_PROTOCOL_PROTOCOL_H
//#define TEST_LOG
//#define TEST_LONGLONG
//#define TEST_MIME
-//#define TEST_SOCKETS
+#define TEST_SOCKETS
//#define TEST_STRINGS
//#define TEST_THREADS
-#define TEST_TIMER
+//#define TEST_TIMER
// ============================================================================
// implementation
// ============================================================================
+// ----------------------------------------------------------------------------
+// helper functions
+// ----------------------------------------------------------------------------
+
+#if defined(TEST_STRINGS) || defined(TEST_SOCKETS)
+
+// replace TABs with \t and CRs with \n
+static wxString MakePrintable(const wxChar *s)
+{
+ wxString str(s);
+ (void)str.Replace(_T("\t"), _T("\\t"));
+ (void)str.Replace(_T("\n"), _T("\\n"));
+ (void)str.Replace(_T("\r"), _T("\\r"));
+
+ return str;
+}
+
+#endif // MakePrintable() is used
+
// ----------------------------------------------------------------------------
// wxCmdLineParser
// ----------------------------------------------------------------------------
#ifdef TEST_SOCKETS
#include <wx/socket.h>
+#include <wx/protocol/protocol.h>
+#include <wx/protocol/ftp.h>
+#include <wx/protocol/http.h>
+
+static void TestSocketServer()
+{
+ puts("*** Testing wxSocketServer ***\n");
+
+ // we want to launch a server
+ wxIPV4address addr;
+ addr.Service(3000);
+
+ wxSocketServer *server = new wxSocketServer(addr);
+ if ( !server->Ok() )
+ {
+ puts("ERROR: failed to bind");
+ }
+}
static void TestSocketClient()
{
puts("*** Testing wxSocketClient ***\n");
- wxIPV4address addrDst;
- addrDst.Hostname("www.wxwindows.org");
- addrDst.Service(80);
+ static const char *hostname = "www.wxwindows.org";
+
+ wxIPV4address addr;
+ addr.Hostname(hostname);
+ addr.Service(80);
+
+ printf("--- Attempting to connect to %s:80...\n", hostname);
wxSocketClient client;
- if ( !client.Connect(addrDst) )
+ if ( !client.Connect(addr) )
{
- printf("ERROR: failed to connect to %s\n", addrDst.Hostname().c_str());
+ printf("ERROR: failed to connect to %s\n", hostname);
}
else
{
+ printf("--- Connected to %s:%u...\n",
+ addr.Hostname().c_str(), addr.Service());
+
char buf[8192];
- client.Write("get /front.htm\n", 17);
+ // could use simply "GET" here I suppose
+ wxString cmdGet =
+ wxString::Format("GET http://%s/\r\n", hostname);
+ client.Write(cmdGet, cmdGet.length());
+ printf("--- Sent command '%s' to the server\n",
+ MakePrintable(cmdGet).c_str());
client.Read(buf, WXSIZEOF(buf));
- printf("Server replied:\n%s", buf);
+ printf("--- Server replied:\n%s", buf);
+ }
+}
+
+static void TestProtocolFtp()
+{
+ puts("*** Testing wxFTP ***\n");
+
+ wxLog::AddTraceMask(_T("ftp"));
+
+ static const char *hostname = "ftp.wxwindows.org";
+
+ printf("--- Attempting to connect to %s:21...\n", hostname);
+
+ wxFTP ftp;
+ if ( !ftp.Connect(hostname) )
+ {
+ printf("ERROR: failed to connect to %s\n", hostname);
+ }
+ else
+ {
+ printf("--- Connected to %s, current directory is '%s'\n",
+ hostname, ftp.Pwd().c_str());
+ if ( !ftp.ChDir(_T("pub")) )
+ {
+ puts("ERROR: failed to cd to pub");
+ }
+
+ wxArrayString files;
+ if ( !ftp.GetList(files) )
+ {
+ puts("ERROR: failed to get list of files");
+ }
+ else
+ {
+ printf("List of files under '%s':\n", ftp.Pwd().c_str());
+ size_t count = files.GetCount();
+ for ( size_t n = 0; n < count; n++ )
+ {
+ printf("\t%s\n", files[n].c_str());
+ }
+ puts("End of the file list");
+ }
+
+ if ( !ftp.ChDir(_T("..")) )
+ {
+ puts("ERROR: failed to cd to ..");
+ }
+
+ static const char *filename = "welcome.msg";
+ wxInputStream *in = ftp.GetInputStream(filename);
+ if ( !in )
+ {
+ puts("ERROR: couldn't get input stream");
+ }
+ else
+ {
+ size_t size = in->StreamSize();
+ printf("Reading file %s (%u bytes)...", filename, size);
+
+ char *data = new char[size];
+ if ( !in->Read(data, size) )
+ {
+ puts("ERROR: read error");
+ }
+ else
+ {
+ printf("\nContents of %s:\n%s\n", filename, data);
+ }
+
+ delete [] data;
+ delete in;
+ }
}
}
puts("");
}
-// replace TABs with \t and CRs with \n
-static wxString MakePrintable(const wxChar *s)
-{
- wxString str(s);
- (void)str.Replace(_T("\t"), _T("\\t"));
- (void)str.Replace(_T("\n"), _T("\\n"));
- (void)str.Replace(_T("\r"), _T("\\r"));
-
- return str;
-}
-
static void TestStringTokenizer()
{
puts("*** Testing wxStringTokenizer ***");
#endif // TEST_MIME
#ifdef TEST_SOCKETS
- TestSocketClient();
+ if ( 0 )
+ {
+ TestSocketServer();
+ TestSocketClient();
+ }
+ TestProtocolFtp();
#endif // TEST_SOCKETS
#ifdef TEST_TIMER
#include "wx/sckstrm.h"
#include "wx/protocol/protocol.h"
#include "wx/protocol/ftp.h"
+#include "wx/log.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
+// the length of FTP status code (3 digits)
+static const size_t LEN_CODE = 3;
+
#define FTP_BSIZE 1024
IMPLEMENT_DYNAMIC_CLASS(wxFTP, wxProtocol)
////////////////////////////////////////////////////////////////
wxFTP::wxFTP()
- : wxProtocol()
+ : wxProtocol()
{
- m_lastError = wxPROTO_NOERR;
- m_streaming = FALSE;
+ m_lastError = wxPROTO_NOERR;
+ m_streaming = FALSE;
- m_user = wxT("anonymous");
- m_passwd = wxGetUserId();
- m_passwd += wxT('@');
- m_passwd += wxGetHostName();
+ m_user = wxT("anonymous");
+ m_passwd << wxGetUserId() << wxT('@') << wxGetFullHostName();
- SetNotify(0);
- SetFlags(wxSOCKET_NONE);
+ SetNotify(0);
+ SetFlags(wxSOCKET_NONE);
}
wxFTP::~wxFTP()
{
- SendCommand("QUIT", '2');
+ Close();
}
////////////////////////////////////////////////////////////////
return Connect(addr);
}
-bool wxFTP::Close()
+bool wxFTP::Close(bool force)
{
- if (m_streaming) {
- m_lastError = wxPROTO_STREAMING;
- return FALSE;
- }
- if (IsConnected())
- SendCommand(wxString(wxT("QUIT")), '2');
+ if ( m_streaming )
+ {
+ if ( !force )
+ {
+ m_lastError = wxPROTO_STREAMING;
+ return FALSE;
+ }
+
+ (void)Abort();
+ }
+
+ if ( IsConnected() )
+ SendCommand(wxT("QUIT"), '2');
- return wxSocketClient::Close();
+ return wxSocketClient::Close();
}
-////////////////////////////////////////////////////////////////
-////// wxFTP low-level methods /////////////////////////////////
-////////////////////////////////////////////////////////////////
+// ============================================================================
+// low level methods
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// Send command to FTP server
+// ----------------------------------------------------------------------------
+
bool wxFTP::SendCommand(const wxString& command, char exp_ret)
{
- wxString tmp_str;
+ wxString tmp_str;
- if (m_streaming) {
- m_lastError = wxPROTO_STREAMING;
- return FALSE;
- }
- tmp_str = command + wxT("\r\n");
- const wxWX2MBbuf tmp_buf = tmp_str.mb_str();
- if (Write(wxMBSTRINGCAST tmp_buf, strlen(tmp_buf)).Error()) {
- m_lastError = wxPROTO_NETERR;
- return FALSE;
- }
- return GetResult(exp_ret);
+ if (m_streaming)
+ {
+ m_lastError = wxPROTO_STREAMING;
+ return FALSE;
+ }
+
+ tmp_str = command + wxT("\r\n");
+ const wxWX2MBbuf tmp_buf = tmp_str.mb_str();
+ if ( Write(wxMBSTRINGCAST tmp_buf, strlen(tmp_buf)).Error())
+ {
+ m_lastError = wxPROTO_NETERR;
+ return FALSE;
+ }
+
+ wxLogTrace(_T("ftp"), _T("==> %s"), command.c_str());
+
+ return GetResult(exp_ret);
}
+// ----------------------------------------------------------------------------
+// Recieve servers reply
+// ----------------------------------------------------------------------------
+
bool wxFTP::GetResult(char exp)
{
- m_lastError = GetLine(this, m_lastResult);
- if ( m_lastError )
- return FALSE;
- if (m_lastResult.GetChar(0) != exp) {
- m_lastError = wxPROTO_PROTERR;
- return FALSE;
- }
+ wxString code;
+
+ // we handle multiline replies here according to RFC 959: it says that a
+ // reply may either be on 1 line of the form "xyz ..." or on several lines
+ // in whuch case it looks like
+ // xyz-...
+ // ...
+ // xyz ...
+ // and the intermeidate lines may start with xyz or not
+ bool badReply = FALSE;
+ bool firstLine = TRUE;
+ bool endOfReply = FALSE;
+ while ( !endOfReply && !badReply )
+ {
+ m_lastError = ReadLine(m_lastResult);
+ if ( m_lastError )
+ return FALSE;
+
+ // unless this is an intermediate line of a multiline reply, it must
+ // contain the code in the beginning and '-' or ' ' following it
+ if ( m_lastResult.Len() < LEN_CODE + 1 )
+ {
+ if ( firstLine )
+ {
+ badReply = TRUE;
+ }
+ else
+ {
+ wxLogTrace(_T("ftp"), _T("<== %s %s"),
+ code.c_str(), m_lastResult.c_str());
+ }
+ }
+ else // line has at least 4 chars
+ {
+ // this is the char which tells us what we're dealing with
+ wxChar chMarker = m_lastResult.GetChar(LEN_CODE);
+
+ if ( firstLine )
+ {
+ code = wxString(m_lastResult, LEN_CODE);
+ wxLogTrace(_T("ftp"), _T("<== %s %s"),
+ code.c_str(), m_lastResult.c_str() + LEN_CODE + 1);
+
+ switch ( chMarker )
+ {
+ case _T(' '):
+ endOfReply = TRUE;
+ break;
+
+ case _T('-'):
+ firstLine = FALSE;
+ break;
+
+ default:
+ // unexpected
+ badReply = TRUE;
+ }
+ }
+ else // subsequent line of multiline reply
+ {
+ if ( wxStrncmp(m_lastResult, code, LEN_CODE) == 0 )
+ {
+ if ( chMarker == _T(' ') )
+ {
+ endOfReply = TRUE;
+ }
+
+ wxLogTrace(_T("ftp"), _T("<== %s %s"),
+ code.c_str(), m_lastResult.c_str() + LEN_CODE + 1);
+ }
+ else
+ {
+ // just part of reply
+ wxLogTrace(_T("ftp"), _T("<== %s %s"),
+ code.c_str(), m_lastResult.c_str());
+ }
+ }
+ }
+ }
- if (m_lastResult.GetChar(3) == '-') {
- wxString key = m_lastResult.Left((size_t)3);
+ if ( badReply )
+ {
+ wxLogDebug(_T("Broken FTP server: '%s' is not a valid reply."),
+ m_lastResult.c_str());
- key += wxT(' ');
+ m_lastError = wxPROTO_PROTERR;
- while (m_lastResult.Index(key) != 0) {
- m_lastError = GetLine(this, m_lastResult);
- if ( m_lastError )
return FALSE;
}
- }
- return TRUE;
+
+ if ( code.GetChar(0) != exp )
+ {
+ m_lastError = wxPROTO_PROTERR;
+
+ return FALSE;
+ }
+
+ return TRUE;
}
////////////////////////////////////////////////////////////////
wxString wxFTP::Pwd()
{
- int beg, end;
-
- if (!SendCommand(wxT("PWD"), '2'))
- return wxString((char *)NULL);
-
- beg = m_lastResult.Find(wxT('\"'),FALSE);
- end = m_lastResult.Find(wxT('\"'),TRUE);
+ wxString path;
+
+ if ( SendCommand(wxT("PWD"), '2') )
+ {
+ // the result is at least that long if SendCommand() succeeded
+ const wxChar *p = m_lastResult.c_str() + LEN_CODE + 1;
+ if ( *p != _T('"') )
+ {
+ wxLogDebug(_T("Missing starting quote in reply for PWD: %s"), p);
+ }
+ else
+ {
+ for ( p++; *p; p++ )
+ {
+ if ( *p == _T('"') )
+ {
+ // check if the quote is doubled
+ p++;
+ if ( !*p || *p != _T('"') )
+ {
+ // no, this is the end
+ break;
+ }
+ //else: yes, it is: this is an embedded quote in the
+ // filename, treat as normal char
+ }
+
+ path += *p;
+ }
+
+ if ( !*p )
+ {
+ wxLogDebug(_T("Missing ending quote in reply for PWD: %s"),
+ m_lastResult.c_str() + LEN_CODE + 1);
+ }
+ }
+ }
- return wxString(beg+1, end);
+ return path;
}
bool wxFTP::Rename(const wxString& src, const wxString& dst)
return client;
}
-bool wxFTP::Abort(void)
+bool wxFTP::Abort()
{
- m_streaming = FALSE;
- if (!SendCommand(wxT("ABOR"), '4'))
- return FALSE;
- return GetResult('2');
+ if ( !m_streaming )
+ return TRUE;
+
+ m_streaming = FALSE;
+ if ( !SendCommand(wxT("ABOR"), '4') )
+ return FALSE;
+
+ return GetResult('2');
}
wxInputStream *wxFTP::GetInputStream(const wxString& path)
return new wxOutputFTPStream(this, sock);
}
+bool wxFTP::GetList(wxArrayString& files, const wxString& wildcard)
+{
+ wxSocketBase *sock = GetPort();
+ if ( !sock )
+ {
+ return FALSE;
+ }
+
+ wxString line = _T("NLST");
+ if ( !!wildcard )
+ {
+ // notice that there is no space here
+ line += wildcard;
+ }
+
+ if ( !SendCommand(line, '1') )
+ {
+ return FALSE;
+ }
+
+ files.Empty();
+
+ while ( ReadLine(sock, line) == wxPROTO_NOERR )
+ {
+ files.Add(line);
+ }
+
+ delete sock;
+
+ // the file list should be terminated by "226 Transfer complete""
+ if ( !GetResult('2') )
+ return FALSE;
+
+ return TRUE;
+}
+
wxList *wxFTP::GetList(const wxString& wildcard)
{
wxList *file_list = new wxList;
return TRUE;
}
+// ----------------------------------------------------------------------------
+// Read a line from socket
+// ----------------------------------------------------------------------------
+
+// TODO ReadLine() should use buffers private to wxProtocol for efficiency!
+
+// static
+wxProtocolError wxProtocol::ReadLine(wxSocketBase *socket, wxString& result)
+{
+ result.Empty();
+ char ch, chLast = '\0';
+ while ( !socket->Read(&ch, sizeof(ch)).Error() )
+ {
+ switch ( ch )
+ {
+ case '\r':
+ // remember it, if the following is '\n', we're done
+ chLast = '\r';
+ break;
+
+ case '\n':
+ // only ends line if the previous character was '\r'
+ if ( chLast == '\r' )
+ {
+ // EOL found
+ return wxPROTO_NOERR;
+ }
+ //else: fall through
+
+ default:
+ // normal char
+ if ( chLast )
+ {
+ result += chLast;
+ chLast = '\0';
+ }
+
+ result += ch;
+ }
+ }
+
+ return wxPROTO_NETERR;
+}
+
+wxProtocolError wxProtocol::ReadLine(wxString& result)
+{
+ return ReadLine(this, result);
+}
+
+// old function which only chops '\n' and not '\r\n'
wxProtocolError GetLine(wxSocketBase *sock, wxString& result) {
#define PROTO_BSIZE 2048
size_t avail, size;
-# This file was automatically generated by tmake at 15:55, 2000/03/14
+# This file was automatically generated by tmake at 09:19, 2000/03/15
# DO NOT CHANGE THIS FILE, YOUR CHANGES WILL BE LOST! CHANGE BASE.T!
ALL_SOURCES = \
common/init.cpp \
common/fs_inet.cpp \
common/fs_mem.cpp \
common/fs_zip.cpp \
+ common/ftp.cpp \
common/hash.cpp \
+ common/http.cpp \
common/intl.cpp \
common/list.cpp \
common/log.cpp \
common/object.cpp \
common/objstrm.cpp \
common/process.cpp \
+ common/protocol.cpp \
+ common/sckaddr.cpp \
+ common/sckfile.cpp \
+ common/sckipc.cpp \
+ common/sckstrm.cpp \
common/serbase.cpp \
+ common/socket.cpp \
common/strconv.cpp \
common/stream.cpp \
common/string.cpp \
common/tokenzr.cpp \
common/txtstrm.cpp \
common/unzip.c \
+ common/url.cpp \
common/utilscmn.cpp \
common/variant.cpp \
common/wfstream.cpp \
protocol/protocol.h
BASE_OBJS = \
+ ipcbase.o \
+ gsocket.o \
init.o \
appcmn.o \
cmdline.o \
fs_inet.o \
fs_mem.o \
fs_zip.o \
+ ftp.o \
hash.o \
+ http.o \
intl.o \
list.o \
log.o \
object.o \
objstrm.o \
process.o \
+ protocol.o \
+ sckaddr.o \
+ sckfile.o \
+ sckipc.o \
+ sckstrm.o \
serbase.o \
+ socket.o \
strconv.o \
stream.o \
string.o \
tokenzr.o \
txtstrm.o \
unzip.o \
+ url.o \
utilscmn.o \
variant.o \
wfstream.o \
fs_inet.d \
fs_mem.d \
fs_zip.d \
+ ftp.d \
hash.d \
+ http.d \
intl.d \
list.d \
log.d \
object.d \
objstrm.d \
process.d \
+ protocol.d \
+ sckaddr.d \
+ sckfile.d \
+ sckipc.d \
+ sckstrm.d \
serbase.d \
+ socket.d \
strconv.d \
stream.d \
string.d \
tokenzr.d \
txtstrm.d \
unzip.d \
+ url.d \
utilscmn.d \
variant.d \
wfstream.d \
fs_inet.d \
fs_mem.d \
fs_zip.d \
+ ftp.d \
hash.d \
+ http.d \
intl.d \
list.d \
log.d \
object.d \
objstrm.d \
process.d \
+ protocol.d \
+ sckaddr.d \
+ sckfile.d \
+ sckipc.d \
+ sckstrm.d \
serbase.d \
+ socket.d \
strconv.d \
stream.d \
string.d \
tokenzr.d \
txtstrm.d \
unzip.d \
+ url.d \
utilscmn.d \
variant.d \
wfstream.d \
#ifndef __GSOCKET_STANDALONE__
-
-#include "wx/unix/gsockunx.h"
-#include "wx/gsocket.h"
-
+# include "wx/unix/gsockunx.h"
+# include "wx/gsocket.h"
#else
-
-#include "gsockunx.h"
-#include "gsocket.h"
-
+# include "gsockunx.h"
+# include "gsocket.h"
#endif /* __GSOCKET_STANDALONE__ */
/* redefine some GUI-only functions to do nothing in console mode */
#if defined(wxUSE_GUI) && !wxUSE_GUI
- #define _GSocket_GUI_Init(socket)
- #define _GSocket_GUI_Destroy(socket)
- #define _GSocket_Enable_Events(socket)
- #define _GSocket_Disable_Events(socket)
- #define _GSocket_Install_Callback(socket, event)
- #define _GSocket_Uninstall_Callback(socket, event)
+# define _GSocket_GUI_Init(socket) (1)
+# define _GSocket_GUI_Destroy(socket)
+# define _GSocket_Enable_Events(socket)
+# define _GSocket_Disable_Events(socket)
+# define _GSocket_Install_Callback(socket, event)
+# define _GSocket_Uninstall_Callback(socket, event)
#endif /* wxUSE_GUI */
+/* debugging helpers */
+#ifdef __GSOCKET_DEBUG__
+ #define GSocket_Debug(args) printf args
+#else
+ #define GSocket_Debug(args)
+#endif // __GSOCKET_DEBUG__
+
/* Global initialisers */
bool GSocket_Init(void)
GSocket *GSocket_new(void)
{
- int i;
+ int i, success;
GSocket *socket;
socket = (GSocket *)malloc(sizeof(GSocket));
socket->m_establishing = FALSE;
/* Per-socket GUI-specific initialization */
- if (!_GSocket_GUI_Init(socket))
+ success = _GSocket_GUI_Init(socket);
+ if (!success)
{
free(socket);
return NULL;
assert(socket != NULL);
- printf( "GSocket_Write #1, size %d\n", size );
+ GSocket_Debug(( "GSocket_Write #1, size %d\n", size ));
if (socket->m_fd == -1 || socket->m_server)
{
return -1;
}
- printf( "GSocket_Write #2, size %d\n", size );
+ GSocket_Debug(( "GSocket_Write #2, size %d\n", size ));
/* If the socket is blocking, wait for writability (with a timeout) */
if (_GSocket_Output_Timeout(socket) == GSOCK_TIMEDOUT)
return -1;
- printf( "GSocket_Write #3, size %d\n", size );
+ GSocket_Debug(( "GSocket_Write #3, size %d\n", size ));
/* Write the data */
if (socket->m_stream)
else
ret = _GSocket_Send_Dgram(socket, buffer, size);
- printf( "GSocket_Write #4, size %d\n", size );
+ GSocket_Debug(( "GSocket_Write #4, size %d\n", size ));
if (ret == -1)
{
if (errno == EWOULDBLOCK)
{
socket->m_error = GSOCK_WOULDBLOCK;
- printf( "GSocket_Write error WOULDBLOCK\n" );
+ GSocket_Debug(( "GSocket_Write error WOULDBLOCK\n" ));
}
else
{
socket->m_error = GSOCK_IOERR;
- printf( "GSocket_Write error IOERR\n" );
+ GSocket_Debug(( "GSocket_Write error IOERR\n" ));
}
/* Only reenable OUTPUT events after an error (just like WSAAsyncSelect
return -1;
}
- printf( "GSocket_Write #5, size %d ret %d\n", size, ret );
+ GSocket_Debug(( "GSocket_Write #5, size %d ret %d\n", size, ret ));
return ret;
}
*/
GSocketEventFlags GSocket_Select(GSocket *socket, GSocketEventFlags flags)
{
+#if defined(wxUSE_GUI) && !wxUSE_GUI
+
+ GSocketEventFlags result = 0;
+ fd_set readfds;
+ fd_set writefds;
+ fd_set exceptfds;
+ struct timeval tv;
+
+ /* Do not use a static struct, Linux can garble it */
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+
assert(socket != NULL);
+ FD_ZERO(&readfds);
+ FD_ZERO(&writefds);
+ FD_ZERO(&exceptfds);
+ FD_SET(socket->m_fd, &readfds);
+ FD_SET(socket->m_fd, &writefds);
+ FD_SET(socket->m_fd, &exceptfds);
+
+ /* Check known state first */
+ result |= (GSOCK_CONNECTION_FLAG & socket->m_detected & flags);
+ result |= (GSOCK_LOST_FLAG & socket->m_detected & flags);
+
+ /* Try select now */
+ if (select(socket->m_fd + 1, &readfds, &writefds, &exceptfds, &tv) <= 0)
+ return result;
+
+ /* Check for readability */
+ if (FD_ISSET(socket->m_fd, &readfds))
+ {
+ char c;
+
+ if (recv(socket->m_fd, &c, 1, MSG_PEEK) > 0)
+ {
+ result |= (GSOCK_INPUT_FLAG & flags);
+ }
+ else
+ {
+ if (socket->m_server && socket->m_stream)
+ {
+ result |= (GSOCK_CONNECTION_FLAG & flags);
+ socket->m_detected |= GSOCK_CONNECTION_FLAG;
+ }
+ else
+ {
+ result |= (GSOCK_LOST_FLAG & flags);
+ socket->m_detected = GSOCK_LOST_FLAG;
+ }
+ }
+ }
+
+ /* Check for writability */
+ if (FD_ISSET(socket->m_fd, &writefds))
+ {
+ if (socket->m_establishing && !socket->m_server)
+ {
+ int error;
+ SOCKLEN_T len = sizeof(error);
+
+ socket->m_establishing = FALSE;
+
+ getsockopt(socket->m_fd, SOL_SOCKET, SO_ERROR, (void*)&error, &len);
+
+ if (error)
+ {
+ result |= (GSOCK_LOST_FLAG & flags);
+ socket->m_detected = GSOCK_LOST_FLAG;
+ }
+ else
+ {
+ result |= (GSOCK_CONNECTION_FLAG & flags);
+ socket->m_detected |= GSOCK_CONNECTION_FLAG;
+ }
+ }
+ else
+ {
+ result |= (GSOCK_OUTPUT_FLAG & flags);
+ }
+ }
+
+ /* Check for exceptions and errors (is this useful in Unices?) */
+ if (FD_ISSET(socket->m_fd, &exceptfds))
+ {
+ result |= (GSOCK_LOST_FLAG & flags);
+ socket->m_establishing = FALSE;
+ socket->m_detected = GSOCK_LOST_FLAG;
+ }
+
+ return result;
+
+#else
+
+ assert(socket != NULL);
return flags & socket->m_detected;
+
+#endif /* !wxUSE_GUI */
}
/* Flags */
ret = select(socket->m_fd + 1, &readfds, NULL, NULL, &tv);
if (ret == 0)
{
- printf( "GSocket_Input_Timeout, select returned 0\n" );
+ GSocket_Debug(( "GSocket_Input_Timeout, select returned 0\n" ));
socket->m_error = GSOCK_TIMEDOUT;
return GSOCK_TIMEDOUT;
}
if (ret == -1)
{
- printf( "GSocket_Input_Timeout, select returned -1\n" );
- if (errno == EBADF) printf( "Invalid file descriptor\n" );
- if (errno == EINTR) printf( "A non blocked signal was caught\n" );
- if (errno == EINVAL) printf( "The highest number descriptor is negative\n" );
- if (errno == ENOMEM) printf( "Not enough memory\n" );
+ GSocket_Debug(( "GSocket_Input_Timeout, select returned -1\n" ));
+ if (errno == EBADF) GSocket_Debug(( "Invalid file descriptor\n" ));
+ if (errno == EINTR) GSocket_Debug(( "A non blocked signal was caught\n" ));
+ if (errno == EINVAL) GSocket_Debug(( "The highest number descriptor is negative\n" ));
+ if (errno == ENOMEM) GSocket_Debug(( "Not enough memory\n" ));
socket->m_error = GSOCK_TIMEDOUT;
return GSOCK_TIMEDOUT;
}
ret = select(socket->m_fd + 1, NULL, &writefds, NULL, &tv);
if (ret == 0)
{
- printf( "GSocket_Output_Timeout, select returned 0\n" );
+ GSocket_Debug(( "GSocket_Output_Timeout, select returned 0\n" ));
socket->m_error = GSOCK_TIMEDOUT;
return GSOCK_TIMEDOUT;
}
if (ret == -1)
{
- printf( "GSocket_Output_Timeout, select returned -1\n" );
- if (errno == EBADF) printf( "Invalid file descriptor\n" );
- if (errno == EINTR) printf( "A non blocked signal was caught\n" );
- if (errno == EINVAL) printf( "The highest number descriptor is negative\n" );
- if (errno == ENOMEM) printf( "Not enough memory\n" );
+ GSocket_Debug(( "GSocket_Output_Timeout, select returned -1\n" ));
+ if (errno == EBADF) GSocket_Debug(( "Invalid file descriptor\n" ));
+ if (errno == EINTR) GSocket_Debug(( "A non blocked signal was caught\n" ));
+ if (errno == EINVAL) GSocket_Debug(( "The highest number descriptor is negative\n" ));
+ if (errno == ENOMEM) GSocket_Debug(( "Not enough memory\n" ));
socket->m_error = GSOCK_TIMEDOUT;
return GSOCK_TIMEDOUT;
}
void _GSocket_Detected_Read(GSocket *socket)
{
char c;
- int ret;
-
- ret = recv(socket->m_fd, &c, 1, MSG_PEEK);
- if (socket->m_stream)
- {
- if (ret < 0 && socket->m_server)
- {
- CALL_CALLBACK(socket, GSOCK_CONNECTION);
- return;
- }
- }
-
- if (ret > 0)
+ if (recv(socket->m_fd, &c, 1, MSG_PEEK) > 0)
{
CALL_CALLBACK(socket, GSOCK_INPUT);
}
else
{
- CALL_CALLBACK(socket, GSOCK_LOST);
+ if (socket->m_server && socket->m_stream)
+ {
+ CALL_CALLBACK(socket, GSOCK_CONNECTION);
+ }
+ else
+ {
+ CALL_CALLBACK(socket, GSOCK_LOST);
+ }
}
}
socket->m_establishing = FALSE;
- getsockopt(socket->m_fd, SOL_SOCKET, SO_ERROR, (void*) &error, &len);
+ getsockopt(socket->m_fd, SOL_SOCKET, SO_ERROR, (void*)&error, &len);
if (error)
{