Robert Ellis / FTPServer
Committer:
Phlaphead
Date:
Sun Jun 19 13:59:16 2011 +0000
Revision:
0:61dbbee3f903
Initial revision.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Phlaphead 0:61dbbee3f903 1
Phlaphead 0:61dbbee3f903 2 /*
Phlaphead 0:61dbbee3f903 3 Copyright (c) 2011 Robert Ellis (holistic [at] robellis [dot] org [dot] uk)
Phlaphead 0:61dbbee3f903 4
Phlaphead 0:61dbbee3f903 5 Permission is hereby granted, free of charge, to any person obtaining a copy
Phlaphead 0:61dbbee3f903 6 of this software and associated documentation files (the "Software"), to deal
Phlaphead 0:61dbbee3f903 7 in the Software without restriction, including without limitation the rights
Phlaphead 0:61dbbee3f903 8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
Phlaphead 0:61dbbee3f903 9 copies of the Software, and to permit persons to whom the Software is
Phlaphead 0:61dbbee3f903 10 furnished to do so, subject to the following conditions:
Phlaphead 0:61dbbee3f903 11
Phlaphead 0:61dbbee3f903 12 The above copyright notice and this permission notice shall be included in
Phlaphead 0:61dbbee3f903 13 all copies or substantial portions of the Software.
Phlaphead 0:61dbbee3f903 14
Phlaphead 0:61dbbee3f903 15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Phlaphead 0:61dbbee3f903 16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Phlaphead 0:61dbbee3f903 17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Phlaphead 0:61dbbee3f903 18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Phlaphead 0:61dbbee3f903 19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
Phlaphead 0:61dbbee3f903 20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
Phlaphead 0:61dbbee3f903 21 THE SOFTWARE.
Phlaphead 0:61dbbee3f903 22 */
Phlaphead 0:61dbbee3f903 23
Phlaphead 0:61dbbee3f903 24 #include "core/netservice.h"
Phlaphead 0:61dbbee3f903 25 #include "FTPRequestHandler.h"
Phlaphead 0:61dbbee3f903 26 #include "stringUtils.h"
Phlaphead 0:61dbbee3f903 27 #include <string.h>
Phlaphead 0:61dbbee3f903 28 #include <sstream>
Phlaphead 0:61dbbee3f903 29
Phlaphead 0:61dbbee3f903 30 //#define __DEBUG
Phlaphead 0:61dbbee3f903 31 #include "dbg/dbg.h"
Phlaphead 0:61dbbee3f903 32
Phlaphead 0:61dbbee3f903 33 FTPRequestHandler::FTPRequestHandler(FTPServer* pSvr, Host* pCommandClient, TCPSocket* pCommandSocket) :
Phlaphead 0:61dbbee3f903 34 NetService(), m_pSvr(pSvr), m_pCommandClient(pCommandClient), m_closed(false), m_authenticated(false),
Phlaphead 0:61dbbee3f903 35 fileSystem()
Phlaphead 0:61dbbee3f903 36 {
Phlaphead 0:61dbbee3f903 37 m_pDataSocket = NULL;
Phlaphead 0:61dbbee3f903 38 m_pDataClient = NULL;
Phlaphead 0:61dbbee3f903 39 m_command = NOOP;
Phlaphead 0:61dbbee3f903 40 acceptCommandSocket(pCommandSocket);
Phlaphead 0:61dbbee3f903 41 }
Phlaphead 0:61dbbee3f903 42
Phlaphead 0:61dbbee3f903 43 FTPRequestHandler::~FTPRequestHandler()
Phlaphead 0:61dbbee3f903 44 {
Phlaphead 0:61dbbee3f903 45 close();
Phlaphead 0:61dbbee3f903 46 }
Phlaphead 0:61dbbee3f903 47
Phlaphead 0:61dbbee3f903 48
Phlaphead 0:61dbbee3f903 49 void FTPRequestHandler::acceptCommandSocket(TCPSocket* pCommandSocket)
Phlaphead 0:61dbbee3f903 50 {
Phlaphead 0:61dbbee3f903 51 m_pCommandSocket = pCommandSocket;
Phlaphead 0:61dbbee3f903 52 m_pCommandSocket->setOnEvent(this, &FTPRequestHandler::onCommandSocketEvent);
Phlaphead 0:61dbbee3f903 53 onCommandSocketEvent(TCPSOCKET_ACCEPT);
Phlaphead 0:61dbbee3f903 54 }
Phlaphead 0:61dbbee3f903 55
Phlaphead 0:61dbbee3f903 56 void FTPRequestHandler::acceptDataSocket(TCPSocket* pDataSocket)
Phlaphead 0:61dbbee3f903 57 {
Phlaphead 0:61dbbee3f903 58 m_pDataSocket = pDataSocket;
Phlaphead 0:61dbbee3f903 59 m_pDataSocket->setOnEvent(this, &FTPRequestHandler::onDataSocketEvent);
Phlaphead 0:61dbbee3f903 60 onDataSocketEvent(TCPSOCKET_ACCEPT);
Phlaphead 0:61dbbee3f903 61 }
Phlaphead 0:61dbbee3f903 62
Phlaphead 0:61dbbee3f903 63 bool FTPRequestHandler::openDataSocket()
Phlaphead 0:61dbbee3f903 64 {
Phlaphead 0:61dbbee3f903 65 if(m_pDataSocket != NULL)
Phlaphead 0:61dbbee3f903 66 {
Phlaphead 0:61dbbee3f903 67 sendReply(125, "Data connection already open; transfer starting.");
Phlaphead 0:61dbbee3f903 68 return true;
Phlaphead 0:61dbbee3f903 69 }
Phlaphead 0:61dbbee3f903 70
Phlaphead 0:61dbbee3f903 71 m_pDataSocket = new TCPSocket;
Phlaphead 0:61dbbee3f903 72 Host h(IpAddr(127,0,0,1), 20, "localhost");
Phlaphead 0:61dbbee3f903 73 m_pDataSocket->bind(h);
Phlaphead 0:61dbbee3f903 74 sendReply(150, "About to open data connection.");
Phlaphead 0:61dbbee3f903 75 TCPSocketErr bindErr = m_pDataSocket->connect(*m_pDataClient);
Phlaphead 0:61dbbee3f903 76 if(bindErr == TCPSOCKET_OK)
Phlaphead 0:61dbbee3f903 77 {
Phlaphead 0:61dbbee3f903 78 m_pDataSocket->setOnEvent(this, &FTPRequestHandler::onDataSocketEvent);
Phlaphead 0:61dbbee3f903 79 return true;
Phlaphead 0:61dbbee3f903 80 }
Phlaphead 0:61dbbee3f903 81 else
Phlaphead 0:61dbbee3f903 82 {
Phlaphead 0:61dbbee3f903 83 closeDataSocket();
Phlaphead 0:61dbbee3f903 84 sendReply(425, "Can't open data connection.");
Phlaphead 0:61dbbee3f903 85 DBG("Error binding data socket: %d\r\n", bindErr);
Phlaphead 0:61dbbee3f903 86 return false;
Phlaphead 0:61dbbee3f903 87 }
Phlaphead 0:61dbbee3f903 88 }
Phlaphead 0:61dbbee3f903 89
Phlaphead 0:61dbbee3f903 90
Phlaphead 0:61dbbee3f903 91 void FTPRequestHandler::onCommandSocketEvent(TCPSocketEvent e)
Phlaphead 0:61dbbee3f903 92 {
Phlaphead 0:61dbbee3f903 93 DBG("Command Event %d\r\n", e);
Phlaphead 0:61dbbee3f903 94
Phlaphead 0:61dbbee3f903 95 if(m_closed)
Phlaphead 0:61dbbee3f903 96 {
Phlaphead 0:61dbbee3f903 97 DBG("\r\nWARN: Discarded\r\n");
Phlaphead 0:61dbbee3f903 98 return;
Phlaphead 0:61dbbee3f903 99 }
Phlaphead 0:61dbbee3f903 100
Phlaphead 0:61dbbee3f903 101 switch(e)
Phlaphead 0:61dbbee3f903 102 {
Phlaphead 0:61dbbee3f903 103 case TCPSOCKET_ACCEPT:
Phlaphead 0:61dbbee3f903 104 sendReply(220, m_pSvr->getWelcomeMessage().c_str());
Phlaphead 0:61dbbee3f903 105 break;
Phlaphead 0:61dbbee3f903 106
Phlaphead 0:61dbbee3f903 107 case TCPSOCKET_READABLE:
Phlaphead 0:61dbbee3f903 108 DBG("Event TCPSOCKET_READABLE\r\n");
Phlaphead 0:61dbbee3f903 109 handleRequest();
Phlaphead 0:61dbbee3f903 110 break;
Phlaphead 0:61dbbee3f903 111
Phlaphead 0:61dbbee3f903 112 case TCPSOCKET_WRITEABLE:
Phlaphead 0:61dbbee3f903 113 DBG("Event TCPSOCKET_WRITEABLE\r\n");
Phlaphead 0:61dbbee3f903 114 break;
Phlaphead 0:61dbbee3f903 115
Phlaphead 0:61dbbee3f903 116 case TCPSOCKET_CONTIMEOUT:
Phlaphead 0:61dbbee3f903 117 case TCPSOCKET_CONRST:
Phlaphead 0:61dbbee3f903 118 case TCPSOCKET_CONABRT:
Phlaphead 0:61dbbee3f903 119 case TCPSOCKET_ERROR:
Phlaphead 0:61dbbee3f903 120 case TCPSOCKET_DISCONNECTED:
Phlaphead 0:61dbbee3f903 121 close();
Phlaphead 0:61dbbee3f903 122 break;
Phlaphead 0:61dbbee3f903 123 }
Phlaphead 0:61dbbee3f903 124 }
Phlaphead 0:61dbbee3f903 125
Phlaphead 0:61dbbee3f903 126 void FTPRequestHandler::onDataSocketEvent(TCPSocketEvent e)
Phlaphead 0:61dbbee3f903 127 {
Phlaphead 0:61dbbee3f903 128 DBG("Data Event %d\r\n", e);
Phlaphead 0:61dbbee3f903 129
Phlaphead 0:61dbbee3f903 130 if(m_closed)
Phlaphead 0:61dbbee3f903 131 {
Phlaphead 0:61dbbee3f903 132 DBG("\r\nWARN: Discarded\r\n");
Phlaphead 0:61dbbee3f903 133 return;
Phlaphead 0:61dbbee3f903 134 }
Phlaphead 0:61dbbee3f903 135
Phlaphead 0:61dbbee3f903 136 switch(e)
Phlaphead 0:61dbbee3f903 137 {
Phlaphead 0:61dbbee3f903 138 case TCPSOCKET_ACCEPT:
Phlaphead 0:61dbbee3f903 139 sendReply(150, "Accepted data connection.");
Phlaphead 0:61dbbee3f903 140 handleResponse();
Phlaphead 0:61dbbee3f903 141 break;
Phlaphead 0:61dbbee3f903 142
Phlaphead 0:61dbbee3f903 143 case TCPSOCKET_READABLE:
Phlaphead 0:61dbbee3f903 144 DBG("Event TCPSOCKET_READABLE\r\n");
Phlaphead 0:61dbbee3f903 145 break;
Phlaphead 0:61dbbee3f903 146
Phlaphead 0:61dbbee3f903 147 case TCPSOCKET_WRITEABLE:
Phlaphead 0:61dbbee3f903 148 DBG("Event TCPSOCKET_WRITEABLE\r\n");
Phlaphead 0:61dbbee3f903 149 handleResponse();
Phlaphead 0:61dbbee3f903 150 break;
Phlaphead 0:61dbbee3f903 151
Phlaphead 0:61dbbee3f903 152 case TCPSOCKET_CONTIMEOUT:
Phlaphead 0:61dbbee3f903 153 case TCPSOCKET_CONRST:
Phlaphead 0:61dbbee3f903 154 case TCPSOCKET_CONABRT:
Phlaphead 0:61dbbee3f903 155 case TCPSOCKET_ERROR:
Phlaphead 0:61dbbee3f903 156 case TCPSOCKET_DISCONNECTED:
Phlaphead 0:61dbbee3f903 157 closeDataSocket();
Phlaphead 0:61dbbee3f903 158 break;
Phlaphead 0:61dbbee3f903 159 }
Phlaphead 0:61dbbee3f903 160 }
Phlaphead 0:61dbbee3f903 161
Phlaphead 0:61dbbee3f903 162
Phlaphead 0:61dbbee3f903 163 void FTPRequestHandler::close() //Close socket and destroy data
Phlaphead 0:61dbbee3f903 164 {
Phlaphead 0:61dbbee3f903 165 if(m_closed)
Phlaphead 0:61dbbee3f903 166 {
Phlaphead 0:61dbbee3f903 167 return;
Phlaphead 0:61dbbee3f903 168 }
Phlaphead 0:61dbbee3f903 169
Phlaphead 0:61dbbee3f903 170 closeDataSocket();
Phlaphead 0:61dbbee3f903 171
Phlaphead 0:61dbbee3f903 172 m_closed = true; //Prevent recursive calling or calling on an object being destructed by someone else
Phlaphead 0:61dbbee3f903 173
Phlaphead 0:61dbbee3f903 174 if(m_pCommandSocket) //m_pTCPSocket Should only be destroyed if ownership not passed to an handler
Phlaphead 0:61dbbee3f903 175 {
Phlaphead 0:61dbbee3f903 176 m_pCommandSocket->resetOnEvent();
Phlaphead 0:61dbbee3f903 177 m_pCommandSocket->close();
Phlaphead 0:61dbbee3f903 178 delete m_pCommandSocket; //This fn might have been called by this socket (through an event), so DO NOT DESTROY IT HERE
Phlaphead 0:61dbbee3f903 179 }
Phlaphead 0:61dbbee3f903 180
Phlaphead 0:61dbbee3f903 181 if(m_pCommandClient)
Phlaphead 0:61dbbee3f903 182 {
Phlaphead 0:61dbbee3f903 183 delete m_pCommandClient;
Phlaphead 0:61dbbee3f903 184 }
Phlaphead 0:61dbbee3f903 185
Phlaphead 0:61dbbee3f903 186 if(m_pDataClient)
Phlaphead 0:61dbbee3f903 187 {
Phlaphead 0:61dbbee3f903 188 delete m_pDataClient;
Phlaphead 0:61dbbee3f903 189 }
Phlaphead 0:61dbbee3f903 190
Phlaphead 0:61dbbee3f903 191 NetService::close();
Phlaphead 0:61dbbee3f903 192 }
Phlaphead 0:61dbbee3f903 193
Phlaphead 0:61dbbee3f903 194 void FTPRequestHandler::closeDataSocket()
Phlaphead 0:61dbbee3f903 195 {
Phlaphead 0:61dbbee3f903 196 if(m_closed)
Phlaphead 0:61dbbee3f903 197 {
Phlaphead 0:61dbbee3f903 198 return;
Phlaphead 0:61dbbee3f903 199 }
Phlaphead 0:61dbbee3f903 200
Phlaphead 0:61dbbee3f903 201 if(m_pDataSocket)
Phlaphead 0:61dbbee3f903 202 {
Phlaphead 0:61dbbee3f903 203 sendReply(226, "Closing data connection.");
Phlaphead 0:61dbbee3f903 204 m_pDataSocket->resetOnEvent();
Phlaphead 0:61dbbee3f903 205 m_pDataSocket->close();
Phlaphead 0:61dbbee3f903 206 delete m_pDataSocket;
Phlaphead 0:61dbbee3f903 207 m_pDataSocket = NULL;
Phlaphead 0:61dbbee3f903 208 }
Phlaphead 0:61dbbee3f903 209 }
Phlaphead 0:61dbbee3f903 210
Phlaphead 0:61dbbee3f903 211
Phlaphead 0:61dbbee3f903 212 int FTPRequestHandler::getRequest()
Phlaphead 0:61dbbee3f903 213 {
Phlaphead 0:61dbbee3f903 214 char c[2];
Phlaphead 0:61dbbee3f903 215 request = "";
Phlaphead 0:61dbbee3f903 216
Phlaphead 0:61dbbee3f903 217 while(1)
Phlaphead 0:61dbbee3f903 218 {
Phlaphead 0:61dbbee3f903 219 int ret = m_pCommandSocket->recv(c, 1);
Phlaphead 0:61dbbee3f903 220
Phlaphead 0:61dbbee3f903 221 if(!ret)
Phlaphead 0:61dbbee3f903 222 {
Phlaphead 0:61dbbee3f903 223 break;
Phlaphead 0:61dbbee3f903 224 }
Phlaphead 0:61dbbee3f903 225
Phlaphead 0:61dbbee3f903 226 if(request.length() > 0 && c[0] == '\n')
Phlaphead 0:61dbbee3f903 227 {
Phlaphead 0:61dbbee3f903 228 break;
Phlaphead 0:61dbbee3f903 229 }
Phlaphead 0:61dbbee3f903 230 else
Phlaphead 0:61dbbee3f903 231 {
Phlaphead 0:61dbbee3f903 232 request += c[0];
Phlaphead 0:61dbbee3f903 233 }
Phlaphead 0:61dbbee3f903 234 }
Phlaphead 0:61dbbee3f903 235
Phlaphead 0:61dbbee3f903 236 request = trim(request);
Phlaphead 0:61dbbee3f903 237 return request.length();
Phlaphead 0:61dbbee3f903 238 }
Phlaphead 0:61dbbee3f903 239
Phlaphead 0:61dbbee3f903 240
Phlaphead 0:61dbbee3f903 241 void FTPRequestHandler::sendReply(int replyCode, const char* format, ...)
Phlaphead 0:61dbbee3f903 242 {
Phlaphead 0:61dbbee3f903 243 char buf[256], fmt[256];
Phlaphead 0:61dbbee3f903 244 va_list args;
Phlaphead 0:61dbbee3f903 245 int i;
Phlaphead 0:61dbbee3f903 246
Phlaphead 0:61dbbee3f903 247 snprintf(fmt, 256, "%03u %s\r\n", replyCode, format);
Phlaphead 0:61dbbee3f903 248
Phlaphead 0:61dbbee3f903 249 va_start(args, format);
Phlaphead 0:61dbbee3f903 250 i = vsnprintf(buf, 256, fmt, args);
Phlaphead 0:61dbbee3f903 251 va_end(args);
Phlaphead 0:61dbbee3f903 252
Phlaphead 0:61dbbee3f903 253 buf[i+1] = 0;
Phlaphead 0:61dbbee3f903 254 DBG("Response: %s", buf);
Phlaphead 0:61dbbee3f903 255
Phlaphead 0:61dbbee3f903 256 m_pCommandSocket->send(buf, i);
Phlaphead 0:61dbbee3f903 257 }
Phlaphead 0:61dbbee3f903 258
Phlaphead 0:61dbbee3f903 259 void FTPRequestHandler::sendReply(const char* format, ...)
Phlaphead 0:61dbbee3f903 260 {
Phlaphead 0:61dbbee3f903 261 char buf[256], fmt[256];
Phlaphead 0:61dbbee3f903 262 va_list args;
Phlaphead 0:61dbbee3f903 263 int i;
Phlaphead 0:61dbbee3f903 264
Phlaphead 0:61dbbee3f903 265 snprintf(fmt, 256, "%s\r\n", format);
Phlaphead 0:61dbbee3f903 266
Phlaphead 0:61dbbee3f903 267 va_start(args, format);
Phlaphead 0:61dbbee3f903 268 i = vsnprintf(buf, 256, fmt, args);
Phlaphead 0:61dbbee3f903 269 va_end(args);
Phlaphead 0:61dbbee3f903 270
Phlaphead 0:61dbbee3f903 271 buf[i+1] = 0;
Phlaphead 0:61dbbee3f903 272 DBG("Response: %s", buf);
Phlaphead 0:61dbbee3f903 273
Phlaphead 0:61dbbee3f903 274 m_pCommandSocket->send(buf, i);
Phlaphead 0:61dbbee3f903 275 }
Phlaphead 0:61dbbee3f903 276
Phlaphead 0:61dbbee3f903 277 void FTPRequestHandler::sendData(const char* data, int length)
Phlaphead 0:61dbbee3f903 278 {
Phlaphead 0:61dbbee3f903 279 if(m_pDataSocket)
Phlaphead 0:61dbbee3f903 280 {
Phlaphead 0:61dbbee3f903 281 m_pDataSocket->send(data, length);
Phlaphead 0:61dbbee3f903 282 }
Phlaphead 0:61dbbee3f903 283 }
Phlaphead 0:61dbbee3f903 284
Phlaphead 0:61dbbee3f903 285
Phlaphead 0:61dbbee3f903 286 bool FTPRequestHandler::isAuthenticated()
Phlaphead 0:61dbbee3f903 287 {
Phlaphead 0:61dbbee3f903 288 if(!m_authenticated)
Phlaphead 0:61dbbee3f903 289 {
Phlaphead 0:61dbbee3f903 290 sendReply(530, "Not logged in.");
Phlaphead 0:61dbbee3f903 291 }
Phlaphead 0:61dbbee3f903 292
Phlaphead 0:61dbbee3f903 293 return m_authenticated;
Phlaphead 0:61dbbee3f903 294 }
Phlaphead 0:61dbbee3f903 295
Phlaphead 0:61dbbee3f903 296 void FTPRequestHandler::sendSyntaxError()
Phlaphead 0:61dbbee3f903 297 {
Phlaphead 0:61dbbee3f903 298 sendReply(501, "Syntax error in parameters");
Phlaphead 0:61dbbee3f903 299 }
Phlaphead 0:61dbbee3f903 300
Phlaphead 0:61dbbee3f903 301
Phlaphead 0:61dbbee3f903 302 void FTPRequestHandler::handleRequest()
Phlaphead 0:61dbbee3f903 303 {
Phlaphead 0:61dbbee3f903 304 getRequest();
Phlaphead 0:61dbbee3f903 305 DBG("Request: %s\r\n", request.c_str());
Phlaphead 0:61dbbee3f903 306
Phlaphead 0:61dbbee3f903 307 vector<string> tokens = tokenize(request, " ");
Phlaphead 0:61dbbee3f903 308
Phlaphead 0:61dbbee3f903 309 string& command = tokens[0];
Phlaphead 0:61dbbee3f903 310
Phlaphead 0:61dbbee3f903 311 if(command.compare("USER") == 0)
Phlaphead 0:61dbbee3f903 312 {
Phlaphead 0:61dbbee3f903 313 if(tokens.size() == 2)
Phlaphead 0:61dbbee3f903 314 {
Phlaphead 0:61dbbee3f903 315 cmdUser(tokens[1]);
Phlaphead 0:61dbbee3f903 316 }
Phlaphead 0:61dbbee3f903 317 else
Phlaphead 0:61dbbee3f903 318 {
Phlaphead 0:61dbbee3f903 319 sendSyntaxError();
Phlaphead 0:61dbbee3f903 320 }
Phlaphead 0:61dbbee3f903 321 }
Phlaphead 0:61dbbee3f903 322 else if(command.compare("PASS") == 0)
Phlaphead 0:61dbbee3f903 323 {
Phlaphead 0:61dbbee3f903 324 if(tokens.size() == 2)
Phlaphead 0:61dbbee3f903 325 {
Phlaphead 0:61dbbee3f903 326 cmdPass(tokens[1]);
Phlaphead 0:61dbbee3f903 327 }
Phlaphead 0:61dbbee3f903 328 else
Phlaphead 0:61dbbee3f903 329 {
Phlaphead 0:61dbbee3f903 330 sendSyntaxError();
Phlaphead 0:61dbbee3f903 331 }
Phlaphead 0:61dbbee3f903 332 }
Phlaphead 0:61dbbee3f903 333 else if(command.compare("QUIT") == 0)
Phlaphead 0:61dbbee3f903 334 {
Phlaphead 0:61dbbee3f903 335 cmdQuit();
Phlaphead 0:61dbbee3f903 336 }
Phlaphead 0:61dbbee3f903 337 else if(command.compare("FEAT") == 0)
Phlaphead 0:61dbbee3f903 338 {
Phlaphead 0:61dbbee3f903 339 cmdFeat();
Phlaphead 0:61dbbee3f903 340 }
Phlaphead 0:61dbbee3f903 341 else if(command.compare("PORT") == 0)
Phlaphead 0:61dbbee3f903 342 {
Phlaphead 0:61dbbee3f903 343 if(tokens.size() == 2)
Phlaphead 0:61dbbee3f903 344 {
Phlaphead 0:61dbbee3f903 345 cmdPort(tokens[1]);
Phlaphead 0:61dbbee3f903 346 }
Phlaphead 0:61dbbee3f903 347 else
Phlaphead 0:61dbbee3f903 348 {
Phlaphead 0:61dbbee3f903 349 sendSyntaxError();
Phlaphead 0:61dbbee3f903 350 }
Phlaphead 0:61dbbee3f903 351 }
Phlaphead 0:61dbbee3f903 352 else if(command.compare("PASV") == 0)
Phlaphead 0:61dbbee3f903 353 {
Phlaphead 0:61dbbee3f903 354 cmdPasv();
Phlaphead 0:61dbbee3f903 355 }
Phlaphead 0:61dbbee3f903 356 else if(command.compare("TYPE") == 0)
Phlaphead 0:61dbbee3f903 357 {
Phlaphead 0:61dbbee3f903 358 if(tokens.size() == 2)
Phlaphead 0:61dbbee3f903 359 {
Phlaphead 0:61dbbee3f903 360 cmdType(tokens[1], "");
Phlaphead 0:61dbbee3f903 361 }
Phlaphead 0:61dbbee3f903 362 else if(tokens.size() == 3)
Phlaphead 0:61dbbee3f903 363 {
Phlaphead 0:61dbbee3f903 364 cmdType(tokens[1], tokens[2]);
Phlaphead 0:61dbbee3f903 365 }
Phlaphead 0:61dbbee3f903 366 else
Phlaphead 0:61dbbee3f903 367 {
Phlaphead 0:61dbbee3f903 368 sendSyntaxError();
Phlaphead 0:61dbbee3f903 369 }
Phlaphead 0:61dbbee3f903 370
Phlaphead 0:61dbbee3f903 371 }
Phlaphead 0:61dbbee3f903 372 else if(command.compare("PWD") == 0)
Phlaphead 0:61dbbee3f903 373 {
Phlaphead 0:61dbbee3f903 374 cmdPwd();
Phlaphead 0:61dbbee3f903 375 }
Phlaphead 0:61dbbee3f903 376 else if(command.compare("CWD") == 0)
Phlaphead 0:61dbbee3f903 377 {
Phlaphead 0:61dbbee3f903 378 if(tokens.size() == 2)
Phlaphead 0:61dbbee3f903 379 {
Phlaphead 0:61dbbee3f903 380 cmdCwd(tokens[1]);
Phlaphead 0:61dbbee3f903 381 }
Phlaphead 0:61dbbee3f903 382 else
Phlaphead 0:61dbbee3f903 383 {
Phlaphead 0:61dbbee3f903 384 sendSyntaxError();
Phlaphead 0:61dbbee3f903 385 }
Phlaphead 0:61dbbee3f903 386 }
Phlaphead 0:61dbbee3f903 387 else if(command.compare("CDUP") == 0)
Phlaphead 0:61dbbee3f903 388 {
Phlaphead 0:61dbbee3f903 389 cmdCdup();
Phlaphead 0:61dbbee3f903 390 }
Phlaphead 0:61dbbee3f903 391 else if(command.compare("LIST") == 0)
Phlaphead 0:61dbbee3f903 392 {
Phlaphead 0:61dbbee3f903 393 cmdList();
Phlaphead 0:61dbbee3f903 394 }
Phlaphead 0:61dbbee3f903 395 else if(command.compare("MLSD") == 0)
Phlaphead 0:61dbbee3f903 396 {
Phlaphead 0:61dbbee3f903 397 cmdMlsd();
Phlaphead 0:61dbbee3f903 398 }
Phlaphead 0:61dbbee3f903 399 else
Phlaphead 0:61dbbee3f903 400 {
Phlaphead 0:61dbbee3f903 401 sendReply(202, "Command not implemented.");
Phlaphead 0:61dbbee3f903 402 }
Phlaphead 0:61dbbee3f903 403 }
Phlaphead 0:61dbbee3f903 404
Phlaphead 0:61dbbee3f903 405
Phlaphead 0:61dbbee3f903 406 void FTPRequestHandler::handleResponse()
Phlaphead 0:61dbbee3f903 407 {
Phlaphead 0:61dbbee3f903 408 if(m_command == MLSD)
Phlaphead 0:61dbbee3f903 409 {
Phlaphead 0:61dbbee3f903 410 sendData(m_data_mlsd.c_str(), m_data_mlsd.length());
Phlaphead 0:61dbbee3f903 411 closeDataSocket();
Phlaphead 0:61dbbee3f903 412 m_data_mlsd = "";
Phlaphead 0:61dbbee3f903 413 }
Phlaphead 0:61dbbee3f903 414 else
Phlaphead 0:61dbbee3f903 415 {
Phlaphead 0:61dbbee3f903 416
Phlaphead 0:61dbbee3f903 417 }
Phlaphead 0:61dbbee3f903 418 }
Phlaphead 0:61dbbee3f903 419
Phlaphead 0:61dbbee3f903 420
Phlaphead 0:61dbbee3f903 421 void FTPRequestHandler::cmdUser(const string& username)
Phlaphead 0:61dbbee3f903 422 {
Phlaphead 0:61dbbee3f903 423 m_user.setUsername(username);
Phlaphead 0:61dbbee3f903 424 sendReply(331, "User name okay, need password.");
Phlaphead 0:61dbbee3f903 425 //sendReply(530, "Not logged in.");
Phlaphead 0:61dbbee3f903 426 //sendReply(230, "User logged in, proceed.");
Phlaphead 0:61dbbee3f903 427 }
Phlaphead 0:61dbbee3f903 428
Phlaphead 0:61dbbee3f903 429 void FTPRequestHandler::cmdPass(const string& password)
Phlaphead 0:61dbbee3f903 430 {
Phlaphead 0:61dbbee3f903 431 FTPUser* user = m_pSvr->checkUser(m_user.getUsername(), password);
Phlaphead 0:61dbbee3f903 432
Phlaphead 0:61dbbee3f903 433 if(user != NULL)
Phlaphead 0:61dbbee3f903 434 {
Phlaphead 0:61dbbee3f903 435 m_user = *user;
Phlaphead 0:61dbbee3f903 436 m_authenticated = true;
Phlaphead 0:61dbbee3f903 437 sendReply(230, "User logged in, proceed.");
Phlaphead 0:61dbbee3f903 438 }
Phlaphead 0:61dbbee3f903 439 else
Phlaphead 0:61dbbee3f903 440 {
Phlaphead 0:61dbbee3f903 441 sendReply(530, "Not logged in.");
Phlaphead 0:61dbbee3f903 442 close();
Phlaphead 0:61dbbee3f903 443 }
Phlaphead 0:61dbbee3f903 444 }
Phlaphead 0:61dbbee3f903 445
Phlaphead 0:61dbbee3f903 446 void FTPRequestHandler::cmdQuit()
Phlaphead 0:61dbbee3f903 447 {
Phlaphead 0:61dbbee3f903 448 sendReply(221, "Service closing control connection.");
Phlaphead 0:61dbbee3f903 449 close();
Phlaphead 0:61dbbee3f903 450 }
Phlaphead 0:61dbbee3f903 451
Phlaphead 0:61dbbee3f903 452 void FTPRequestHandler::cmdFeat()
Phlaphead 0:61dbbee3f903 453 {
Phlaphead 0:61dbbee3f903 454 if(isAuthenticated())
Phlaphead 0:61dbbee3f903 455 {
Phlaphead 0:61dbbee3f903 456 //List extended features
Phlaphead 0:61dbbee3f903 457 sendReply("211-Extensions supported:");
Phlaphead 0:61dbbee3f903 458 sendReply(" MLSD");
Phlaphead 0:61dbbee3f903 459 sendReply(211, "End");
Phlaphead 0:61dbbee3f903 460 }
Phlaphead 0:61dbbee3f903 461 }
Phlaphead 0:61dbbee3f903 462
Phlaphead 0:61dbbee3f903 463 void FTPRequestHandler::cmdPort(const string& ip_port)
Phlaphead 0:61dbbee3f903 464 {
Phlaphead 0:61dbbee3f903 465 if(isAuthenticated())
Phlaphead 0:61dbbee3f903 466 {
Phlaphead 0:61dbbee3f903 467 vector<string> ip_port_vector = tokenize(ip_port, ",");
Phlaphead 0:61dbbee3f903 468 if(ip_port_vector.size() != 6)
Phlaphead 0:61dbbee3f903 469 {
Phlaphead 0:61dbbee3f903 470 sendSyntaxError();
Phlaphead 0:61dbbee3f903 471 return;
Phlaphead 0:61dbbee3f903 472 }
Phlaphead 0:61dbbee3f903 473
Phlaphead 0:61dbbee3f903 474 if(m_pDataSocket)
Phlaphead 0:61dbbee3f903 475 {
Phlaphead 0:61dbbee3f903 476 sendReply(500, "Sorry, only one transfer at a time.");
Phlaphead 0:61dbbee3f903 477 return;
Phlaphead 0:61dbbee3f903 478 }
Phlaphead 0:61dbbee3f903 479
Phlaphead 0:61dbbee3f903 480 uint8_t ip1 = atoi(ip_port_vector[0].c_str());
Phlaphead 0:61dbbee3f903 481 uint8_t ip2 = atoi(ip_port_vector[1].c_str());
Phlaphead 0:61dbbee3f903 482 uint8_t ip3 = atoi(ip_port_vector[2].c_str());
Phlaphead 0:61dbbee3f903 483 uint8_t ip4 = atoi(ip_port_vector[3].c_str());
Phlaphead 0:61dbbee3f903 484 uint8_t port1 = atoi(ip_port_vector[4].c_str());
Phlaphead 0:61dbbee3f903 485 uint8_t port2 = atoi(ip_port_vector[5].c_str());
Phlaphead 0:61dbbee3f903 486 int port = (port1 << 8) | port2;
Phlaphead 0:61dbbee3f903 487
Phlaphead 0:61dbbee3f903 488 m_pDataClient = new Host(IpAddr(ip1, ip2, ip3, ip4), port);
Phlaphead 0:61dbbee3f903 489
Phlaphead 0:61dbbee3f903 490 sendReply(200, "PORT Command okay.");
Phlaphead 0:61dbbee3f903 491 }
Phlaphead 0:61dbbee3f903 492 }
Phlaphead 0:61dbbee3f903 493
Phlaphead 0:61dbbee3f903 494 void FTPRequestHandler::cmdPasv()
Phlaphead 0:61dbbee3f903 495 {
Phlaphead 0:61dbbee3f903 496 if(isAuthenticated())
Phlaphead 0:61dbbee3f903 497 {
Phlaphead 0:61dbbee3f903 498 if(m_pDataSocket)
Phlaphead 0:61dbbee3f903 499 {
Phlaphead 0:61dbbee3f903 500 sendReply(500, "Sorry, only one transfer at a time.");
Phlaphead 0:61dbbee3f903 501 return;
Phlaphead 0:61dbbee3f903 502 }
Phlaphead 0:61dbbee3f903 503
Phlaphead 0:61dbbee3f903 504 int port = m_pSvr->getDataPort();
Phlaphead 0:61dbbee3f903 505 const IpAddr& ip = m_pSvr->getIp();
Phlaphead 0:61dbbee3f903 506 uint8_t port2 = (port >> 0) & 0xFF;
Phlaphead 0:61dbbee3f903 507 uint8_t port1 = (port >> 8) & 0xFF;
Phlaphead 0:61dbbee3f903 508 sendReply(227, "Entering passive mode (%u,%u,%u,%u,%u,%u)", ip[0], ip[1], ip[2], ip[3], port1, port2);
Phlaphead 0:61dbbee3f903 509 }
Phlaphead 0:61dbbee3f903 510 }
Phlaphead 0:61dbbee3f903 511
Phlaphead 0:61dbbee3f903 512 void FTPRequestHandler::cmdType(const string& type, const string& arg)
Phlaphead 0:61dbbee3f903 513 {
Phlaphead 0:61dbbee3f903 514 if(isAuthenticated())
Phlaphead 0:61dbbee3f903 515 {
Phlaphead 0:61dbbee3f903 516 sendReply(200, "TYPE ignored (always I)");
Phlaphead 0:61dbbee3f903 517 }
Phlaphead 0:61dbbee3f903 518 }
Phlaphead 0:61dbbee3f903 519
Phlaphead 0:61dbbee3f903 520
Phlaphead 0:61dbbee3f903 521
Phlaphead 0:61dbbee3f903 522 void FTPRequestHandler::cmdPwd()
Phlaphead 0:61dbbee3f903 523 {
Phlaphead 0:61dbbee3f903 524 if(isAuthenticated())
Phlaphead 0:61dbbee3f903 525 {
Phlaphead 0:61dbbee3f903 526 string workDir = fileSystem.getWorkingDirectory();
Phlaphead 0:61dbbee3f903 527 sendReply(257, "\"%s\"", workDir.c_str());
Phlaphead 0:61dbbee3f903 528 }
Phlaphead 0:61dbbee3f903 529 }
Phlaphead 0:61dbbee3f903 530
Phlaphead 0:61dbbee3f903 531 void FTPRequestHandler::cmdCwd(const string& dir)
Phlaphead 0:61dbbee3f903 532 {
Phlaphead 0:61dbbee3f903 533 if(isAuthenticated())
Phlaphead 0:61dbbee3f903 534 {
Phlaphead 0:61dbbee3f903 535 if(fileSystem.changeWorkingDirectory(dir))
Phlaphead 0:61dbbee3f903 536 {
Phlaphead 0:61dbbee3f903 537 sendReply(250, "CWD successful.");
Phlaphead 0:61dbbee3f903 538 }
Phlaphead 0:61dbbee3f903 539 else
Phlaphead 0:61dbbee3f903 540 {
Phlaphead 0:61dbbee3f903 541 sendReply(550, "Directory not found.");
Phlaphead 0:61dbbee3f903 542 }
Phlaphead 0:61dbbee3f903 543 }
Phlaphead 0:61dbbee3f903 544 }
Phlaphead 0:61dbbee3f903 545
Phlaphead 0:61dbbee3f903 546 void FTPRequestHandler::cmdCdup()
Phlaphead 0:61dbbee3f903 547 {
Phlaphead 0:61dbbee3f903 548 cmdCwd("..");
Phlaphead 0:61dbbee3f903 549 }
Phlaphead 0:61dbbee3f903 550
Phlaphead 0:61dbbee3f903 551 void FTPRequestHandler::cmdList()
Phlaphead 0:61dbbee3f903 552 {
Phlaphead 0:61dbbee3f903 553 cmdMlsd();
Phlaphead 0:61dbbee3f903 554 }
Phlaphead 0:61dbbee3f903 555
Phlaphead 0:61dbbee3f903 556
Phlaphead 0:61dbbee3f903 557 void FTPRequestHandler::cmdMlsd()
Phlaphead 0:61dbbee3f903 558 {
Phlaphead 0:61dbbee3f903 559 if(isAuthenticated())
Phlaphead 0:61dbbee3f903 560 {
Phlaphead 0:61dbbee3f903 561 m_command = MLSD;
Phlaphead 0:61dbbee3f903 562 m_data_mlsd = "";
Phlaphead 0:61dbbee3f903 563
Phlaphead 0:61dbbee3f903 564 m_data_mlsd += "Type=cdir; ";
Phlaphead 0:61dbbee3f903 565 m_data_mlsd += fileSystem.getWorkingDirectory();
Phlaphead 0:61dbbee3f903 566 m_data_mlsd += "\r\n";
Phlaphead 0:61dbbee3f903 567
Phlaphead 0:61dbbee3f903 568 list<File> fileList = fileSystem.getFileList();
Phlaphead 0:61dbbee3f903 569 for(list<File>::iterator it = fileList.begin(); it != fileList.end(); it++)
Phlaphead 0:61dbbee3f903 570 {
Phlaphead 0:61dbbee3f903 571 File& file = *it;
Phlaphead 0:61dbbee3f903 572
Phlaphead 0:61dbbee3f903 573 if(file.getType() == TYPE_FILE)
Phlaphead 0:61dbbee3f903 574 {
Phlaphead 0:61dbbee3f903 575 m_data_mlsd += "Type=file;";
Phlaphead 0:61dbbee3f903 576 }
Phlaphead 0:61dbbee3f903 577 else if(file.getType() == TYPE_DIR)
Phlaphead 0:61dbbee3f903 578 {
Phlaphead 0:61dbbee3f903 579 m_data_mlsd += "Type=dir;";
Phlaphead 0:61dbbee3f903 580 }
Phlaphead 0:61dbbee3f903 581
Phlaphead 0:61dbbee3f903 582 m_data_mlsd += " ";
Phlaphead 0:61dbbee3f903 583 m_data_mlsd += file.getName();
Phlaphead 0:61dbbee3f903 584 m_data_mlsd += "\r\n";
Phlaphead 0:61dbbee3f903 585 }
Phlaphead 0:61dbbee3f903 586
Phlaphead 0:61dbbee3f903 587 DBG("\r\n%s", m_data_mlsd.c_str());
Phlaphead 0:61dbbee3f903 588 }
Phlaphead 0:61dbbee3f903 589 }
Phlaphead 0:61dbbee3f903 590