+
+ // disconnect socket
+ m_commandSocket->DisconnectFromHost();
+ m_dataSocket->DisconnectFromHost();
+
+ // reset state - necessary??
+ m_isUrlParsed = false;
+ m_filePosition = -1;
+ m_username = DEFAULT_USER;
+ m_password = DEFAULT_PASS;
+ m_dataHostname.clear();
+ m_dataPort = 0;
+}
+
+bool BamFtp::ConnectCommandSocket(void) {
+
+ BT_ASSERT_X(m_commandSocket, "null command socket?");
+
+ // connect to FTP server
+ if ( !m_commandSocket->ConnectToHost(m_hostname, m_port, m_mode) ) {
+ SetErrorString("BamFtp::ConnectCommandSocket", "could not connect to host - ");
+ return false;
+ }
+
+ // receive initial reply from host
+ if ( !ReceiveReply() ) {
+ Close();
+ return false;
+ }
+
+ // send USER command
+ string userCommand = USER_CMD + CMD_SEPARATOR + m_username + FTP_NEWLINE;
+ if ( !SendCommand(userCommand, true) ) {
+ Close();
+ return false;
+ }
+
+ // send PASS command
+ string passwordCommand = PASS_CMD + CMD_SEPARATOR + m_password + FTP_NEWLINE;
+ if ( !SendCommand(passwordCommand, true) ) {
+ Close();
+ return false;
+ }
+
+ // send TYPE command
+ string typeCommand = TYPE_CMD + CMD_SEPARATOR + 'I' + FTP_NEWLINE;
+ if ( !SendCommand(typeCommand, true) ) {
+ Close();
+ return false;
+ }
+
+ // return success
+ return true;
+}
+
+bool BamFtp::ConnectDataSocket(void) {
+
+ // failure if can't connect to command socket first
+ if ( !m_commandSocket->IsConnected() ) {
+ if ( !ConnectCommandSocket() )
+ return false;
+ }
+
+ // make sure we're starting with a fresh data channel
+ if ( m_dataSocket->IsConnected() )
+ m_dataSocket->DisconnectFromHost();
+
+ // send passive connection command
+ const string passiveCommand = PASV_CMD + FTP_NEWLINE;
+ if ( !SendCommand(passiveCommand, true) ) {
+ // TODO: set error string
+ return false;
+ }
+
+ // retrieve passive connection port
+ if ( !ParsePassiveResponse() ) {
+ // TODO: set error string
+ return false;
+ }
+
+ // set up restart command (tell server where to start fetching bytes from)
+ if ( m_filePosition >= 0 ) {
+
+ stringstream fpStream("");
+ fpStream << m_filePosition;
+ string restartCommand = REST_CMD + CMD_SEPARATOR + fpStream.str() + FTP_NEWLINE;
+ if ( !SendCommand(restartCommand, true) ) {
+ // TODO: set error string
+ return false;
+ }
+ }
+
+ // main file retrieval request
+ string retrieveCommand = RETR_CMD + CMD_SEPARATOR + m_filename + FTP_NEWLINE;
+ if ( !SendCommand(retrieveCommand, false) ) {
+ // TODO: set error string
+ return false;
+ }
+
+ // make data channel connection
+ if ( !m_dataSocket->ConnectToHost(m_dataHostname, m_dataPort) ) {
+ // TODO: set error string
+ return false;
+ }
+
+ // fetch intial reply from server
+ if ( !ReceiveReply() ) {
+ // TODO: set error string
+ m_dataSocket->DisconnectFromHost();
+ return false;
+ }
+
+ // make sure we have reply code 150 (all good)
+ if ( !startsWith(m_response, "150") ) {
+ // TODO: set error string
+ m_dataSocket->DisconnectFromHost();
+ return false;
+ }
+
+ // return success
+ return true;
+}
+
+bool BamFtp::IsOpen(void) const {
+ return IBamIODevice::IsOpen() && m_isUrlParsed;