Ver código fonte

2007-06-10 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

	* src/AbstractCommand.cc
	(execute): Changed log level of MSG_RESTARTING_DOWNLOAD and
	MSG_MAX_TRY from error to info.
	Added MSG_DOWNLOAD_ABORTED after MSG_MAX_TRY.

	* src/message.h
	(MSG_TORRENT_DOWNLOAD_ABORTED): New definition.
	(MSG_DOWNLOAD_ABORTED): Added %s.
	(MSG_RESTARTING_DOWNLOAD): Added %s.
	(MSG_DOWNLOAD_ALREADY_COMPLETED): Updated.
	
	* src/PeerAbstractCommand.cc
	(execute): MSG_DOWNLOAD_ABORTED -> MSG_TORRENT_DOWNLOAD_ABORTED
	
	* src/Request.h
	(cookieBox): Made ShardHandle.
	
	* src/RequestGroup.h, src/RequestGroup.cc
	(createNextCommandWithAdj): New function.
	* src/FileAllocationCommand.cc
	(executeInternal): Use createNextCommandWithAdj().
	* src/CheckIntegrityCommand.cc
	(executeInternal): Use createNextCommandWithAdj().

	Added --load-cookies command-option.
	* src/OptionHandlerFactory.cc
	(createOptionHandlers): Added PREF_LOAD_COOKIES.
	* src/CookieBox.h, src/CookieBox.cc: Rwritten using CookieParser.
	Now aria2 can handle cookie's expiration date.
	* src/Cookie.h (expires): Changed its type to time_t.
	* src/main.cc: Added --load-cookies command-line option.
	* src/prefs.h (PREF_LOAD_COOKIES): New definition.
	* src/Util.h, src/Util.cc (httpGMT): New function.
	* src/Request.cc (Request): Initialize cookieBox using
	CookieBoxFactory.
	* src/CookieBoxFactory.h, src/CookieBoxFactory.cc: New class.
	* src/CookieParser.h, src/CookieParser.cc: New class.
	
	* src/main.cc: Chagned the default value of --metalink-servers to 5.

	* src/HttpResponseCommand.cc
	(handleOtherEncoding): Call RequestGroup::shouldCancelDownloadForSafety
Tatsuhiro Tsujikawa 18 anos atrás
pai
commit
d5bb035642

+ 45 - 0
ChangeLog

@@ -1,3 +1,48 @@
+2007-06-10  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
+
+	* src/AbstractCommand.cc
+	(execute): Changed log level of MSG_RESTARTING_DOWNLOAD and
+	MSG_MAX_TRY from error to info.
+	Added MSG_DOWNLOAD_ABORTED after MSG_MAX_TRY.
+
+	* src/message.h
+	(MSG_TORRENT_DOWNLOAD_ABORTED): New definition.
+	(MSG_DOWNLOAD_ABORTED): Added %s.
+	(MSG_RESTARTING_DOWNLOAD): Added %s.
+	(MSG_DOWNLOAD_ALREADY_COMPLETED): Updated.
+	
+	* src/PeerAbstractCommand.cc
+	(execute): MSG_DOWNLOAD_ABORTED -> MSG_TORRENT_DOWNLOAD_ABORTED
+	
+	* src/Request.h
+	(cookieBox): Made ShardHandle.
+	
+	* src/RequestGroup.h, src/RequestGroup.cc
+	(createNextCommandWithAdj): New function.
+	* src/FileAllocationCommand.cc
+	(executeInternal): Use createNextCommandWithAdj().
+	* src/CheckIntegrityCommand.cc
+	(executeInternal): Use createNextCommandWithAdj().
+
+	Added --load-cookies command-option.
+	* src/OptionHandlerFactory.cc
+	(createOptionHandlers): Added PREF_LOAD_COOKIES.
+	* src/CookieBox.h, src/CookieBox.cc: Rwritten using CookieParser.
+	Now aria2 can handle cookie's expiration date.
+	* src/Cookie.h (expires): Changed its type to time_t.
+	* src/main.cc: Added --load-cookies command-line option.
+	* src/prefs.h (PREF_LOAD_COOKIES): New definition.
+	* src/Util.h, src/Util.cc (httpGMT): New function.
+	* src/Request.cc (Request): Initialize cookieBox using
+	CookieBoxFactory.
+	* src/CookieBoxFactory.h, src/CookieBoxFactory.cc: New class.
+	* src/CookieParser.h, src/CookieParser.cc: New class.
+	
+	* src/main.cc: Chagned the default value of --metalink-servers to 5.
+
+	* src/HttpResponseCommand.cc
+	(handleOtherEncoding): Call RequestGroup::shouldCancelDownloadForSafety
+
 2007-06-09  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
 
 	Added -j command-line option.

+ 7 - 5
src/AbstractCommand.cc

