Преглед изворни кода

2006-08-03 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>

	* src/Option.h
	(getAsBool): New function.
	* src/Option.cc
	(prefs.h): Included.
	(defined): 0-length value is now recognized as undefined.
	(getAsInt): Rewritten.
	(getAsLLInt): Rewritten.
	(getAsBool): New function.
	
	* src/FeatureConfig.h: Rewritten.
	* src/FeatureConfig.cc: Rewritten.

	* src/prefs.h
	(PREF_STDOUT_LOG): New definition.
	(PREF_LOG): New definition.
	(PREF_DIR): New definition.
	(PREF_OUT): New definition.
	(PREF_SPLIT): New definition.
	(PREF_DAEMON): New definition.
	(PREF_REFERER): New definition.
	(PREF_TORRENT_FILE): New definition.
	(PREF_LISTEN_PORT): New definition.
	(PREF_METALINK_FILE): New definition.
	(PREF_METALINK_VERSION): New definition.
	(PREF_METALINK_LANGUAGE): New definition.
	(PREF_METALINK_OS): New definition.
	(PREF_METALINK_SERVERS): New definition.

	* src/main.cc
	(main): Following command-line parameters are now put into 
Option
	class: stdoutLog, logfile, dir, ufilename, split, daemonMode,
	referer, torrentFile, metalinkFile, listenPort, metalinkVersion,
	metalinkLanguage, metalinkOs, metalinkServers
	To fix the bug that aria2 can not handle http response header 
properly.
	
	* src/HttpHeader.cc
	(put): Made name lowercased.
	(defined): Made name lowercased.
	(getFirst): Made name lowercased.
	(get): Made name lowercased.
	(getFirstAsInt): Rewritten.
	(getFirstAsLLInt): Rewritten.
Tatsuhiro Tsujikawa пре 19 година
родитељ
комит
9251b47f6c
11 измењених фајлова са 280 додато и 145 уклоњено
  1. 45 0
      ChangeLog
  2. 3 1
      TODO
  3. 49 22
      src/FeatureConfig.cc
  4. 41 29
      src/FeatureConfig.h
  5. 9 13
      src/HttpHeader.cc
  6. 16 6
      src/Option.cc
  7. 1 0
      src/Option.h
  8. 2 2
      src/Request.cc
  9. 65 63
      src/main.cc
  10. 32 0
      src/prefs.h
  11. 17 9
      test/FeatureConfigTest.cc

+ 45 - 0
ChangeLog

@@ -1,3 +1,48 @@
+2006-08-03  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
+
+	* src/Option.h
+	(getAsBool): New function.
+	* src/Option.cc
+	(prefs.h): Included.
+	(defined): 0-length value is now recognized as undefined.
+	(getAsInt): Rewritten.
+	(getAsLLInt): Rewritten.
+	(getAsBool): New function.
+	
+	* src/FeatureConfig.h: Rewritten.
+	* src/FeatureConfig.cc: Rewritten.
+
+	* src/prefs.h
+	(PREF_STDOUT_LOG): New definition.
+	(PREF_LOG): New definition.
+	(PREF_DIR): New definition.
+	(PREF_OUT): New definition.
+	(PREF_SPLIT): New definition.
+	(PREF_DAEMON): New definition.
+	(PREF_REFERER): New definition.
+	(PREF_TORRENT_FILE): New definition.
+	(PREF_LISTEN_PORT): New definition.
+	(PREF_METALINK_FILE): New definition.
+	(PREF_METALINK_VERSION): New definition.
+	(PREF_METALINK_LANGUAGE): New definition.
+	(PREF_METALINK_OS): New definition.
+	(PREF_METALINK_SERVERS): New definition.
+
+	* src/main.cc
+	(main): Following command-line parameters are now put into Option
+	class: stdoutLog, logfile, dir, ufilename, split, daemonMode,
+	referer, torrentFile, metalinkFile, listenPort, metalinkVersion,
+	metalinkLanguage, metalinkOs, metalinkServers
+	To fix the bug that aria2 can not handle http response header properly.
+	
+	* src/HttpHeader.cc
+	(put): Made name lowercased.
+	(defined): Made name lowercased.
+	(getFirst): Made name lowercased.
+	(get): Made name lowercased.
+	(getFirstAsInt): Rewritten.
+	(getFirstAsLLInt): Rewritten.
+
 2006-07-30  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
 
 	* src/TorrentMan.h:

