summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2006-02-21 12:28:42 +0000
committerTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2006-02-21 12:28:42 +0000
commite0aa767f9428eb34a7ab7c1169c1ecc55262dade (patch)
tree3af381ddfad8f90ed2d1e93657635679bdad0a55 /src
parent5a8710676d58be3b3f3606993e802c6a075dbd89 (diff)
Diffstat (limited to 'src')
-rw-r--r--src/FtpConnection.cc207
-rw-r--r--src/FtpConnection.h65
-rw-r--r--src/FtpDownloadCommand.cc38
-rw-r--r--src/FtpDownloadCommand.h37
-rw-r--r--src/FtpInitiateConnectionCommand.cc84
-rw-r--r--src/FtpInitiateConnectionCommand.h39
-rw-r--r--src/FtpNegotiationCommand.cc328
-rw-r--r--src/FtpNegotiationCommand.h87
-rw-r--r--src/FtpTunnelRequestCommand.cc41
-rw-r--r--src/FtpTunnelRequestCommand.h35
-rw-r--r--src/FtpTunnelResponseCommand.cc49
-rw-r--r--src/FtpTunnelResponseCommand.h39
-rw-r--r--src/HttpHeader.cc66
-rw-r--r--src/HttpHeader.h46
14 files changed, 1161 insertions, 0 deletions
diff --git a/src/FtpConnection.cc b/src/FtpConnection.cc
new file mode 100644
index 00000000..4c528ada
--- /dev/null
+++ b/src/FtpConnection.cc
@@ -0,0 +1,207 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "FtpConnection.h"
+#include "Util.h"
+#include "DlAbortEx.h"
+#include "message.h"
+
+FtpConnection::FtpConnection(int cuid, const Socket* socket, const Request* req, const Option* op, const Logger* logger):cuid(cuid), socket(socket), req(req), option(op), logger(logger) {}
+
+FtpConnection::~FtpConnection() {}
+
+void FtpConnection::sendUser() const {
+ string request = "USER "+option->get("ftp_user")+"\r\n";
+ logger->info(MSG_SENDING_FTP_REQUEST, cuid, request.c_str());
+ socket->writeData(request);
+}
+
+void FtpConnection::sendPass() const {
+ string request = "PASS "+option->get("ftp_passwd")+"\r\n";
+ logger->info(MSG_SENDING_FTP_REQUEST, cuid, "PASS ********");
+ socket->writeData(request);
+}
+
+void FtpConnection::sendType() const {
+ string request = "TYPE "+option->get("ftp_type")+"\r\n";
+ logger->info(MSG_SENDING_FTP_REQUEST, cuid, request.c_str());
+ socket->writeData(request);
+}
+
+void FtpConnection::sendCwd() const {
+ string request = "CWD "+req->getDir()+"\r\n";
+ logger->info(MSG_SENDING_FTP_REQUEST, cuid, request.c_str());
+ socket->writeData(request);
+}
+
+void FtpConnection::sendSize() const {
+ string request = "SIZE "+req->getFile()+"\r\n";
+ logger->info(MSG_SENDING_FTP_REQUEST, cuid, request.c_str());
+ socket->writeData(request);
+}
+
+void FtpConnection::sendPasv() const {
+ string request = "PASV\r\n";
+ logger->info(MSG_SENDING_FTP_REQUEST, cuid, request.c_str());
+ socket->writeData(request);
+}
+
+Socket* FtpConnection::sendPort() const {
+ Socket* serverSocket = new Socket();
+ try {
+ serverSocket->beginListen();
+
+ pair<string, int> addrinfo;
+ socket->getAddrInfo(addrinfo);
+ int ipaddr[4];
+ sscanf(addrinfo.first.c_str(), "%d.%d.%d.%d",
+ &ipaddr[0], &ipaddr[1], &ipaddr[2], &ipaddr[3]);
+ serverSocket->getAddrInfo(addrinfo);
+ string request = "PORT "+
+ Util::itos(ipaddr[0])+","+Util::itos(ipaddr[1])+","+
+ Util::itos(ipaddr[2])+","+Util::itos(ipaddr[3])+","+
+ Util::itos(addrinfo.second/256)+","+Util::itos(addrinfo.second%256)+"\r\n";
+ logger->info(MSG_SENDING_FTP_REQUEST, cuid, request.c_str());
+ socket->writeData(request);
+ } catch (Exception* ex) {
+ delete serverSocket;
+ throw;
+ }
+ return serverSocket;
+}
+
+void FtpConnection::sendRest(const Segment& segment) const {
+ string request = "REST "+Util::llitos(segment.sp+segment.ds)+"\r\n";
+ logger->info(MSG_SENDING_FTP_REQUEST, cuid, request.c_str());
+ socket->writeData(request);
+}
+
+void FtpConnection::sendRetr() const {
+ string request = "RETR "+req->getFile()+"\r\n";
+ logger->info(MSG_SENDING_FTP_REQUEST, cuid, request.c_str());
+ socket->writeData(request);
+}
+
+int FtpConnection::getStatus(string response) const {
+ int status;
+ // TODO we must handle when the response is not like "%d %*s"
+ // In this case, we return 0
+ if(sscanf(response.c_str(), "%d %*s", &status) == 1) {
+ return status;
+ } else {
+ return 0;
+ }
+}
+
+bool FtpConnection::isEndOfResponse(int status, string response) const {
+ if(response.size() <= 4) {
+ return false;
+ }
+ // if forth character of buf is '-', then multi line response is expected.
+ if(response.at(3) == '-') {
+ // multi line response
+ string::size_type p;
+ p = response.find("\r\n"+Util::itos(status)+" ");
+ if(p == string::npos) {
+ return false;
+ }
+ }
+ if(Util::endsWith(response, "\r\n")) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool FtpConnection::bulkReceiveResponse(pair<int, string>& response) {
+ char buf[1024];
+ while(socket->isReadable(0)) {
+ int size = sizeof(buf)-1;
+ socket->readData(buf, size);
+ buf[size] = '\0';
+ strbuf += buf;
+ }
+ int status;
+ if(strbuf.size() >= 4) {
+ status = getStatus(strbuf);
+ if(status == 0) {
+ throw new DlAbortEx(EX_INVALID_RESPONSE);
+ }
+ } else {
+ return false;
+ }
+ if(isEndOfResponse(status, strbuf)) {
+ logger->info(MSG_RECEIVE_RESPONSE, cuid, strbuf.c_str());
+ response.first = status;
+ response.second = strbuf;
+ strbuf.erase();
+ return true;
+ } else {
+ // didn't receive response fully.
+ return false;
+ }
+}
+
+int FtpConnection::receiveResponse() {
+ pair<int, string> response;
+ if(bulkReceiveResponse(response)) {
+ return response.first;
+ } else {
+ return 0;
+ }
+}
+
+int FtpConnection::receiveSizeResponse(long long int& size) {
+ pair<int, string> response;
+ if(bulkReceiveResponse(response)) {
+ if(response.first == 213) {
+ sscanf(response.second.c_str(), "%*d %Ld", &size);
+ }
+ return response.first;
+ } else {
+ return 0;
+ }
+}
+
+int FtpConnection::receivePasvResponse(pair<string, int>& dest) {
+ pair<int, string> response;
+ if(bulkReceiveResponse(response)) {
+ if(response.first == 227) {
+ // we assume the format of response is "227 Entering Passive Mode (h1,h2,h3,h4,p1,p2)."
+ int h1, h2, h3, h4, p1, p2;
+ string::size_type p = response.second.find("(");
+ if(p >= 4) {
+ sscanf(response.second.substr(response.second.find("(")).c_str(),
+ "(%d,%d,%d,%d,%d,%d).",
+ &h1, &h2, &h3, &h4, &p1, &p2);
+ // ip address
+ dest.first = Util::itos(h1)+"."+Util::itos(h2)+"."+Util::itos(h3)+"."+Util::itos(h4);
+ // port number
+ dest.second = 256*p1+p2;
+ } else {
+ throw new DlAbortEx(EX_INVALID_RESPONSE);
+ }
+ }
+ return response.first;
+ } else {
+ return 0;
+ }
+}
diff --git a/src/FtpConnection.h b/src/FtpConnection.h
new file mode 100644
index 00000000..6dab8e68
--- /dev/null
+++ b/src/FtpConnection.h
@@ -0,0 +1,65 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_FTP_CONNECTION_H_
+#define _D_FTP_CONNECTION_H_
+
+#include "Socket.h"
+#include "Option.h"
+#include "Logger.h"
+#include "Segment.h"
+#include "Request.h"
+#include <utility>
+
+using namespace std;
+
+class FtpConnection {
+private:
+ int cuid;
+ const Socket* socket;
+ const Request* req;
+ const Option* option;
+ const Logger* logger;
+
+ string strbuf;
+
+ int getStatus(string response) const;
+ bool isEndOfResponse(int status, string response) const;
+ bool bulkReceiveResponse(pair<int, string>& response);
+public:
+ FtpConnection(int cuid, const Socket* socket, const Request* req, const Option* op, const Logger* logger);
+ ~FtpConnection();
+ void sendUser() const;
+ void sendPass() const;
+ void sendType() const;
+ void sendCwd() const;
+ void sendSize() const;
+ void sendPasv() const;
+ Socket* sendPort() const;
+ void sendRest(const Segment& segment) const;
+ void sendRetr() const;
+
+ int receiveResponse();
+ int receiveSizeResponse(long long int& size);
+ int receivePasvResponse(pair<string, int>& dest);
+};
+
+#endif // _D_FTP_CONNECTION_H_
diff --git a/src/FtpDownloadCommand.cc b/src/FtpDownloadCommand.cc
new file mode 100644
index 00000000..3d29c84c
--- /dev/null
+++ b/src/FtpDownloadCommand.cc
@@ -0,0 +1,38 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "FtpDownloadCommand.h"
+
+FtpDownloadCommand::FtpDownloadCommand(int cuid, Request* req, DownloadEngine* e, Socket* dataSocket, Socket* ctrlSocket):
+ DownloadCommand(cuid, req, e, dataSocket)
+{
+ this->ctrlSocket = new Socket(*ctrlSocket);
+}
+
+FtpDownloadCommand::~FtpDownloadCommand() {
+ if(ctrlSocket != NULL) {
+ delete ctrlSocket;
+ }
+}
+
+TransferEncoding* FtpDownloadCommand::getTransferEncoding(string name) {
+ return NULL;
+}
diff --git a/src/FtpDownloadCommand.h b/src/FtpDownloadCommand.h
new file mode 100644
index 00000000..b2db68a8
--- /dev/null
+++ b/src/FtpDownloadCommand.h
@@ -0,0 +1,37 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_FTP_DOWNLOAD_COMMAND_H_
+#define _D_FTP_DOWNLOAD_COMMAND_H_
+
+#include "DownloadCommand.h"
+
+class FtpDownloadCommand : public DownloadCommand {
+private:
+ Socket* ctrlSocket;
+public:
+ FtpDownloadCommand(int cuid, Request* req, DownloadEngine* e, Socket* dataSocket, Socket* ctrlSocket);
+ ~FtpDownloadCommand();
+
+ TransferEncoding* getTransferEncoding(string name);
+};
+
+#endif // _D_FTP_DOWNLOAD_COMMAND_H_
diff --git a/src/FtpInitiateConnectionCommand.cc b/src/FtpInitiateConnectionCommand.cc
new file mode 100644
index 00000000..26bec02c
--- /dev/null
+++ b/src/FtpInitiateConnectionCommand.cc
@@ -0,0 +1,84 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "FtpInitiateConnectionCommand.h"
+#include "FtpNegotiationCommand.h"
+#include "HttpRequestCommand.h"
+#include "FtpTunnelRequestCommand.h"
+#include "DlAbortEx.h"
+#include "message.h"
+
+FtpInitiateConnectionCommand::FtpInitiateConnectionCommand(int cuid, Request* req, DownloadEngine* e):AbstractCommand(cuid, req, e) {}
+
+FtpInitiateConnectionCommand::~FtpInitiateConnectionCommand() {}
+
+bool FtpInitiateConnectionCommand::executeInternal(Segment segment) {
+ if(!e->segmentMan->downloadStarted) {
+ e->segmentMan->filename = req->getFile();
+ bool segFileExists = e->segmentMan->segmentFileExists();
+ if(segFileExists) {
+ e->segmentMan->load();
+ e->diskWriter->openExistingFile(e->segmentMan->getFilePath());
+ e->segmentMan->downloadStarted = true;
+ } else {
+ e->diskWriter->initAndOpenFile(e->segmentMan->getFilePath());
+ }
+ }
+
+ socket = new Socket();
+ Command* command;
+ if(useHttpProxy()) {
+ e->logger->info(MSG_CONNECTING_TO_SERVER, cuid,
+ e->option->get("http_proxy_host").c_str(),
+ e->option->getAsInt("http_proxy_port"));
+ socket->establishConnection(e->option->get("http_proxy_host"),
+ e->option->getAsInt("http_proxy_port"));
+
+ if(useHttpProxyGet()) {
+ command = new HttpRequestCommand(cuid, req, e, socket);
+ } else if(useHttpProxyConnect()) {
+ command = new FtpTunnelRequestCommand(cuid, req, e, socket);
+ } else {
+ // TODO
+ throw new DlAbortEx("ERROR");
+ }
+ } else {
+ e->logger->info(MSG_CONNECTING_TO_SERVER, cuid, req->getHost().c_str(),
+ req->getPort());
+ socket->establishConnection(req->getHost(), req->getPort());
+ command = new FtpNegotiationCommand(cuid, req, e, socket);
+ }
+ e->commands.push(command);
+ return true;
+}
+
+bool FtpInitiateConnectionCommand::useHttpProxy() const {
+ return e->option->defined("http_proxy_enabled") &&
+ e->option->get("http_proxy_enabled") == "true";
+}
+
+bool FtpInitiateConnectionCommand::useHttpProxyGet() const {
+ return useHttpProxy() && e->option->get("ftp_via_http_proxy") == "get";
+}
+
+bool FtpInitiateConnectionCommand::useHttpProxyConnect() const {
+ return useHttpProxy() && e->option->get("ftp_via_http_proxy") == "tunnel";
+}
diff --git a/src/FtpInitiateConnectionCommand.h b/src/FtpInitiateConnectionCommand.h
new file mode 100644
index 00000000..0f997bf8
--- /dev/null
+++ b/src/FtpInitiateConnectionCommand.h
@@ -0,0 +1,39 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_FTP_INITIATE_CONNECTION_COMMAND_H_
+#define _D_FTP_INITIATE_CONNECTION_COMMAND_H_
+
+#include "AbstractCommand.h"
+
+class FtpInitiateConnectionCommand : public AbstractCommand {
+private:
+ bool useHttpProxy() const;
+ bool useHttpProxyGet() const;
+ bool useHttpProxyConnect() const;
+protected:
+ bool executeInternal(Segment segment);
+public:
+ FtpInitiateConnectionCommand(int cuid, Request* req, DownloadEngine* e);
+ ~FtpInitiateConnectionCommand();
+};
+
+#endif // _D_FTP_INITIATE_CONNECTION_COMMAND_H_
diff --git a/src/FtpNegotiationCommand.cc b/src/FtpNegotiationCommand.cc
new file mode 100644
index 00000000..ee6821ec
--- /dev/null
+++ b/src/FtpNegotiationCommand.cc
@@ -0,0 +1,328 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "FtpNegotiationCommand.h"
+#include "FtpDownloadCommand.h"
+#include "DlAbortEx.h"
+#include "message.h"
+
+FtpNegotiationCommand::FtpNegotiationCommand(int cuid, Request* req, DownloadEngine* e, Socket* s):
+ AbstractCommand(cuid, req, e, s),
+ dataSocket(NULL), serverSocket(NULL), sequence(SEQ_RECV_GREETING)
+{
+ ftp = new FtpConnection(cuid, socket, req, e->option, e->logger);
+ setReadCheckSocket(NULL);
+ setWriteCheckSocket(socket);
+}
+
+FtpNegotiationCommand::~FtpNegotiationCommand() {
+ if(dataSocket != NULL) {
+ delete dataSocket;
+ }
+ if(serverSocket != NULL) {
+ delete serverSocket;
+ }
+ delete ftp;
+}
+
+bool FtpNegotiationCommand::executeInternal(Segment segment) {
+ while(processSequence(segment));
+ if(sequence == SEQ_RETRY) {
+ return prepareForRetry(0);
+ } else if(sequence == SEQ_NEGOTIATION_COMPLETED) {
+ FtpDownloadCommand* command = new FtpDownloadCommand(cuid, req, e, dataSocket, socket);
+ e->commands.push(command);
+ return true;
+ } else {
+ e->commands.push(this);
+ return false;
+ }
+}
+
+bool FtpNegotiationCommand::recvGreeting() {
+ socket->setBlockingMode();
+ int status = ftp->receiveResponse();
+ if(status == 0) {
+ return false;
+ }
+ if(status != 220) {
+ throw new DlAbortEx(EX_CONNECTION_FAILED);
+ }
+ sequence = SEQ_SEND_USER;
+
+ setReadCheckSocket(socket);
+ setWriteCheckSocket(NULL);
+
+ return true;
+}
+
+bool FtpNegotiationCommand::sendUser() {
+ ftp->sendUser();
+ sequence = SEQ_RECV_USER;
+ return false;
+}
+
+bool FtpNegotiationCommand::recvUser() {
+ int status = ftp->receiveResponse();
+ switch(status) {
+ case 0:
+ return false;
+ case 230:
+ sequence = SEQ_SEND_TYPE;
+ break;
+ case 331:
+ sequence = SEQ_SEND_PASS;
+ break;
+ default:
+ throw new DlAbortEx(EX_BAD_STATUS, status);
+ }
+ return true;
+}
+
+bool FtpNegotiationCommand::sendPass() {
+ ftp->sendPass();
+ sequence = SEQ_RECV_PASS;
+ return false;
+}
+
+bool FtpNegotiationCommand::recvPass() {
+ int status = ftp->receiveResponse();
+ if(status == 0) {
+ return false;
+ }
+ if(status != 230) {
+ throw new DlAbortEx(EX_BAD_STATUS, status);
+ }
+ sequence = SEQ_SEND_TYPE;
+ return true;
+}
+
+bool FtpNegotiationCommand::sendType() {
+ ftp->sendType();
+ sequence = SEQ_RECV_TYPE;
+ return false;
+}
+
+bool FtpNegotiationCommand::recvType() {
+ int status = ftp->receiveResponse();
+ if(status == 0) {
+ return false;
+ }
+ if(status != 200) {
+ throw new DlAbortEx(EX_BAD_STATUS, status);
+ }
+ sequence = SEQ_SEND_CWD;
+ return true;
+}
+
+bool FtpNegotiationCommand::sendCwd() {
+ ftp->sendCwd();
+ sequence = SEQ_RECV_CWD;
+ return false;
+}
+
+bool FtpNegotiationCommand::recvCwd() {
+ int status = ftp->receiveResponse();
+ if(status == 0) {
+ return false;
+ }
+ if(status != 250) {
+ throw new DlAbortEx(EX_BAD_STATUS, status);
+ }
+ sequence = SEQ_SEND_SIZE;
+ return true;
+}
+
+bool FtpNegotiationCommand::sendSize() {
+ ftp->sendSize();
+ sequence = SEQ_RECV_SIZE;
+ return false;
+}
+
+bool FtpNegotiationCommand::recvSize() {
+ long long int size = 0;
+ int status = ftp->receiveSizeResponse(size);
+ if(status == 0) {
+ return false;
+ }
+ if(status != 213) {
+ throw new DlAbortEx(EX_BAD_STATUS, status);
+ }
+ // TODO check the value of size
+ if(!e->segmentMan->downloadStarted) {
+ e->segmentMan->downloadStarted = true;
+ e->segmentMan->totalSize = size;
+ } else if(e->segmentMan->totalSize != size) {
+ throw new DlAbortEx(EX_SIZE_MISMATCH, e->segmentMan->totalSize, size);
+ }
+ if(e->option->get("ftp_pasv_enabled") == "true") {
+ sequence = SEQ_SEND_PASV;
+ } else {
+ sequence = SEQ_SEND_PORT;
+ }
+ return true;
+}
+
+bool FtpNegotiationCommand::sendPort() {
+ serverSocket = ftp->sendPort();
+ sequence = SEQ_RECV_PORT;
+ return false;
+}
+
+bool FtpNegotiationCommand::recvPort() {
+ int status = ftp->receiveResponse();
+ if(status == 0) {
+ return false;
+ }
+ if(status != 200) {
+ throw new DlAbortEx(EX_BAD_STATUS, status);
+ }
+ sequence = SEQ_SEND_REST;
+ return true;
+}
+
+bool FtpNegotiationCommand::sendPasv() {
+ ftp->sendPasv();
+ sequence = SEQ_RECV_PASV;
+ return false;
+}
+
+bool FtpNegotiationCommand::recvPasv() {
+ pair<string, int> dest;
+ int status = ftp->receivePasvResponse(dest);
+ if(status == 0) {
+ return false;
+ }
+ if(status != 227) {
+ throw new DlAbortEx(EX_BAD_STATUS, status);
+ }
+ // make a data connection to the server.
+ dataSocket = new Socket();
+
+ e->logger->info(MSG_CONNECTING_TO_SERVER, cuid,
+ dest.first.c_str(),
+ dest.second);
+ dataSocket->establishConnection(dest.first, dest.second);
+
+ setReadCheckSocket(NULL);
+ setWriteCheckSocket(dataSocket);
+
+ sequence = SEQ_SEND_REST_PASV;
+ return false;
+}
+
+bool FtpNegotiationCommand::sendRestPasv(const Segment& segment) {
+ dataSocket->setBlockingMode();
+ setReadCheckSocket(socket);
+ setWriteCheckSocket(NULL);
+ return sendRest(segment);
+}
+
+bool FtpNegotiationCommand::sendRest(const Segment& segment) {
+ ftp->sendRest(segment);
+ sequence = SEQ_RECV_REST;
+ return false;
+}
+
+bool FtpNegotiationCommand::recvRest() {
+ int status = ftp->receiveResponse();
+ if(status == 0) {
+ return false;
+ }
+ // TODO if we recieve negative response, then we set e->segmentMan->splittable = false, and continue.
+ if(status != 350) {
+ throw new DlAbortEx(EX_BAD_STATUS, status);
+ }
+ sequence = SEQ_SEND_RETR;
+ return true;
+}
+
+bool FtpNegotiationCommand::sendRetr() {
+ ftp->sendRetr();
+ sequence = SEQ_RECV_RETR;
+ return false;
+}
+
+bool FtpNegotiationCommand::recvRetr() {
+ int status = ftp->receiveResponse();
+ if(status == 0) {
+ return false;
+ }
+ if(status != 150) {
+ throw new DlAbortEx(EX_BAD_STATUS, status);
+ }
+ if(e->option->get("ftp_pasv_enabled") != "true") {
+ assert(serverSocket);
+ dataSocket = serverSocket->acceptConnection();
+ }
+ sequence = SEQ_NEGOTIATION_COMPLETED;
+
+ return false;
+}
+
+bool FtpNegotiationCommand::processSequence(const Segment& segment) {
+ bool doNextSequence = true;
+ switch(sequence) {
+ case SEQ_RECV_GREETING:
+ return recvGreeting();
+ case SEQ_SEND_USER:
+ return sendUser();
+ case SEQ_RECV_USER:
+ return recvUser();
+ case SEQ_SEND_PASS:
+ return sendPass();
+ case SEQ_RECV_PASS:
+ return recvPass();
+ case SEQ_SEND_TYPE:
+ return sendType();
+ case SEQ_RECV_TYPE:
+ return recvType();
+ case SEQ_SEND_CWD:
+ return sendCwd();
+ case SEQ_RECV_CWD:
+ return recvCwd();
+ case SEQ_SEND_SIZE:
+ return sendSize();
+ case SEQ_RECV_SIZE:
+ return recvSize();
+ case SEQ_SEND_PORT:
+ return sendPort();
+ case SEQ_RECV_PORT:
+ return recvPort();
+ case SEQ_SEND_PASV:
+ return sendPasv();
+ case SEQ_RECV_PASV:
+ return recvPasv();
+ case SEQ_SEND_REST_PASV:
+ return sendRestPasv(segment);
+ case SEQ_SEND_REST:
+ return sendRest(segment);
+ case SEQ_RECV_REST:
+ return recvRest();
+ case SEQ_SEND_RETR:
+ return sendRetr();
+ case SEQ_RECV_RETR:
+ return recvRetr();
+ default:
+ abort();
+ }
+ return doNextSequence;
+}
diff --git a/src/FtpNegotiationCommand.h b/src/FtpNegotiationCommand.h
new file mode 100644
index 00000000..29e2c0e6
--- /dev/null
+++ b/src/FtpNegotiationCommand.h
@@ -0,0 +1,87 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_FTP_NEGOTIATION_COMMAND_H_
+#define _D_FTP_NEGOTIATION_COMMAND_H_
+
+#include "AbstractCommand.h"
+#include "FtpConnection.h"
+
+class FtpNegotiationCommand : public AbstractCommand {
+private:
+ enum Seq {
+ SEQ_RECV_GREETING,
+ SEQ_SEND_USER,
+ SEQ_RECV_USER,
+ SEQ_SEND_PASS,
+ SEQ_RECV_PASS,
+ SEQ_SEND_TYPE,
+ SEQ_RECV_TYPE,
+ SEQ_SEND_CWD,
+ SEQ_RECV_CWD,
+ SEQ_SEND_SIZE,
+ SEQ_RECV_SIZE,
+ SEQ_SEND_PORT,
+ SEQ_RECV_PORT,
+ SEQ_SEND_PASV,
+ SEQ_RECV_PASV,
+ SEQ_SEND_REST_PASV,
+ SEQ_SEND_REST,
+ SEQ_RECV_REST,
+ SEQ_SEND_RETR,
+ SEQ_RECV_RETR,
+ SEQ_NEGOTIATION_COMPLETED,
+ SEQ_RETRY
+ };
+ bool recvGreeting();
+ bool sendUser();
+ bool recvUser();
+ bool sendPass();
+ bool recvPass();
+ bool sendType();
+ bool recvType();
+ bool sendCwd();
+ bool recvCwd();
+ bool sendSize();
+ bool recvSize();
+ bool sendPort();
+ bool recvPort();
+ bool sendPasv();
+ bool recvPasv();
+ bool sendRest(const Segment& segment);
+ bool sendRestPasv(const Segment& segment);
+ bool recvRest();
+ bool sendRetr();
+ bool recvRetr();
+ bool processSequence(const Segment& segment);
+
+ Socket* dataSocket;
+ Socket* serverSocket;
+ int sequence;
+ FtpConnection* ftp;
+protected:
+ bool executeInternal(Segment segment);
+public:
+ FtpNegotiationCommand(int cuid, Request* req, DownloadEngine* e, Socket* s);
+ ~FtpNegotiationCommand();
+};
+
+#endif // _D_FTP_NEGOTIATION_COMMAND_H_
diff --git a/src/FtpTunnelRequestCommand.cc b/src/FtpTunnelRequestCommand.cc
new file mode 100644
index 00000000..f103f7ce
--- /dev/null
+++ b/src/FtpTunnelRequestCommand.cc
@@ -0,0 +1,41 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "FtpTunnelRequestCommand.h"
+#include "FtpTunnelResponseCommand.h"
+#include "HttpConnection.h"
+
+FtpTunnelRequestCommand::FtpTunnelRequestCommand(int cuid, Request* req, DownloadEngine* e, Socket* s):AbstractCommand(cuid, req, e, s) {
+ setReadCheckSocket(NULL);
+ setWriteCheckSocket(NULL);
+}
+
+FtpTunnelRequestCommand::~FtpTunnelRequestCommand() {}
+
+bool FtpTunnelRequestCommand::executeInternal(Segment segment) {
+ socket->setBlockingMode();
+ HttpConnection httpConnection(cuid, socket, req, e->option, e->logger);
+ httpConnection.sendProxyRequest();
+
+ FtpTunnelResponseCommand* command = new FtpTunnelResponseCommand(cuid, req, e, socket);
+ e->commands.push(command);
+ return true;
+}
diff --git a/src/FtpTunnelRequestCommand.h b/src/FtpTunnelRequestCommand.h
new file mode 100644
index 00000000..817f1c9d
--- /dev/null
+++ b/src/FtpTunnelRequestCommand.h
@@ -0,0 +1,35 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_FTP_TUNNEL_REQUEST_COMMAND_H_
+#define _D_FTP_TUNNEL_REQUEST_COMMAND_H_
+
+#include "AbstractCommand.h"
+
+class FtpTunnelRequestCommand : public AbstractCommand {
+protected:
+ bool executeInternal(Segment segment);
+public:
+ FtpTunnelRequestCommand(int cuid, Request* req, DownloadEngine* e, Socket* s);
+ ~FtpTunnelRequestCommand();
+};
+
+#endif // _D_FTP_TUNNEL_REQUEST_COMMAND_H_
diff --git a/src/FtpTunnelResponseCommand.cc b/src/FtpTunnelResponseCommand.cc
new file mode 100644
index 00000000..7009310c
--- /dev/null
+++ b/src/FtpTunnelResponseCommand.cc
@@ -0,0 +1,49 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "FtpTunnelResponseCommand.h"
+#include "FtpNegotiationCommand.h"
+#include "DlRetryEx.h"
+#include "message.h"
+
+FtpTunnelResponseCommand::FtpTunnelResponseCommand(int cuid, Request* req, DownloadEngine* e, Socket* s):AbstractCommand(cuid, req, e, s) {
+ http = new HttpConnection(cuid, socket, req, e->option, e->logger);
+}
+
+FtpTunnelResponseCommand::~FtpTunnelResponseCommand() {
+ delete http;
+}
+
+bool FtpTunnelResponseCommand::executeInternal(Segment segment) {
+ HttpHeader headers;
+ int status = http->receiveResponse(headers);
+ if(status == 0) {
+ // we didn't receive all of headers yet.
+ e->commands.push(this);
+ return false;
+ }
+ if(status != 200) {
+ throw new DlRetryEx(EX_PROXY_CONNECTION_FAILED);
+ }
+ FtpNegotiationCommand* command = new FtpNegotiationCommand(cuid, req, e, socket);
+ e->commands.push(command);
+ return true;
+}
diff --git a/src/FtpTunnelResponseCommand.h b/src/FtpTunnelResponseCommand.h
new file mode 100644
index 00000000..eeba75ac
--- /dev/null
+++ b/src/FtpTunnelResponseCommand.h
@@ -0,0 +1,39 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_FTP_TUNNEL_RESPONSE_COMMAND_H_
+#define _D_FTP_TUNNEL_RESPONSE_COMMAND_H_
+
+#include "AbstractCommand.h"
+#include "HttpConnection.h"
+
+class FtpTunnelResponseCommand : public AbstractCommand {
+private:
+ HttpConnection* http;
+protected:
+ bool executeInternal(Segment segment);
+public:
+ FtpTunnelResponseCommand(int cuid, Request* req, DownloadEngine* e, Socket* s);
+ ~FtpTunnelResponseCommand();
+};
+
+#endif // _D_FTP_TUNNEL_RESPONSE_COMMAND_H_
+
diff --git a/src/HttpHeader.cc b/src/HttpHeader.cc
new file mode 100644
index 00000000..eb80cf5b
--- /dev/null
+++ b/src/HttpHeader.cc
@@ -0,0 +1,66 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#include "HttpHeader.h"
+
+void HttpHeader::put(const string& name, const string& value) {
+ multimap<string, string>::value_type vt(name, value);
+ table.insert(vt);
+}
+
+bool HttpHeader::defined(const string& name) const {
+ return table.count(name) == 1;
+}
+
+string HttpHeader::getFirst(const string& name) const {
+ multimap<string, string>::const_iterator itr = table.find(name);
+ if(itr == table.end()) {
+ return "";
+ } else {
+ return (*itr).second;
+ }
+}
+
+vector<string> HttpHeader::get(const string& name) const {
+ vector<string> v;
+ for(multimap<string, string>::const_iterator itr = table.find(name); itr != table.end(); itr++) {
+ v.push_back((*itr).second);
+ }
+ return v;
+}
+
+int HttpHeader::getFirstAsInt(const string& name) const {
+ multimap<string, string>::const_iterator itr = table.find(name);
+ if(itr == table.end()) {
+ return 0;
+ } else {
+ return (int)strtol((*itr).second.c_str(), NULL, 10);
+ }
+}
+
+long long int HttpHeader::getFirstAsLLInt(const string& name) const {
+ multimap<string, string>::const_iterator itr = table.find(name);
+ if(itr == table.end()) {
+ return 0;
+ } else {
+ return strtoll((*itr).second.c_str(), NULL, 10);
+ }
+}
diff --git a/src/HttpHeader.h b/src/HttpHeader.h
new file mode 100644
index 00000000..3bcaa479
--- /dev/null
+++ b/src/HttpHeader.h
@@ -0,0 +1,46 @@
+/* <!-- copyright */
+/*
+ * aria2 - a simple utility for downloading files faster
+ *
+ * Copyright (C) 2006 Tatsuhiro Tsujikawa
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+/* copyright --> */
+#ifndef _D_HTTP_HEADER_H_
+#define _D_HTTP_HEADER_H_
+
+#include <map>
+#include <vector>
+#include <string>
+
+using namespace std;
+
+class HttpHeader {
+private:
+ multimap<string, string> table;
+public:
+ HttpHeader() {}
+ ~HttpHeader() {}
+
+ void put(const string& name, const string& value);
+ bool defined(const string& name) const;
+ string getFirst(const string& name) const;
+ vector<string> get(const string& name) const;
+ int getFirstAsInt(const string& name) const;
+ long long int getFirstAsLLInt(const string& name) const;
+};
+
+#endif // _D_HTTP_HEADER_H_