@@ -106,14 +106,14 @@ bool AbstractCommand::execute() {
       return false;
     }
   } catch(FatalException* err) {
-    logger->error(MSG_DOWNLOAD_ABORTED, err, cuid);
+    logger->error(MSG_DOWNLOAD_ABORTED, err, cuid, req->getUrl().c_str());
     onAbort(err);
     delete(err);
     req->resetUrl();
     _requestGroup->getSegmentMan()->errors++;
     return true;    
   } catch(DlAbortEx* err) {
-    logger->error(MSG_DOWNLOAD_ABORTED, err, cuid);
+    logger->error(MSG_DOWNLOAD_ABORTED, err, cuid, req->getUrl().c_str());
     onAbort(err);
     delete(err);
     req->resetUrl();
@@ -121,20 +121,22 @@ bool AbstractCommand::execute() {
     tryReserved();
     return true;
   } catch(DlRetryEx* err) {
-    logger->error(MSG_RESTARTING_DOWNLOAD, err, cuid);
+    logger->info(MSG_RESTARTING_DOWNLOAD, err, cuid, req->getUrl().c_str());
     req->addTryCount();
     bool isAbort = e->option->getAsInt(PREF_MAX_TRIES) != 0 &&
       req->getTryCount() >= e->option->getAsInt(PREF_MAX_TRIES);
     if(isAbort) {
       onAbort(err);
     }
-    delete(err);
     if(isAbort) {
-      logger->error(MSG_MAX_TRY, cuid, req->getTryCount());
+      logger->info(MSG_MAX_TRY, cuid, req->getTryCount());
+      logger->error(MSG_DOWNLOAD_ABORTED, err, cuid, req->getUrl().c_str());
+      delete(err);
       _requestGroup->getSegmentMan()->errors++;
       tryReserved();
       return true;
     } else {
+      delete(err);
       return prepareForRetry(e->option->getAsInt(PREF_RETRY_WAIT));
     }
   }

+ 1 - 1
src/CheckIntegrityCommand.cc

@@ -69,7 +69,7 @@ bool CheckIntegrityCommand::executeInternal()
 	 _entry->getNextDownloadCommand()) {
 	_e->commands.push_back(_entry->popNextDownloadCommand());
       } else {
-	Commands commands = _requestGroup->createNextCommand(_e);
+	Commands commands = _requestGroup->createNextCommandWithAdj(_e, -1);
 	Command* command = InitiateConnectionCommandFactory::createInitiateConnectionCommand(cuid, _entry->getCurrentRequest(), _requestGroup, _e);
 	commands.push_front(command);
 	_e->addCommand(commands);

+ 48 - 0
src/Cookie.cc

@@ -0,0 +1,48 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "Cookie.h"
+#include "Util.h"
+
+bool Cookie::match(const string& host, const string& dir, time_t date, bool secure) const
+{
+  if((secure || !this->secure && !secure) &&
+     Util::endsWith(host, this->domain) &&
+     Util::startsWith(dir, this->path) &&
+     (this->onetime || date < this->expires)) {
+    return true;
+  } else {
+    return false;
+  }
+}

+ 98 - 0
src/Cookie.h

@@ -0,0 +1,98 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_COOKIE_H_
+#define _D_COOKIE_H_
+
+#include "common.h"
+
+class Cookie {
+public:
+  string name;
+  string value;
+  time_t expires;
+  string path;
+  string domain;
+  bool secure;
+  bool onetime; // if true, this cookie will expire when the user's session ends.
+public:
+  Cookie(const string& name,
+	 const string& value,
+	 time_t  expires,
+	 const string& path,
+	 const string& domain,
+	 bool secure):
+    name(name),
+    value(value),
+    expires(expires),
+    path(path),
+    domain(domain),
+    secure(secure),
+    onetime(false) {}
+
+  Cookie(const string& name,
+	 const string& value,
+	 const string& path,
+	 const string& domain,
+	 bool secure):
+    name(name),
+    value(value),
+    path(path),
+    domain(domain),
+    secure(secure),
+    onetime(true) {}
+
+  Cookie():expires(0), secure(false), onetime(true) {}
+
+  ~Cookie() {}
+  string toString() const {
+    return name+"="+value;
+  }
+  void clear() {
+    name = value = path = domain = "";
+    expires = 0;
+    secure = false;
+  }
+
+  bool good() const
+  {
+    return !name.empty();
+  }
+
+  bool match(const string& host, const string& dir, time_t date, bool secure) const;
+};
+
+typedef deque<Cookie> Cookies;
+
+#endif // _D_COOKIE_H_

+ 9 - 32
src/CookieBox.cc

@@ -34,6 +34,7 @@
 /* copyright --> */
 #include "CookieBox.h"
 #include "Util.h"
+#include "CookieParser.h"
 
 CookieBox::CookieBox() {}
 
@@ -44,46 +45,22 @@ void CookieBox::add(const Cookie& cookie) {
 }
 
 void CookieBox::add(const string& cookieStr) {
-  Cookie c;
-  parse(c, cookieStr);
-  cookies.push_back(c);
-}
-
-void CookieBox::setField(Cookie& cookie, const string& name, const string& value) const {
-  if(name.size() == string("secure").size() &&
-     strcasecmp(name.c_str(), "secure") == 0) {
-    cookie.secure = true;
-  } else if(name.size() == string("domain").size() && strcasecmp(name.c_str(), "domain") == 0) {
-    cookie.domain = value;
-  } else if(name.size() == string("path").size() && strcasecmp(name.c_str(), "path") == 0) {
-    cookie.path = value;
-  } else if(name.size() == string("expires").size() && strcasecmp(name.c_str(), "expires") == 0) {
-    cookie.expires = value;
-  } else {
-    cookie.name = name;
-    cookie.value = value;
+  Cookie c = CookieParser().parse(cookieStr);
+  if(c.good()) {
+    cookies.push_back(c);
   }
 }
 
-void CookieBox::parse(Cookie& cookie, const string& cookieStr) const {
-  cookie.clear();
-  Strings terms;
-  Util::slice(terms, cookieStr, ';', true);
-  for(Strings::iterator itr = terms.begin(); itr != terms.end(); itr++) {
-    pair<string, string> nv;
-    Util::split(nv, *itr, '=');
-    setField(cookie, nv.first, nv.second);
-  }
+void CookieBox::add(const Cookies& cookies)
+{
+  this->cookies.insert(this->cookies.end(), cookies.begin(), cookies.end());
 }
 
-Cookies CookieBox::criteriaFind(const string& host, const string& dir, bool secure) const {
+Cookies CookieBox::criteriaFind(const string& host, const string& dir, time_t date,  bool secure) const {
   Cookies result;
   for(Cookies::const_iterator itr = cookies.begin(); itr != cookies.end(); itr++) {
     const Cookie& c = *itr;
-    if((secure || !c.secure && !secure) &&
-       Util::endsWith(host, c.domain) &&
-       Util::startsWith(dir, c.path)) {
-      // TODO we currently ignore expire date.
+    if(c.match(host, dir, date, secure)) {
       result.push_back(c);
     }
   }

+ 5 - 30
src/CookieBox.h

@@ -36,46 +36,21 @@
 #define _D_COOKIE_BOX_H_
 
 #include "common.h"
-#include <string>
-#include <deque>
-
-using namespace std;
-
-class Cookie {
-public:
-  string name;
-  string value;
-  string expires;
-  string path;
-  string domain;
-  bool secure;
-public:
-  Cookie(const string& name, const string& value, const string& expires, const string& path, const string& domain, bool secure):name(name), value(value), expires(expires), path(path), domain(domain), secure(secure) {}
-  Cookie():secure(false) {}
-  ~Cookie() {}
-  string toString() const {
-    return name+"="+value;
-  }
-  void clear() {
-    name = value = expires = path = domain = "";
-    secure = false;
-  }
-};
-
-typedef deque<Cookie> Cookies;
+#include "Cookie.h"
 
 class CookieBox {
 private:
   Cookies cookies;
-  void setField(Cookie& cookie, const string& name, const string& value) const;
 public:
   CookieBox();
   ~CookieBox();
   void clear();
   void add(const Cookie& cookie);
   void add(const string& cookieStr);
-  void parse(Cookie& cookie, const string& cookieStr) const;
-  Cookies criteriaFind(const string& host, const string& dir, bool secure) const;
+  void add(const Cookies& cookies);
+  Cookies criteriaFind(const string& host, const string& dir, time_t date, bool secure) const;
 };
 
+typedef SharedHandle<CookieBox> CookieBoxHandle;
+
 #endif // _D_COOKIE_BOX_H_

+ 77 - 0
src/CookieBoxFactory.cc

@@ -0,0 +1,77 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "CookieBoxFactory.h"
+#include "CookieParser.h"
+#include "Util.h"
+
+CookieBoxHandle CookieBoxFactory::createNewInstance()
+{
+  CookieBoxHandle box = new CookieBox();
+  box->add(defaultCookies);
+  return box;
+}
+
+void CookieBoxFactory::loadDefaultCookie(istream& s)
+{
+  string line;
+  while(getline(s, line)) {
+    if(Util::startsWith(line, "#")) {
+      continue;
+    }
+    Cookie c = parseNsCookie(line);
+    if(c.good()) {
+      defaultCookies.push_back(c);
+    }
+  }
+}
+
+Cookie CookieBoxFactory::parseNsCookie(const string& nsCookieStr) const
+{
+  Strings vs;
+  Util::slice(vs, nsCookieStr, '\t', true);
+  Cookie c;
+  if(vs.size() < 6 ) {
+    return c;
+  }
+  c.domain = vs[0];
+  c.path = vs[2];
+  c.secure = vs[3] == "TRUE" ? true : false;
+  c.expires = strtol(vs[4].c_str(), NULL, 10);
+  c.name = vs[5];
+  if(vs.size() >= 7) {
+    c.value = vs[6];
+  }
+  return c;
+}

+ 66 - 0
src/CookieBoxFactory.h

@@ -0,0 +1,66 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_COOKIE_BOX_FACTORY_H_
+#define _D_COOKIE_BOX_FACTORY_H_
+
+#include "common.h"
+#include "CookieBox.h"
+#include <istream>
+
+class CookieBoxFactory {
+private:
+  Cookies defaultCookies;
+
+public:
+  CookieBoxFactory() {}
+
+  ~CookieBoxFactory() {}
+
+  CookieBoxHandle createNewInstance();
+
+  void loadDefaultCookie(istream& s);
+
+  Cookie parseNsCookie(const string& nsCookieStr) const;
+
+  const Cookies& getDefaultCookies() const
+  {
+    return defaultCookies;
+  }
+};
+
+typedef SharedHandle<CookieBoxFactory> CookieBoxFactoryHandle;
+typedef SingletonHolder<CookieBoxFactoryHandle> CookieBoxFactorySingletonHolder;
+
+#endif // _D_COOKIE_BOX_FACTORY_H_

+ 85 - 0
src/CookieParser.cc

@@ -0,0 +1,85 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#include "CookieParser.h"
+#include "Util.h"
+
+void CookieParser::setField(Cookie& cookie, const string& name, const string& value) const
+{
+  if(name.size() == string("secure").size() &&
+     strcasecmp(name.c_str(), "secure") == 0) {
+    cookie.secure = true;
+  } else if(name.size() == string("domain").size() && strcasecmp(name.c_str(), "domain") == 0) {
+    cookie.domain = value;
+  } else if(name.size() == string("path").size() && strcasecmp(name.c_str(), "path") == 0) {
+    cookie.path = value;
+  } else if(name.size() == string("expires").size() && strcasecmp(name.c_str(), "expires") == 0) {
+    cookie.expires = Util::httpGMT(value);
+    cookie.onetime = false;
+  } else {
+    cookie.name = name;
+    cookie.value = value;
+  }
+}
+
+Cookie CookieParser::parse(const string& cookieStr) const
+{
+  Cookie cookie;
+  Strings terms;
+  Util::slice(terms, Util::trim(cookieStr), ';', true);
+  for(Strings::iterator itr = terms.begin(); itr != terms.end(); itr++) {
+    pair<string, string> nv;
+    Util::split(nv, *itr, '=');
+    setField(cookie, nv.first, nv.second);
+  }
+  return cookie;
+}
+
+
+Cookies CookieParser::parse(istream& s) const
+{
+  Cookies cookies;
+  string line;
+  while(getline(s, line)) {
+    if(Util::trim(line) == "" || Util::startsWith(line, "#")) {
+      continue;
+    }
+    Cookie cookie = parse(line);
+    if(cookie.good()) {
+      cookies.push_back(cookie);
+    }
+  }
+  return cookies;
+}
+

+ 57 - 0
src/CookieParser.h

@@ -0,0 +1,57 @@
+/* <!-- copyright */
+/*
+ * aria2 - The high speed download utility
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL.  If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so.  If you
+ * do not wish to do so, delete this exception statement from your
+ * version.  If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+/* copyright --> */
+#ifndef _D_COOKIE_PARSER_H_
+#define _D_COOKIE_PARSER_H_
+
+#include "common.h"
+#include "Cookie.h"
+#include <istream>
+
+class CookieParser {
+private:
+  void setField(Cookie& cookie, const string& name, const string& value) const;
+public:
+  CookieParser() {}
+
+  ~CookieParser() {}
+
+  Cookie parse(const string& cookieStr) const;
+
+  Cookies parse(istream& s) const;
+};
+
+typedef SharedHandle<CookieParser> CookieParserHandle;
+
+#endif // _D_COOKIE_PARSER_H_

+ 1 - 1
src/FileAllocationCommand.cc

@@ -52,7 +52,7 @@ bool FileAllocationCommand::executeInternal()
        _fileAllocationEntry->getNextDownloadCommand()) {
       _e->commands.push_back(_fileAllocationEntry->popNextDownloadCommand());
     } else {
-      Commands commands = _requestGroup->createNextCommand(_e);
+      Commands commands = _requestGroup->createNextCommandWithAdj(_e, -1);
       Command* command = InitiateConnectionCommandFactory::createInitiateConnectionCommand(cuid, _fileAllocationEntry->getCurrentRequest(), _requestGroup, _e);
       
       commands.push_front(command);

+ 1 - 0
src/HttpRequest.cc

@@ -116,6 +116,7 @@ string HttpRequest::createRequest() const
   string cookiesValue;
   Cookies cookies = request->cookieBox->criteriaFind(getHost(),
 						     getDir(),
+						     time(0),
 						     getProtocol() == "https" ?
 						     true : false);
   for(Cookies::const_iterator itr = cookies.begin(); itr != cookies.end(); itr++) {

+ 1 - 3
src/HttpResponse.cc

@@ -86,9 +86,7 @@ void HttpResponse::retrieveCookie()
 {
   Strings v = httpHeader->get("Set-Cookie");
   for(Strings::const_iterator itr = v.begin(); itr != v.end(); itr++) {
-    Cookie c;
-    httpRequest->getRequest()->cookieBox->parse(c, *itr);
-    httpRequest->getRequest()->cookieBox->add(c);
+    httpRequest->getRequest()->cookieBox->add(*itr);
   }
 }
 

+ 3 - 2
src/HttpResponseCommand.cc

@@ -88,14 +88,14 @@ bool HttpResponseCommand::executeInternal()
     return prepareForRetry(0);
   }
   if(_requestGroup->getSegmentMan()->downloadStarted) {
-    // TODO validate totalsize
+    // validate totalsize
     _requestGroup->validateFilename(httpResponse->determinFilename());
     _requestGroup->validateTotalLength(httpResponse->getEntityLength());
 
     e->commands.push_back(createHttpDownloadCommand(httpResponse));
     return true;
   } else {
-    // TODO validate totalsize against hintTotalSize if it is provided.
+    // validate totalsize against hintTotalSize if it is provided.
     _requestGroup->validateFilenameByHint(httpResponse->determinFilename());
     _requestGroup->validateTotalLengthByHint(httpResponse->getEntityLength());
 
@@ -165,6 +165,7 @@ bool HttpResponseCommand::handleOtherEncoding(const HttpResponseHandle& httpResp
   // disable keep-alive
   req->setKeepAlive(false);
   segment = _requestGroup->getSegmentMan()->getSegment(cuid);	
+  _requestGroup->shouldCancelDownloadForSafety();
   _requestGroup->getSegmentMan()->diskWriter->initAndOpenFile(_requestGroup->getSegmentMan()->getFilePath());
   e->commands.push_back(createHttpDownloadCommand(httpResponse));
   return true;

+ 4 - 1
src/Makefile.am

@@ -100,7 +100,10 @@ SRCS =  Socket.h\
 	CheckIntegrityEntry.cc CheckIntegrityEntry.h\
 	CheckIntegrityMan.h\
 	ProgressAwareEntry.h\
-	RequestGroupEntry.cc RequestGroupEntry.h
+	RequestGroupEntry.cc RequestGroupEntry.h\
+	Cookie.cc Cookie.h\
+	CookieParser.cc CookieParser.h\
+	CookieBoxFactory.cc CookieBoxFactory.h
 #	debug_new.cpp
 
 if ENABLE_BITTORRENT

+ 17 - 9
src/Makefile.in

@@ -240,12 +240,14 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
 	IteratableChecksumValidator.cc IteratableChecksumValidator.h \
 	ChecksumCommand.cc ChecksumCommand.h CheckIntegrityEntry.cc \
 	CheckIntegrityEntry.h CheckIntegrityMan.h ProgressAwareEntry.h \
-	RequestGroupEntry.cc RequestGroupEntry.h MetaEntry.h Data.cc \
-	Data.h Dictionary.cc Dictionary.h List.cc List.h \
-	MetaFileUtil.cc MetaFileUtil.h MetaEntryVisitor.h \
-	ShaVisitor.cc ShaVisitor.h PeerConnection.cc PeerConnection.h \
-	PeerMessageUtil.cc PeerMessageUtil.h PeerAbstractCommand.cc \
-	PeerAbstractCommand.h PeerInitiateConnectionCommand.cc \
+	RequestGroupEntry.cc RequestGroupEntry.h Cookie.cc Cookie.h \
+	CookieParser.cc CookieParser.h CookieBoxFactory.cc \
+	CookieBoxFactory.h MetaEntry.h Data.cc Data.h Dictionary.cc \
+	Dictionary.h List.cc List.h MetaFileUtil.cc MetaFileUtil.h \
+	MetaEntryVisitor.h ShaVisitor.cc ShaVisitor.h \
+	PeerConnection.cc PeerConnection.h PeerMessageUtil.cc \
+	PeerMessageUtil.h PeerAbstractCommand.cc PeerAbstractCommand.h \
+	PeerInitiateConnectionCommand.cc \
 	PeerInitiateConnectionCommand.h PeerInteractionCommand.cc \
 	PeerInteractionCommand.h Peer.cc Peer.h \
 	TorrentDownloadEngine.cc TorrentDownloadEngine.h \
@@ -425,7 +427,9 @@ am__objects_3 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \
 	RealtimeCommand.$(OBJEXT) \
 	IteratableChecksumValidator.$(OBJEXT) \
 	ChecksumCommand.$(OBJEXT) CheckIntegrityEntry.$(OBJEXT) \
-	RequestGroupEntry.$(OBJEXT) $(am__objects_1) $(am__objects_2)
+	RequestGroupEntry.$(OBJEXT) Cookie.$(OBJEXT) \
+	CookieParser.$(OBJEXT) CookieBoxFactory.$(OBJEXT) \
+	$(am__objects_1) $(am__objects_2)
 am_libaria2c_a_OBJECTS = $(am__objects_3)
 libaria2c_a_OBJECTS = $(am_libaria2c_a_OBJECTS)
 am__installdirs = "$(DESTDIR)$(bindir)"
@@ -657,8 +661,9 @@ SRCS = Socket.h SocketCore.cc SocketCore.h Command.cc Command.h \
 	IteratableChecksumValidator.cc IteratableChecksumValidator.h \
 	ChecksumCommand.cc ChecksumCommand.h CheckIntegrityEntry.cc \
 	CheckIntegrityEntry.h CheckIntegrityMan.h ProgressAwareEntry.h \
-	RequestGroupEntry.cc RequestGroupEntry.h $(am__append_1) \
-	$(am__append_2)
+	RequestGroupEntry.cc RequestGroupEntry.h Cookie.cc Cookie.h \
+	CookieParser.cc CookieParser.h CookieBoxFactory.cc \
+	CookieBoxFactory.h $(am__append_1) $(am__append_2)
 noinst_LIBRARIES = libaria2c.a
 libaria2c_a_SOURCES = $(SRCS)
 aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\
@@ -786,7 +791,10 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CompactPeerListProcessor.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ConsoleDownloadEngine.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ConsoleFileAllocationMonitor.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Cookie.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CookieBox.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CookieBoxFactory.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CookieParser.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CopyDiskAdaptor.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Data.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultAuthResolver.Po@am__quote@

+ 1 - 0
src/OptionHandlerFactory.cc

@@ -92,6 +92,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
   handlers.push_back(new BooleanOptionHandler(PREF_NO_NETRC));
   handlers.push_back(new DefaultOptionHandler(PREF_INPUT_FILE));
   handlers.push_back(new NumberOptionHandler(PREF_MAX_CONCURRENT_DOWNLOADS, 1, 15));
+  handlers.push_back(new DefaultOptionHandler(PREF_LOAD_COOKIES));
 
   return handlers;
 }

+ 1 - 1
src/PeerAbstractCommand.cc

@@ -78,7 +78,7 @@ bool PeerAbstractCommand::execute() {
     }
     return executeInternal();
   } catch(RecoverableException* err) {
-    logger->debug(MSG_DOWNLOAD_ABORTED, err, cuid);
+    logger->debug(MSG_TORRENT_DOWNLOAD_ABORTED, err, cuid);
     logger->debug("CUID#%d - Peer %s:%d banned.",
 		  cuid, peer->ipaddr.c_str(), peer->port);
     onAbort(err);

+ 4 - 7
src/Request.cc

@@ -35,6 +35,7 @@
 #include "Request.h"
 #include "Util.h"
 #include "FeatureConfig.h"
+#include "CookieBoxFactory.h"
 
 const string Request::METHOD_GET = "get";
 
@@ -43,14 +44,10 @@ const string Request::METHOD_HEAD = "head";
 Request::Request():port(0), tryCount(0), keepAlive(true), method(METHOD_GET),
 		   _httpAuthResolver(0),
 		   _httpProxyAuthResolver(0),
-		   _ftpAuthResolver(0)
-{
-  cookieBox = new CookieBox();
-}
+		   _ftpAuthResolver(0),
+		   cookieBox(CookieBoxFactorySingletonHolder::instance()->createNewInstance()) {}
 
-Request::~Request() {
-  delete cookieBox;
-}
+Request::~Request() {}
 
 bool Request::setUrl(const string& url) {
   this->url = url;

+ 1 - 1
src/Request.h

@@ -80,7 +80,7 @@ private:
 
   bool parseUrl(const string& url);
 public:
-  CookieBox* cookieBox;
+  CookieBoxHandle cookieBox;
 public:
   Request();
   virtual ~Request();

+ 4 - 4
src/RequestGroup.cc

@@ -56,10 +56,10 @@ SegmentManHandle RequestGroup::initSegmentMan()
   return _segmentMan;
 }
 
-Commands RequestGroup::createNextCommand(DownloadEngine* e, const string& method)
+Commands RequestGroup::createNextCommandWithAdj(DownloadEngine* e, int32_t numAdj)
 {
-  int32_t numCommand = _numConcurrentCommand == 0 ? _uris.size() : _numConcurrentCommand;
-  return createNextCommand(e, numCommand, method);
+  int32_t numCommand = _numConcurrentCommand == 0 ? _uris.size() : _numConcurrentCommand+numAdj;
+  return createNextCommand(e, numCommand, "GET");
 }
 
 Commands RequestGroup::createNextCommand(DownloadEngine* e, int32_t numCommand, const string& method)
@@ -212,7 +212,7 @@ void RequestGroup::prepareForNextAction(int cuid, const RequestHandle& req, Down
     if(downloadCommand) {
       e->commands.push_back(downloadCommand);
     } else {
-      Commands commands = createNextCommand(e);
+      Commands commands = createNextCommandWithAdj(e, -1);
       Command* command = InitiateConnectionCommandFactory::createInitiateConnectionCommand(cuid, req, this, e);
       commands.push_front(command);
       e->addCommand(commands);

+ 1 - 1
src/RequestGroup.h

@@ -113,7 +113,7 @@ public:
     return _segmentMan;
   }
 
-  Commands createNextCommand(DownloadEngine* e, const string& method = "GET");
+  Commands createNextCommandWithAdj(DownloadEngine* e, int32_t numAdj);
 
   Commands createNextCommand(DownloadEngine* e, int32_t numCommand, const string& method = "GET");
   

+ 9 - 0
src/Util.cc

@@ -706,3 +706,12 @@ string Util::abbrevSize(int64_t size)
   } 
   return Util::llitos(size, true)+units[i];
 }
+
+time_t Util::httpGMT(const string& httpStdTime)
+{
+  struct tm tm;
+  memset(&tm, 0, sizeof(tm));
+  strptime(httpStdTime.c_str(), "%a, %Y-%m-%d %H:%M:%S GMT", &tm);
+  time_t thetime = timegm(&tm);
+  return thetime;
+}

+ 2 - 0
src/Util.h

@@ -150,6 +150,8 @@ public:
   static int64_t getRealSize(const string& sizeWithUnit);
 
   static string abbrevSize(int64_t size);
+
+  static time_t httpGMT(const string& httpTimeFormat);
 };
 
 #endif // _D_UTIL_H_

+ 24 - 4
src/main.cc

@@ -51,6 +51,7 @@
 #include "File.h"
 #include "CUIDCounter.h"
 #include "UriFileListParser.h"
+#include "CookieBoxFactory.h"
 #include <deque>
 #include <algorithm>
 #include <time.h>
@@ -211,6 +212,8 @@ void showUsage() {
 	    "                              URIs by Tab in a single line.") << endl;
   cout << _(" -j, --max-concurrent-downloads=N Set maximum number of concurrent downloads.\n"
 	    "                              Default: 5") << endl;
+  cout << _(" --load-cookies=FILE          Load cookies from FILE. The format of FILE is\n"
+	    "                              one used by Netscape and Mozilla.") << endl;
 #ifdef ENABLE_BITTORRENT
   cout << _(" -T, --torrent-file=TORRENT_FILE  The file path to .torrent file.") << endl;
   cout << _(" --follow-torrent=true|false  Setting this option to false prevents aria2 to\n"
@@ -243,9 +246,8 @@ void showUsage() {
 #ifdef ENABLE_METALINK
   cout << _(" -M, --metalink-file=METALINK_FILE The file path to .metalink file.") << endl;
   cout << _(" -C, --metalink-servers=NUM_SERVERS The number of servers to connect to\n"
-	    "                              simultaneously. If more than one connection per\n"
-	    "                              server is required, use -s option.\n"
-	    "                              Default: 15") << endl;
+	    "                              simultaneously.\n"
+	    "                              Default: 5") << endl;
   cout << _(" --metalink-version=VERSION   The version of file to download.") << endl;
   cout << _(" --metalink-language=LANGUAGE The language of file to download.") << endl;
   cout << _(" --metalink-os=OS             The operating system the file is targeted.") << endl;
@@ -319,7 +321,7 @@ int main(int argc, char* argv[]) {
   op->put(PREF_SEGMENT_SIZE, Util::itos(1024*1024));
   op->put(PREF_HTTP_KEEP_ALIVE, V_FALSE);
   op->put(PREF_LISTEN_PORT, "-1");
-  op->put(PREF_METALINK_SERVERS, "15");
+  op->put(PREF_METALINK_SERVERS, "5");
   op->put(PREF_FOLLOW_TORRENT,
 #ifdef ENABLE_BITTORRENT
 	  V_TRUE
@@ -401,6 +403,7 @@ int main(int argc, char* argv[]) {
       { "no-netrc", no_argument, 0, 'n' },
       { "input-file", required_argument, 0, 'i' },
       { "max-concurrent-downloads", required_argument, 0, 'j' },
+      { "load-cookies", required_argument, &lopt, 205 },
 #ifdef ENABLE_BITTORRENT
       { "torrent-file", required_argument, NULL, 'T' },
       { "listen-port", required_argument, &lopt, 15 },
@@ -531,6 +534,9 @@ int main(int argc, char* argv[]) {
       case 204:
 	cmdstream << PREF_REALTIME_CHUNK_CHECKSUM << "=" << optarg << "\n";
 	break;
+      case 205:
+	cmdstream << PREF_LOAD_COOKIES << "=" << optarg << "\n";
+	break;
       }
       break;
     }
@@ -682,6 +688,20 @@ int main(int argc, char* argv[]) {
 	requestFactory->setNetrc(netrc);
       }
     }
+
+    CookieBoxFactoryHandle cookieBoxFactory = new CookieBoxFactory();
+    CookieBoxFactorySingletonHolder::instance(cookieBoxFactory);
+    if(op->defined(PREF_LOAD_COOKIES)) {
+      File cookieFile(op->get(PREF_LOAD_COOKIES));
+      if(cookieFile.isFile()) {
+	ifstream in(op->get(PREF_LOAD_COOKIES).c_str());
+	CookieBoxFactorySingletonHolder::instance()->loadDefaultCookie(in);
+      } else {
+	logger->error("Failed to load cookies from %s", op->get(PREF_LOAD_COOKIES).c_str());
+	exit(EXIT_FAILURE);
+      }
+    }
+
     RequestFactorySingletonHolder::instance(requestFactory);
     CUIDCounterHandle cuidCounter = new CUIDCounter();
     CUIDCounterSingletonHolder::instance(cuidCounter);

+ 4 - 3
src/message.h

@@ -44,8 +44,9 @@
 #define MSG_REDIRECT _("CUID#%d - Redirecting to %s")
 #define MSG_SENDING_REQUEST _("CUID#%d - Requesting:\n%s")
 #define MSG_RECEIVE_RESPONSE _("CUID#%d - Response received:\n%s")
-#define MSG_DOWNLOAD_ABORTED _("CUID#%d - Download aborted.")
-#define MSG_RESTARTING_DOWNLOAD _("CUID#%d - Restarting the download.")
+#define MSG_DOWNLOAD_ABORTED _("CUID#%d - Download aborted. URI=%s")
+#define MSG_RESTARTING_DOWNLOAD _("CUID#%d - Restarting the download. URI=%s")
+#define MSG_TORRENT_DOWNLOAD_ABORTED _("CUID#%d - Download aborted.")
 #define MSG_MAX_TRY _("CUID#%d - %d times attempted, but no success. Download aborted.")
 #define MSG_UNREGISTER_CUID _("CUID#%d - Unregistering cuid from segmentManager.")
 #define MSG_SEND_PEER_MESSAGE "CUID#%d - To: %s:%d %s"
@@ -56,7 +57,7 @@
 #define MSG_GOT_NEW_PIECE _("CUID#%d - we got new piece. index=%d")
 #define MSG_GOT_WRONG_PIECE _("CUID#%d - we got wrong piece. index=%d")
 #define MSG_DOWNLOAD_NOT_COMPLETE _("CUID#%d - Download not complete: %s")
-#define MSG_DOWNLOAD_ALREADY_COMPLETED _("CUID#%d - Download already completed: %s")
+#define MSG_DOWNLOAD_ALREADY_COMPLETED _("CUID#%d - Download has already completed: %s")
 #define MSG_GOOD_CHECKSUM _("CUID#%d - Good checksum: %s")
 #define MSG_BAD_CHECKSUM _("CUID#%d - Bad checksum: %s")
 

+ 2 - 0
src/prefs.h

@@ -135,6 +135,8 @@
 #define PREF_HTTP_KEEP_ALIVE "http-keep-alive"
 // values: string
 #define PREF_USER_AGENT "user-agent"
+// value: string that your file system recognizes as a file name.
+#define PREF_LOAD_COOKIES "load-cookies"
 
 /** 
  * HTTP proxy related preferences

+ 5 - 0
test/AllTest.cc

@@ -1,3 +1,4 @@
+#include "CookieBoxFactory.h"
 #include <cppunit/CompilerOutputter.h>
 #include <cppunit/extensions/TestFactoryRegistry.h>
 #include <cppunit/ui/text/TestRunner.h>
@@ -9,6 +10,10 @@ int main(int argc, char* argv[]) {
 
   runner.setOutputter(new CppUnit::CompilerOutputter(&runner.result(), std::cerr));
   
+  // setup
+  CookieBoxFactoryHandle cookieBoxFactory = new CookieBoxFactory();
+  CookieBoxFactorySingletonHolder::instance(cookieBoxFactory);
+
   // Run the tests.
   bool successfull = runner.run();
 

+ 64 - 0
test/CookieBoxFactoryTest.cc

@@ -0,0 +1,64 @@
+#include "CookieBoxFactory.h"
+#include <fstream>
+#include <cppunit/extensions/HelperMacros.h>
+
+using namespace std;
+
+class CookieBoxFactoryTest:public CppUnit::TestFixture {
+
+  CPPUNIT_TEST_SUITE(CookieBoxFactoryTest);
+  CPPUNIT_TEST(testLoadDefaultCookie);
+  CPPUNIT_TEST(testCreateNewInstance);
+  CPPUNIT_TEST_SUITE_END();
+private:
+
+public:
+  void setUp() {
+  }
+
+  void testLoadDefaultCookie();
+  void testCreateNewInstance();
+};
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION( CookieBoxFactoryTest );
+
+void CookieBoxFactoryTest::testLoadDefaultCookie()
+{
+  ifstream f("nscookietest.txt");
+
+  CookieBoxFactory factory;
+
+  factory.loadDefaultCookie(f);
+
+  Cookies cookies = factory.getDefaultCookies();
+
+  CPPUNIT_ASSERT_EQUAL(4, (int32_t)cookies.size());
+
+  Cookie c = cookies[0];
+  CPPUNIT_ASSERT_EQUAL(string("JSESSIONID"), c.name);
+  CPPUNIT_ASSERT_EQUAL(string("123456789"), c.value);
+
+  c = cookies[1];
+  CPPUNIT_ASSERT_EQUAL(string("user"), c.name);
+  CPPUNIT_ASSERT_EQUAL(string("me"), c.value);
+
+  c = cookies[2];
+  CPPUNIT_ASSERT_EQUAL(string("passwd"), c.name);
+  CPPUNIT_ASSERT_EQUAL(string("secret"), c.value);
+
+  c = cookies[3];
+  CPPUNIT_ASSERT_EQUAL(string("novalue"), c.name);
+  CPPUNIT_ASSERT_EQUAL(string(""), c.value);
+}
+
+void CookieBoxFactoryTest::testCreateNewInstance()
+{
+  ifstream f("nscookietest.txt");
+  CookieBoxFactory factory;
+  factory.loadDefaultCookie(f);
+  CookieBoxHandle box = factory.createNewInstance();
+  Cookies cookies = box->criteriaFind("localhost", "/", 0, true);
+
+  CPPUNIT_ASSERT_EQUAL(4, (int32_t)cookies.size());
+}

+ 11 - 37
test/CookieBoxTest.cc

@@ -7,7 +7,6 @@ using namespace std;
 class CookieBoxTest:public CppUnit::TestFixture {
 
   CPPUNIT_TEST_SUITE(CookieBoxTest);
-  CPPUNIT_TEST(testParse);
   CPPUNIT_TEST(testCriteriaFind);
   CPPUNIT_TEST_SUITE_END();
 private:
@@ -16,44 +15,18 @@ public:
   void setUp() {
   }
 
-  void testParse();
   void testCriteriaFind();
 };
 
 
 CPPUNIT_TEST_SUITE_REGISTRATION( CookieBoxTest );
 
-void CookieBoxTest::testParse() {
-  CookieBox box;
-  string str = "JSESSIONID=123456789; expires=Sat, 16-02-2006 19:38:00 JST; path=/; domain=localhost; secure";
-  Cookie c;
-  box.parse(c, str);
-  CPPUNIT_ASSERT_EQUAL(string("JSESSIONID"), c.name);
-  CPPUNIT_ASSERT_EQUAL(string("123456789"), c.value);
-  CPPUNIT_ASSERT_EQUAL(string("Sat, 16-02-2006 19:38:00 JST"), c.expires);
-  
-  CPPUNIT_ASSERT_EQUAL(string("/"), c.path);
-  
-  CPPUNIT_ASSERT_EQUAL(string("localhost"), c.domain);
-  CPPUNIT_ASSERT_EQUAL(true, c.secure);
-
-  string str2 = "JSESSIONID=123456789";
-  box.parse(c, str2);
-  CPPUNIT_ASSERT_EQUAL(string("JSESSIONID"), c.name);
-  CPPUNIT_ASSERT_EQUAL(string("123456789"), c.value);
-  CPPUNIT_ASSERT_EQUAL(string(""), c.expires);
-  
-  CPPUNIT_ASSERT_EQUAL(string(""), c.path);
-  
-  CPPUNIT_ASSERT_EQUAL(string(""), c.domain);
-  CPPUNIT_ASSERT_EQUAL(false, c.secure);  
-}
-
 void CookieBoxTest::testCriteriaFind() {
-  Cookie c1("SESSIONID1", "1", "", "/downloads", "rednoah.com", false);
-  Cookie c2("SESSIONID2", "2", "", "/downloads", "rednoah.com", false);
-  Cookie c3("USER", "user", "", "/home", "aria.rednoah.com", false);
-  Cookie c4("PASS", "pass", "", "/downloads", "rednoah.com", true);
+  // 1181473200 = Sun Jun 10 11:00:00 2007 GMT
+  Cookie c1("SESSIONID1", "1", 1181473200, "/downloads", "rednoah.com", false);
+  Cookie c2("SESSIONID2", "2", 1181473200, "/downloads", "rednoah.com", false);
+  Cookie c3("USER", "user", "/home", "aria.rednoah.com", false);
+  Cookie c4("PASS", "pass", "/downloads", "rednoah.com", true);
 
   CookieBox box;
   box.add(c1);
@@ -61,14 +34,14 @@ void CookieBoxTest::testCriteriaFind() {
   box.add(c3);
   box.add(c4);
 
-  Cookies result1 = box.criteriaFind("rednoah.com", "/downloads", false);
+  Cookies result1 = box.criteriaFind("rednoah.com", "/downloads", 1181473100, false);
   CPPUNIT_ASSERT_EQUAL(2, (int)result1.size());
   Cookies::iterator itr = result1.begin();
   CPPUNIT_ASSERT_EQUAL(string("SESSIONID1=1"), (*itr).toString());
   itr++;
   CPPUNIT_ASSERT_EQUAL(string("SESSIONID2=2"), (*itr).toString());
 
-  result1 = box.criteriaFind("rednoah.com", "/downloads", true);
+  result1 = box.criteriaFind("rednoah.com", "/downloads", 1181473100, true);
   CPPUNIT_ASSERT_EQUAL(3, (int)result1.size());
   itr = result1.begin();
   CPPUNIT_ASSERT_EQUAL(string("SESSIONID1=1"), (*itr).toString());
@@ -77,14 +50,15 @@ void CookieBoxTest::testCriteriaFind() {
   itr++;
   CPPUNIT_ASSERT_EQUAL(string("PASS=pass"), (*itr).toString());
 
-  result1 = box.criteriaFind("aria.rednoah.com", "/", false);
+  result1 = box.criteriaFind("aria.rednoah.com", "/", 1181473100, false);
   CPPUNIT_ASSERT_EQUAL(0, (int)result1.size());
 
-  result1 = box.criteriaFind("aria.rednoah.com", "/home", false);
+  result1 = box.criteriaFind("aria.rednoah.com", "/home", 1181473100, false);
   CPPUNIT_ASSERT_EQUAL(1, (int)result1.size());
   itr = result1.begin();
   CPPUNIT_ASSERT_EQUAL(string("USER=user"), (*itr).toString());
   
-
+  result1 = box.criteriaFind("rednoah.com", "/downloads", 1181473200, false);
+  CPPUNIT_ASSERT_EQUAL(0, (int)result1.size());
 }
 

+ 75 - 0
test/CookieParserTest.cc

@@ -0,0 +1,75 @@
+#include "CookieParser.h"
+#include <fstream>
+#include <cppunit/extensions/HelperMacros.h>
+
+using namespace std;
+
+class CookieParserTest:public CppUnit::TestFixture {
+
+  CPPUNIT_TEST_SUITE(CookieParserTest);
+  CPPUNIT_TEST(testParse);
+  CPPUNIT_TEST(testParse_file);
+  CPPUNIT_TEST_SUITE_END();
+private:
+
+public:
+  void setUp() {
+  }
+
+  void testParse();
+  
+  void testParse_file();
+};
+
+
+CPPUNIT_TEST_SUITE_REGISTRATION( CookieParserTest );
+
+void CookieParserTest::testParse()
+{
+  string str = "JSESSIONID=123456789; expires=Sun, 2007-06-10 11:00:00 GMT; path=/; domain=localhost; secure";
+  Cookie c = CookieParser().parse(str);
+  CPPUNIT_ASSERT(c.good());
+  CPPUNIT_ASSERT_EQUAL(string("JSESSIONID"), c.name);
+  CPPUNIT_ASSERT_EQUAL(string("123456789"), c.value);
+  CPPUNIT_ASSERT_EQUAL((time_t)1181473200, c.expires);  
+  CPPUNIT_ASSERT_EQUAL(string("/"), c.path);
+  CPPUNIT_ASSERT_EQUAL(string("localhost"), c.domain);
+  CPPUNIT_ASSERT_EQUAL(true, c.secure);
+  CPPUNIT_ASSERT_EQUAL(false, c.onetime);
+
+  string str2 = "JSESSIONID=123456789";
+  c = CookieParser().parse(str2);
+  CPPUNIT_ASSERT(c.good());
+  CPPUNIT_ASSERT_EQUAL(string("JSESSIONID"), c.name);
+  CPPUNIT_ASSERT_EQUAL(string("123456789"), c.value);
+  CPPUNIT_ASSERT_EQUAL((time_t)0, c.expires);
+  CPPUNIT_ASSERT_EQUAL(string(""), c.path);
+  CPPUNIT_ASSERT_EQUAL(string(""), c.domain);
+  CPPUNIT_ASSERT_EQUAL(false, c.secure);
+  CPPUNIT_ASSERT_EQUAL(true, c.onetime);
+
+  string str3 = "";
+  c = CookieParser().parse(str3);
+  CPPUNIT_ASSERT(!c.good());
+}
+
+void CookieParserTest::testParse_file()
+{
+  ifstream f("cookietest.txt");
+
+  Cookies cookies = CookieParser().parse(f);
+
+  CPPUNIT_ASSERT_EQUAL(3, (int32_t)cookies.size());
+
+  Cookie c = cookies[0];
+  CPPUNIT_ASSERT_EQUAL(string("JSESSIONID"), c.name);
+  CPPUNIT_ASSERT_EQUAL(string("123456789"), c.value);
+
+  c = cookies[1];
+  CPPUNIT_ASSERT_EQUAL(string("user"), c.name);
+  CPPUNIT_ASSERT_EQUAL(string("me"), c.value);
+
+  c = cookies[2];
+  CPPUNIT_ASSERT_EQUAL(string("passwd"), c.name);
+  CPPUNIT_ASSERT_EQUAL(string("secret"), c.value);
+}

+ 4 - 4
test/HttpRequestTest.cc

@@ -317,10 +317,10 @@ void HttpRequestTest::testCreateRequest_with_cookie()
   request->setUrl("http://localhost/archives/aria2-1.0.0.tar.bz2");
   SegmentHandle segment = new Segment();
 
-  Cookie cookie1("name1", "value1", "2007/1/1", "/archives", "localhost", false);
-  Cookie cookie2("name2", "value2", "2007/1/1", "/archives/download", "localhost", false);
-  Cookie cookie3("name3", "value3", "2007/1/1", "/archives/download", "tt.localhost", false);
-  Cookie cookie4("name4", "value4", "2007/1/1", "/archives/download", "tt.localhost", true);
+  Cookie cookie1("name1", "value1", 1181473200, "/archives", "localhost", false);
+  Cookie cookie2("name2", "value2", 1181473200, "/archives/download", "localhost", false);
+  Cookie cookie3("name3", "value3", 1181473200, "/archives/download", "tt.localhost", false);
+  Cookie cookie4("name4", "value4", 1181473200, "/archives/download", "tt.localhost", true);
 
   request->cookieBox->add(cookie1);
   request->cookieBox->add(cookie2);

+ 5 - 3
test/Makefile.am

@@ -1,6 +1,11 @@
 TESTS = aria2c
 check_PROGRAMS = $(TESTS)
 aria2c_SOURCES = AllTest.cc\
+	CookieBoxTest.cc\
+	RequestTest.cc\
+	CookieParserTest.cc\
+	HttpRequestTest.cc\
+	CookieBoxFactoryTest.cc\
 	ByteArrayDiskWriterTest.cc\
 	RequestGroupManTest.cc\
 	IteratableChecksumValidatorTest.cc\
@@ -11,8 +16,6 @@ aria2c_SOURCES = AllTest.cc\
 	RequestFactoryTest.cc\
 	NetrcAuthResolverTest.cc\
 	DefaultAuthResolverTest.cc\
-	RequestTest.cc\
-	HttpRequestTest.cc\
 	UtilTest.cc\
 	OptionHandlerTest.cc\
 	SegmentManTest.cc\
@@ -27,7 +30,6 @@ aria2c_SOURCES = AllTest.cc\
 	FileTest.cc\
 	OptionTest.cc\
 	Base64Test.cc\
-	CookieBoxTest.cc\
 	DataTest.cc\
 	DictionaryTest.cc\
 	ListTest.cc\

+ 12 - 8
test/Makefile.in

@@ -57,7 +57,9 @@ mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
 CONFIG_HEADER = $(top_builddir)/config.h
 CONFIG_CLEAN_FILES =
 am__EXEEXT_1 = aria2c$(EXEEXT)
-am_aria2c_OBJECTS = AllTest.$(OBJEXT) \
+am_aria2c_OBJECTS = AllTest.$(OBJEXT) CookieBoxTest.$(OBJEXT) \
+	RequestTest.$(OBJEXT) CookieParserTest.$(OBJEXT) \
+	HttpRequestTest.$(OBJEXT) CookieBoxFactoryTest.$(OBJEXT) \
 	ByteArrayDiskWriterTest.$(OBJEXT) \
 	RequestGroupManTest.$(OBJEXT) \
 	IteratableChecksumValidatorTest.$(OBJEXT) \
@@ -65,16 +67,14 @@ am_aria2c_OBJECTS = AllTest.$(OBJEXT) \
 	UriFileListParserTest.$(OBJEXT) PeerTest.$(OBJEXT) \
 	DefaultPeerStorageTest.$(OBJEXT) RequestFactoryTest.$(OBJEXT) \
 	NetrcAuthResolverTest.$(OBJEXT) \
-	DefaultAuthResolverTest.$(OBJEXT) RequestTest.$(OBJEXT) \
-	HttpRequestTest.$(OBJEXT) UtilTest.$(OBJEXT) \
+	DefaultAuthResolverTest.$(OBJEXT) UtilTest.$(OBJEXT) \
 	OptionHandlerTest.$(OBJEXT) SegmentManTest.$(OBJEXT) \
 	BitfieldManTest.$(OBJEXT) GlowFileAllocatorTest.$(OBJEXT) \
 	NetrcTest.$(OBJEXT) SingletonHolderTest.$(OBJEXT) \
 	HttpHeaderTest.$(OBJEXT) HttpResponseTest.$(OBJEXT) \
 	SharedHandleTest.$(OBJEXT) ChunkedEncodingTest.$(OBJEXT) \
 	FileTest.$(OBJEXT) OptionTest.$(OBJEXT) Base64Test.$(OBJEXT) \
-	CookieBoxTest.$(OBJEXT) DataTest.$(OBJEXT) \
-	DictionaryTest.$(OBJEXT) ListTest.$(OBJEXT) \
+	DataTest.$(OBJEXT) DictionaryTest.$(OBJEXT) ListTest.$(OBJEXT) \
 	MetaFileUtilTest.$(OBJEXT) ShaVisitorTest.$(OBJEXT) \
 	PeerMessageUtilTest.$(OBJEXT) DefaultDiskWriterTest.$(OBJEXT) \
 	MultiDiskAdaptorTest.$(OBJEXT) \
@@ -267,6 +267,11 @@ sysconfdir = @sysconfdir@
 target_alias = @target_alias@
 TESTS = aria2c
 aria2c_SOURCES = AllTest.cc\
+	CookieBoxTest.cc\
+	RequestTest.cc\
+	CookieParserTest.cc\
+	HttpRequestTest.cc\
+	CookieBoxFactoryTest.cc\
 	ByteArrayDiskWriterTest.cc\
 	RequestGroupManTest.cc\
 	IteratableChecksumValidatorTest.cc\
@@ -277,8 +282,6 @@ aria2c_SOURCES = AllTest.cc\
 	RequestFactoryTest.cc\
 	NetrcAuthResolverTest.cc\
 	DefaultAuthResolverTest.cc\
-	RequestTest.cc\
-	HttpRequestTest.cc\
 	UtilTest.cc\
 	OptionHandlerTest.cc\
 	SegmentManTest.cc\
@@ -293,7 +296,6 @@ aria2c_SOURCES = AllTest.cc\
 	FileTest.cc\
 	OptionTest.cc\
 	Base64Test.cc\
-	CookieBoxTest.cc\
 	DataTest.cc\
 	DictionaryTest.cc\
 	ListTest.cc\
@@ -430,7 +432,9 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ChunkChecksumValidatorTest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ChunkedEncodingTest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ConsoleFileAllocationMonitorTest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CookieBoxFactoryTest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CookieBoxTest.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CookieParserTest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DataTest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultAuthResolverTest.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DefaultBtAnnounceTest.Po@am__quote@

+ 6 - 0
test/cookietest.txt

@@ -0,0 +1,6 @@
+JSESSIONID=123456789; expires=Sun, 2007-06-10 11:00:00 GMT; path=/; domain=localhost; secure
+# name=this is a omment line;
+
+user=me;
+
+passwd=secret

+ 7 - 0
test/nscookietest.txt

@@ -0,0 +1,7 @@
+# name=this is a omment line;
+localhost	FALSE	/	TRUE	1181473200	JSESSIONID	123456789
+
+localhost	FALSE	/	FALSE	1181473200	user	me
+
+localhost	FALSE	/	FALSE	1181473200	passwd	secret
+localhost	FALSE	/	FALSE	1181473200	novalue