+ 3 - 1
TODO

@@ -12,4 +12,6 @@
 * Query resource by location
 * Log version
 * List available os, version, etc for metalink
-* Performance Profiling
+* bittorrent in metalink
+* rename Time to something appropriate
+* ipv6(RFC2428 for ftp)

+ 49 - 22
src/FeatureConfig.cc

@@ -21,36 +21,63 @@
 /* copyright --> */
 #include "FeatureConfig.h"
 
-string FeatureConfig::FEATURE_HTTP = "http";
-string FeatureConfig::FEATURE_HTTPS = "https";
-string FeatureConfig::FEATURE_FTP = "ftp";
-string FeatureConfig::FEATURE_BITTORRENT = "bittorrent";
-string FeatureConfig::FEATURE_METALINK = "metalink";
+FeatureConfig* FeatureConfig::featureConfig = 0;
 
-static ProtocolPortMap::value_type defaultPortsArray[] = {
-  ProtocolPortMap::value_type(FeatureConfig::FEATURE_HTTP, 80),
-  ProtocolPortMap::value_type(FeatureConfig::FEATURE_HTTPS, 443),
-  ProtocolPortMap::value_type(FeatureConfig::FEATURE_FTP, 21),
-};
+#define FEATURE_HTTP "http"
+#define FEATURE_HTTPS "https"
+#define FEATURE_FTP "ftp"
+#define FEATURE_BITTORRENT "bittorrent"
+#define FEATURE_METALINK "metalink"
+#define FEATURE_MESSAGE_DIGEST "message digest"
 
-ProtocolPortMap FeatureConfig::defaultPorts(&defaultPortsArray[0],
-					     &defaultPortsArray[3]);
+FeatureConfig::FeatureConfig() {
+  static PortMap::value_type portArray[] = {
+    PortMap::value_type("http", 80),
+    PortMap::value_type("https", 443),
+    PortMap::value_type("ftp", 21),
+  };
+  int portArraySize = sizeof(portArray)/sizeof(PortMap::value_type);
+  defaultPorts.insert(&portArray[0],
+		      &portArray[portArraySize]);
 
-static SupportedFeatureMap::value_type supportedFeaturesArray[] = {
-  SupportedFeatureMap::value_type(FeatureConfig::FEATURE_HTTP, true),
+  static FeatureMap::value_type featureArray[] = {
+    FeatureMap::value_type(FEATURE_HTTP, true),
+    FeatureMap::value_type(FEATURE_HTTPS,
 #ifdef ENABLE_SSL
-  SupportedFeatureMap::value_type(FeatureConfig::FEATURE_HTTPS, true),
+			   true
+#else
+			   false
 #endif // ENABLE_SSL
-  SupportedFeatureMap::value_type(FeatureConfig::FEATURE_FTP, true),
+			   ),
+    FeatureMap::value_type(FEATURE_FTP, true),
+    FeatureMap::value_type(FEATURE_BITTORRENT,
 #ifdef ENABLE_BITTORRENT
-  SupportedFeatureMap::value_type(FeatureConfig::FEATURE_BITTORRENT, true),
+			   true
+#else
+			   false
 #endif // ENABLE_BITTORRENT
+			   ),
+    FeatureMap::value_type(FEATURE_METALINK,
 #ifdef ENABLE_METALINK
-  SupportedFeatureMap::value_type(FeatureConfig::FEATURE_METALINK, true),
+			   true
+#else
+			   false
 #endif // ENABLE_METALINK
-};
+			   ),
+    FeatureMap::value_type(FEATURE_MESSAGE_DIGEST,
+#ifdef ENABLE_MESSAGE_DIGEST
+			   true
+#else
+			   false
+#endif // ENABLE_MESSAGE_DIGEST
+			   ),
+  };
 
-SupportedFeatureMap
-FeatureConfig::supportedFeatures(&supportedFeaturesArray[0],
-				 &supportedFeaturesArray[sizeof(supportedFeaturesArray)/sizeof(SupportedFeatureMap::value_type)]);
+  int featureArraySize = sizeof(featureArray)/sizeof(FeatureMap::value_type);
+  supportedFeatures.insert(&featureArray[0],
+			   &featureArray[featureArraySize]);
 
+  for(int i = 0; i < featureArraySize; i++) {
+    features.push_back(featureArray[i].first);
+  }
+}

+ 41 - 29
src/FeatureConfig.h

@@ -25,48 +25,60 @@
 #include "common.h"
 #include <map>
 
-typedef map<string, int> ProtocolPortMap;
-typedef map<string, bool> SupportedFeatureMap;
+typedef map<string, int> PortMap;
+typedef map<string, bool> FeatureMap;
 
 class FeatureConfig {
 private:
-  static ProtocolPortMap defaultPorts;
-  static SupportedFeatureMap supportedFeatures;
+  static FeatureConfig* featureConfig;
+
+  PortMap defaultPorts;
+  FeatureMap supportedFeatures;
+  Strings features;
+
+  FeatureConfig();
+  ~FeatureConfig() {}
 public:
-  static string FEATURE_HTTP;
-  static string FEATURE_HTTPS;
-  static string FEATURE_FTP;
-  static string FEATURE_BITTORRENT;
-  static string FEATURE_METALINK;
+  static FeatureConfig* getInstance() {
+    if(!featureConfig) {
+      featureConfig = new FeatureConfig();
+    }
+    return featureConfig;
+  }
 
-  static int getDefaultPort(const string& protocol) {
-    if(defaultPorts.count(protocol)) {
-      return defaultPorts[protocol];
-    } else {
+  static void release() {
+    delete featureConfig;
+    featureConfig = 0;
+  }
+
+  int getDefaultPort(const string& protocol) const {
+    PortMap::const_iterator itr = defaultPorts.find(protocol);
+    if(itr == defaultPorts.end()) {
       return 0;
+    } else {
+      return itr->second;
     }
   }
 
-  static bool isSupported(const string& protocol) {
-    if(supportedFeatures.count(protocol)) {
-      return supportedFeatures[protocol];
-    } else {
+  bool isSupported(const string& feature) const {
+    FeatureMap::const_iterator itr = supportedFeatures.find(feature);
+    if(itr == supportedFeatures.end()) {
       return false;
+    } else {
+      return itr->second;
     }
   }
-  
-  static string getConfigurationSummary() {
-    string protos[] = {
-      FEATURE_HTTP,
-      FEATURE_HTTPS,
-      FEATURE_FTP,
-      FEATURE_BITTORRENT,
-      FEATURE_METALINK
-    };
+
+  const Strings& getFeatures() const {
+    return features;
+  }
+
+  string getConfigurationSummary() const {
     string summary;
-    for(int i = 0; i < (int)(sizeof(protos)/sizeof(string)); i++) {
-      summary += protos[i];
-      if(isSupported(protos[i])) {
+    for(Strings::const_iterator itr = features.begin();
+	itr != features.end(); itr++) {
+      summary += *itr;
+      if(isSupported(*itr)) {
 	summary += ": yes";
       } else {
 	summary += ": no";

+ 9 - 13
src/HttpHeader.cc

@@ -20,18 +20,19 @@
  */
 /* copyright --> */
 #include "HttpHeader.h"
+#include "Util.h"
 
 void HttpHeader::put(const string& name, const string& value) {
-  multimap<string, string>::value_type vt(name, value);
+  multimap<string, string>::value_type vt(Util::toLower(name), value);
   table.insert(vt);
 }
 
 bool HttpHeader::defined(const string& name) const {
-  return table.count(name) == 1;
+  return table.count(Util::toLower(name)) >= 1;
 }
 
 string HttpHeader::getFirst(const string& name) const {
-  multimap<string, string>::const_iterator itr = table.find(name);
+  multimap<string, string>::const_iterator itr = table.find(Util::toLower(name));
   if(itr == table.end()) {
     return "";
   } else {
@@ -41,26 +42,21 @@ string HttpHeader::getFirst(const string& name) const {
 
 Strings HttpHeader::get(const string& name) const {
   Strings v;
-  for(multimap<string, string>::const_iterator itr = table.find(name); itr != table.end(); itr++) {
+  for(multimap<string, string>::const_iterator itr = table.find(Util::toLower(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);
-  }
+  return (int)getFirstAsLLInt(name);
 }
 
 long long int HttpHeader::getFirstAsLLInt(const string& name) const {
-  multimap<string, string>::const_iterator itr = table.find(name);
-  if(itr == table.end()) {
+  string value = getFirst(name);
+  if(value == "") {
     return 0;
   } else {
-    return strtoll((*itr).second.c_str(), NULL, 10);
+    return strtoll(value.c_str(), NULL, 10);
   }
 }

+ 16 - 6
src/Option.cc

@@ -20,6 +20,7 @@
  */
 /* copyright --> */
 #include "Option.h"
+#include "prefs.h"
 
 Option::Option() {}
 
@@ -43,19 +44,28 @@ string Option::get(const string& name) const {
 }
 
 int Option::getAsInt(const string& name) const {
-  map<string, string>::const_iterator itr = table.find(name);
-  if(itr == table.end()) {
+  string value = get(name);
+  if(value == "") {
     return 0;
   } else {
-    return (int)strtol((*itr).second.c_str(), NULL, 10);
+    return (int)strtol(value.c_str(), NULL, 10);
   }
 }
 
 long long int Option::getAsLLInt(const string& name) const {
-  map<string, string>::const_iterator itr = table.find(name);
-  if(itr == table.end()) {
+  string value = get(name);
+  if(value == "") {
     return 0;
   } else {
-    return (int)strtoll((*itr).second.c_str(), NULL, 10);
+    return strtoll(value.c_str(), NULL, 10);
+  }
+}
+
+bool Option::getAsBool(const string& name) const {
+  string value = get(name);
+  if(value == V_TRUE) {
+    return true;
+  } else {
+    return false;
   }
 }

+ 1 - 0
src/Option.h

@@ -40,6 +40,7 @@ public:
   string get(const string& name) const;
   int getAsInt(const string& name) const;
   long long int getAsLLInt(const string& name) const;
+  bool getAsBool(const string& name) const;
 };
 
 #endif // _D_OPTION_H_

+ 2 - 2
src/Request.cc

@@ -54,7 +54,7 @@ bool Request::parseUrl(const string& url) {
   string tempUrl;
   string::size_type sharpIndex = url.find("#");
   if(sharpIndex != string::npos) {
-    if(FeatureConfig::isSupported(FeatureConfig::FEATURE_METALINK) &&
+    if(FeatureConfig::getInstance()->isSupported("metalink") &&
        url.find(METALINK_MARK) == sharpIndex) {
       tempUrl = url.substr(sharpIndex+strlen(METALINK_MARK));
     } else {
@@ -82,7 +82,7 @@ bool Request::parseUrl(const string& url) {
   if(hp == string::npos) return false;
   protocol = tempUrl.substr(0, hp);
   int defPort;
-  if((defPort = FeatureConfig::getDefaultPort(protocol)) == 0) {
+  if((defPort = FeatureConfig::getInstance()->getDefaultPort(protocol)) == 0) {
     return false;
   }
   hp += 3;

+ 65 - 63
src/main.cc

@@ -132,7 +132,7 @@ void showVersion() {
   cout << "Copyright (C) 2006 Tatsuhiro Tsujikawa" << endl;
   cout << endl;
   cout << "**Configuration**" << endl;
-  cout << FeatureConfig::getConfigurationSummary();
+  cout << FeatureConfig::getInstance()->getConfigurationSummary();
   cout << endl;
   cout <<
     _("This program is free software; you can redistribute it and/or modify\n"
@@ -291,8 +291,6 @@ void showUsage() {
 bool normalDownload(const Requests& requests,
 		    const Requests& reserved,
 		    Option* op,
-		    const string& dir,
-		    const string& ufilename,
 		    string& downloadedFilename) {
   setSignalHander(SIGINT, handler, 0);
   setSignalHander(SIGTERM, handler, 0);
@@ -301,8 +299,8 @@ bool normalDownload(const Requests& requests,
   e->option = op;
   e->segmentMan = new SegmentMan();
   e->segmentMan->diskWriter = new DefaultDiskWriter();
-  e->segmentMan->dir = dir;
-  e->segmentMan->ufilename = ufilename;
+  e->segmentMan->dir = op->get(PREF_DIR);
+  e->segmentMan->ufilename = op->get(PREF_OUT);
   e->segmentMan->option = op;
   e->segmentMan->splitter = new SplitSlowestSegmentSplitter();
   e->segmentMan->splitter->setMinSegmentSize(op->getAsLLInt(PREF_MIN_SEGMENT_SIZE));
@@ -345,20 +343,6 @@ int main(int argc, char* argv[]) {
   bindtextdomain (PACKAGE, LOCALEDIR);
   textdomain (PACKAGE);
 #endif // ENABLE_NLS
-  bool stdoutLog = false;
-  string logfile;
-  string dir = ".";
-  string ufilename;
-  int split = 1;
-  bool daemonMode = false;
-  string referer;
-  string torrentFile;
-  string metalinkFile;
-  int listenPort = -1;
-  string metalinkVersion;
-  string metalinkLanguage;
-  string metalinkOs;
-  int metalinkServers = 15;
   Integers selectFileIndexes;
 #ifdef ENABLE_BITTORRENT
   bool followTorrent = true;
@@ -373,6 +357,12 @@ int main(int argc, char* argv[]) {
 
   int c;
   Option* op = new Option();
+  op->put(PREF_STDOUT_LOG, V_FALSE);
+  op->put(PREF_DIR, ".");
+  op->put(PREF_SPLIT, "1");
+  op->put(PREF_DAEMON, V_FALSE);
+  op->put(PREF_LISTEN_PORT, "-1");
+  op->put(PREF_METALINK_SERVERS, "15");
   op->put(PREF_RETRY_WAIT, "5");
   op->put(PREF_TIMEOUT, "60");
   op->put(PREF_PEER_CONNECTION_TIMEOUT, "60");
@@ -479,7 +469,7 @@ int main(int argc, char* argv[]) {
 	}
 	break;
       case 7:
-	referer = optarg;
+	op->put(PREF_REFERER, optarg);
 	break;
       case 8: {
 	int wait = (int)strtol(optarg, NULL, 10);
@@ -544,14 +534,16 @@ int main(int argc, char* argv[]) {
 	  exit(EXIT_FAILURE);
 	}
 	break;
-      case 15:
-	listenPort = (int)strtol(optarg, NULL, 10);
+      case 15: {
+	int listenPort = (int)strtol(optarg, NULL, 10);
 	if(!(1024 <= listenPort && listenPort <= 65535)) {
 	  cerr << _("listen-port must be between 1024 and 65535.") << endl;
 	  showUsage();
 	  exit(EXIT_FAILURE);
 	}
+	op->put(PREF_LISTEN_PORT, Util::itos(listenPort));
 	break;
+      }
       case 16:
 	if(string(optarg) == "true") {
 	  followTorrent = true;
@@ -591,13 +583,13 @@ int main(int argc, char* argv[]) {
 	Util::unfoldRange(optarg, selectFileIndexes);
 	break;
       case 100:
-	metalinkVersion = string(optarg);
+	op->put(PREF_METALINK_VERSION, optarg);
 	break;
       case 101:
-	metalinkLanguage = string(optarg);
+	op->put(PREF_METALINK_LANGUAGE, optarg);
 	break;
       case 102:
-	metalinkOs = string(optarg);
+	op->put(PREF_METALINK_OS, optarg);
 	break;
       case 103:
 	if(string(optarg) == "true") {
@@ -614,29 +606,31 @@ int main(int argc, char* argv[]) {
       break;
     }
     case 'D':
-      daemonMode = true;
+      op->put(PREF_DAEMON, V_TRUE);
       break;
     case 'd':
-      dir = optarg;
+      op->put(PREF_DIR, optarg);
       break;
     case 'o':
-      ufilename = optarg;
+      op->put(PREF_OUT, optarg);
       break;
     case 'l':
       if(strcmp("-", optarg) == 0) {
-	stdoutLog = true;
+	op->put(PREF_STDOUT_LOG, V_TRUE);
       } else {
-	logfile = optarg;
+	op->put(PREF_LOG, optarg);
       }
       break;
-    case 's':
-      split = (int)strtol(optarg, NULL, 10);
+    case 's': {
+      int split = (int)strtol(optarg, NULL, 10);
       if(!(1 <= split && split <= 5)) {
 	cerr << _("split must be between 1 and 5.") << endl;
 	showUsage();
 	exit(EXIT_FAILURE);
       }
+      op->put(PREF_SPLIT, Util::itos(split));
       break;
+    }
     case 't': {
       int timeout = (int)strtol(optarg, NULL, 10);
       if(1 <= timeout && timeout <= 600) {
@@ -665,19 +659,21 @@ int main(int argc, char* argv[]) {
       op->put(PREF_SHOW_FILES, V_TRUE);
       break;
     case 'T':
-      torrentFile = string(optarg);
+      op->put(PREF_TORRENT_FILE, optarg);
       break;
     case 'M':
-      metalinkFile = string(optarg);
+      op->put(PREF_METALINK_FILE, optarg);
       break;
-    case 'C':
-      metalinkServers = (int)strtol(optarg, NULL, 10);
+    case 'C': {
+      int metalinkServers = (int)strtol(optarg, NULL, 10);
       if(metalinkServers <= 0) {
 	cerr << _("metalink-servers must be greater than 0.") << endl;
 	showUsage();
 	exit(EXIT_FAILURE);
       }
-      break;      
+      op->put(PREF_METALINK_SERVERS, Util::itos(metalinkServers));
+      break;
+    }
     case 'v':
       showVersion();
       exit(EXIT_SUCCESS);
@@ -689,14 +685,14 @@ int main(int argc, char* argv[]) {
       exit(EXIT_FAILURE);
     }
   }
-  if(torrentFile.empty() && metalinkFile.empty()) {
+  if(!op->defined(PREF_TORRENT_FILE) && !op->defined(PREF_METALINK_FILE)) {
     if(optind == argc) {
       cerr << _("specify at least one URL") << endl;
       showUsage();
       exit(EXIT_FAILURE);
     }
   }
-  if(daemonMode) {
+  if(op->getAsBool(PREF_DAEMON)) {
     if(daemon(1, 1) < 0) {
       perror(_("daemon failed"));
       exit(EXIT_FAILURE);
@@ -704,7 +700,7 @@ int main(int argc, char* argv[]) {
   }
   
   Strings args(argv+optind, argv+argc);
-
+  
 #ifdef HAVE_LIBSSL
   // for SSL initialization
   SSL_load_error_strings();
@@ -717,10 +713,10 @@ int main(int argc, char* argv[]) {
   xmlInitParser();
 #endif // ENABLE_METALINK
   srandom(time(NULL));
-  if(stdoutLog) {
+  if(op->getAsBool(PREF_STDOUT_LOG)) {
     LogFactory::setLogFile("/dev/stdout");
-  } else if(logfile.size()) {
-    LogFactory::setLogFile(logfile);
+  } else if(op->get(PREF_LOG).size()) {
+    LogFactory::setLogFile(op->get(PREF_LOG));
   }
   // make sure logger is configured properly.
   try {
@@ -733,12 +729,12 @@ int main(int argc, char* argv[]) {
 
   setSignalHander(SIGPIPE, SIG_IGN, 0);
 
-  if(torrentFile.empty() && metalinkFile.empty()) {
+  if(!op->defined(PREF_TORRENT_FILE) && !op->defined(PREF_METALINK_FILE)) {
     Requests requests;
     int cuidCounter = 1;
     for(Strings::const_iterator itr = args.begin(); itr != args.end(); itr++) {
-      for(int s = 1; s <= split; s++) {
-	createRequest(cuidCounter, *itr, referer, requests); 
+      for(int s = 1; s <= op->getAsInt(PREF_SPLIT); s++) {
+	createRequest(cuidCounter, *itr, op->get(PREF_REFERER), requests); 
 	cuidCounter++;
       }
     }
@@ -747,22 +743,24 @@ int main(int argc, char* argv[]) {
 
     Requests reserved;
     string downloadedFilename;
-    normalDownload(requests, reserved, op, dir, ufilename, downloadedFilename);
+    normalDownload(requests, reserved, op, downloadedFilename);
 
     for_each(requests.begin(), requests.end(), Deleter());
     for_each(reserved.begin(), reserved.end(), Deleter());
     requests.clear();
   }
 #ifdef ENABLE_METALINK
-  if(!metalinkFile.empty() || followMetalink && readyToMetalinkMode) {
-    string targetMetalinkFile = metalinkFile.empty() ?
-      downloadedMetalinkFile : metalinkFile;
+  if(op->defined(PREF_METALINK_FILE) ||
+     followMetalink && readyToMetalinkMode) {
+    string targetMetalinkFile = op->defined(PREF_METALINK_FILE) ?
+      op->get(PREF_METALINK_FILE) : downloadedMetalinkFile;
     Xml2MetalinkProcessor proc;
     Metalinker* metalinker = proc.parseFile(targetMetalinkFile);
     
-    MetalinkEntry* entry = metalinker->queryEntry(metalinkVersion,
-						  metalinkLanguage,
-						  metalinkOs);
+    MetalinkEntry* entry =
+      metalinker->queryEntry(op->get(PREF_METALINK_VERSION),
+			     op->get(PREF_METALINK_LANGUAGE),
+			     op->get(PREF_METALINK_OS));
     if(entry == NULL) {
       printf("No file matched with your preference.\n");
       exit(EXIT_FAILURE);
@@ -774,13 +772,15 @@ int main(int argc, char* argv[]) {
     for(MetalinkResources::const_iterator itr = entry->resources.begin();
 	itr != entry->resources.end(); itr++) {
       MetalinkResource* resource = *itr;
-      for(int s = 1; s <= split; s++) {
-	createRequest(cuidCounter, resource->url, referer, requests); 
+      for(int s = 1; s <= op->getAsInt(PREF_SPLIT); s++) {
+	createRequest(cuidCounter, resource->url,
+		      op->get(PREF_REFERER), requests); 
 	cuidCounter++;
       }
     }
     Requests reserved;
-    int maxConnection = metalinkServers*split;
+    int maxConnection =
+      op->getAsInt(PREF_METALINK_SERVERS)*op->getAsInt(PREF_SPLIT);
     if((int)requests.size() > maxConnection) {
       copy(requests.begin()+maxConnection, requests.end(),
 	   insert_iterator<Requests>(reserved, reserved.end()));
@@ -791,8 +791,7 @@ int main(int argc, char* argv[]) {
     setSignalHander(SIGTERM, handler, 0);
 
     string downloadedFilename;
-    bool success = normalDownload(requests, reserved, op, dir, ufilename,
-				  downloadedFilename);
+    bool success = normalDownload(requests, reserved, op, downloadedFilename);
 
     for_each(requests.begin(), requests.end(), Deleter());
     for_each(reserved.begin(), reserved.end(), Deleter());
@@ -813,7 +812,8 @@ int main(int argc, char* argv[]) {
   }
 #endif // ENABLE_METALINK
 #ifdef ENABLE_BITTORRENT
-  if(!torrentFile.empty() || followTorrent && readyToTorrentMode) {
+  if(op->defined(PREF_TORRENT_FILE) ||
+     followTorrent && readyToTorrentMode) {
     try {
       //op->put(PREF_MAX_TRIES, "0");
       setSignalHander(SIGINT, torrentHandler, SA_RESETHAND);
@@ -831,11 +831,11 @@ int main(int argc, char* argv[]) {
       te->segmentMan->splitter = new SplitSlowestSegmentSplitter();
       te->segmentMan->splitter->setMinSegmentSize(op->getAsLLInt(PREF_MIN_SEGMENT_SIZE));
       te->torrentMan = new TorrentMan();
-      te->torrentMan->setStoreDir(dir);
+      te->torrentMan->setStoreDir(op->get(PREF_DIR));
       te->torrentMan->option = op;
       te->torrentMan->req = req;
-      string targetTorrentFile = torrentFile.empty() ?
-	downloadedTorrentFile : torrentFile;
+      string targetTorrentFile = op->defined(PREF_TORRENT_FILE) ?
+	op->get(PREF_TORRENT_FILE) : downloadedTorrentFile;
       if(op->get(PREF_SHOW_FILES) == V_TRUE) {
 	FileEntries fileEntries =
 	  te->torrentMan->readFileEntryFromMetaInfoFile(targetTorrentFile);
@@ -853,7 +853,7 @@ int main(int argc, char* argv[]) {
       } else {
 	if(selectFileIndexes.empty()) {
 	  Strings targetFiles;
-	  if(!torrentFile.empty() && !args.empty()) {
+	  if(op->defined(PREF_TORRENT_FILE) && !args.empty()) {
 	    targetFiles = args;
 	  }
 	  te->torrentMan->setup(targetTorrentFile, targetFiles);
@@ -864,6 +864,7 @@ int main(int argc, char* argv[]) {
       PeerListenCommand* listenCommand =
 	new PeerListenCommand(te->torrentMan->getNewCuid(), te);
       int port;
+      int listenPort = op->getAsInt(PREF_LISTEN_PORT);
       if(listenPort == -1) {
 	port = listenCommand->bindPort(6881, 6999);
       } else {
@@ -911,5 +912,6 @@ int main(int argc, char* argv[]) {
 #ifdef ENABLE_METALINK
   xmlCleanupParser();
 #endif // ENABLE_METALINK
+  FeatureConfig::release();
   return 0;
 }

+ 32 - 0
src/prefs.h

@@ -43,6 +43,20 @@
 #define PREF_MIN_SEGMENT_SIZE "min_segment_size"
 // values: 1*digit
 #define PREF_AUTO_SAVE_INTERVAL "auto_save_interval"
+// values: true | false
+#define PREF_STDOUT_LOG "stdout_log"
+// values: a string that your file system recognizes as a file name.
+#define PREF_LOG "log"
+// values: a string that your file system recognizes as a directory.
+#define PREF_DIR "dir"
+// values: a string that your file system recognizes as a file name.
+#define PREF_OUT "out"
+// values: 1*digit
+#define PREF_SPLIT "split"
+// value: true | false
+#define PREF_DAEMON "daemon"
+// value: a string
+#define PREF_REFERER "referer"
 
 /**
  * FTP related preferences
@@ -98,5 +112,23 @@
 #define PREF_DIRECT_FILE_MAPPING "direct_file_mapping"
 // values: 1*digit
 #define PREF_UPLOAD_LIMIT "upload_limit"
+// values: a string that your file system recognizes as a file name.
+#define PREF_TORRENT_FILE "torrent_file"
+// values: 1*digit
+#define PREF_LISTEN_PORT "listen_port"
+
+/**
+ * Metalink related preferences
+ */
+// values: a string that your file system recognizes as a file name.
+#define PREF_METALINK_FILE "metalink_file"
+// values: a string
+#define PREF_METALINK_VERSION "metalink_version"
+// values: a string
+#define PREF_METALINK_LANGUAGE "metalink_language"
+// values: a string
+#define PREF_METALINK_OS "metalink_os"
+// values: 1*digit
+#define PREF_METALINK_SERVERS "metalink_servers"
 
 #endif // _D_PREFS_H_

+ 17 - 9
test/FeatureConfigTest.cc

@@ -20,16 +20,23 @@ public:
 CPPUNIT_TEST_SUITE_REGISTRATION(FeatureConfigTest);
 
 void FeatureConfigTest::testGetDefaultPort() {
-  CPPUNIT_ASSERT_EQUAL(80, FeatureConfig::getDefaultPort("http"));
-  CPPUNIT_ASSERT_EQUAL(443, FeatureConfig::getDefaultPort("https"));
-  CPPUNIT_ASSERT_EQUAL(21, FeatureConfig::getDefaultPort("ftp"));
+  CPPUNIT_ASSERT_EQUAL(80,
+		       FeatureConfig::getInstance()->getDefaultPort("http"));
+  CPPUNIT_ASSERT_EQUAL(443,
+		       FeatureConfig::getInstance()->getDefaultPort("https"));
+  CPPUNIT_ASSERT_EQUAL(21,
+		       FeatureConfig::getInstance()->getDefaultPort("ftp"));
 }
 
 void FeatureConfigTest::testIsSupported() {
-  CPPUNIT_ASSERT_EQUAL(true, FeatureConfig::isSupported("http"));
-  CPPUNIT_ASSERT_EQUAL(true, FeatureConfig::isSupported("https"));
-  CPPUNIT_ASSERT_EQUAL(true, FeatureConfig::isSupported("ftp"));
-  CPPUNIT_ASSERT_EQUAL(false, FeatureConfig::isSupported("ftps"));
+  CPPUNIT_ASSERT_EQUAL(true,
+		       FeatureConfig::getInstance()->isSupported("http"));
+  CPPUNIT_ASSERT_EQUAL(true,
+		       FeatureConfig::getInstance()->isSupported("https"));
+  CPPUNIT_ASSERT_EQUAL(true,
+		       FeatureConfig::getInstance()->isSupported("ftp"));
+  CPPUNIT_ASSERT_EQUAL(false,
+		       FeatureConfig::getInstance()->isSupported("ftps"));
 }
 
 void FeatureConfigTest::testGetConfigurationSummary() {
@@ -37,6 +44,7 @@ void FeatureConfigTest::testGetConfigurationSummary() {
 		       +"https: yes\n"
 		       +"ftp: yes\n"
 		       +"bittorrent: yes\n"
-		       +"metalink: yes\n",
-		       FeatureConfig::getConfigurationSummary());
+		       +"metalink: yes\n"
+		       +"message digest: yes\n",
+		       FeatureConfig::getInstance()->getConfigurationSummary());
 }