Просмотр исходного кода

2006-08-08 Tatsuhiro Tsujikawa <tujikawa@rednoah.com>

	* src/FtpNegotiateCommand.cc
	(recvGreeting): Call disableWriteCheckSocket just after
	socket->setBlockingMode(). This avoids unnecessary CPU-hog loop.

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

	* src/PeerChokeCommand.h
	(PeerChokeCommand): Rearranged the arguments.
	* src/PeerChokeCommand.cc
	(PeerChokeCommand): Rearranged the arguments.

	* src/MetalinkEntry.h
	(Checksum.h): Included.
	(md5): Removed.
	(sha1): Removed.
	(checksum): New variable.
	(operator=): Updated.
	(check): Removed.

	* src/prefs.h
	(PREF_LOWEST_SPEED_LIMIT): New definition.
	(PREF_FOLLOW_TORRENT): New definition.
	(PREF_SELECT_FILE): New definition.
	(PREF_FOLLOW_METALINK): New definition.

	* src/MetalinkResource.h
	(TYPE_HTTPS): Added to enum TYPE.

	* src/TorrentMan.cc
	(~TorrentMan): Rewritten.

	* src/MultiDiskWriter.cc
	(MultiDiskAdaptor): Updated according to the changes in
	MessageDigestContext.
	(~MultiDiskAdaptor): Updated according to the changes in
	MessageDigestContext.
	(hashUpdate): Updated according to the changes in 
MessageDigestContext.
	(sha1Sum): Updated according to the changes in 
MessageDigestContext.

	* src/Util.h
	(fileChecksum): Updated according to the changes in
	MessageDigestContext.
	* src/Util.cc
	(sha1Sum): Updated according to the changes in 
MessageDigestContext.
	(fileChecksum): Updated according to the changes in
	MessageDigestContext.

	* src/messageDigest.h: Rewritten.

	* src/MetalinkEntry.cc
	(check): Removed.
	(Supported): Updated.
	(dropUnsupportedResource): Fixed a memory leak.

	* src/ShaVisitor.cc
	(ShaVisitor): Updated according to the changes in 
MessageDigestContext.
	(~ShaVisitor): Updated according to the changes in
	MessageDigestContext.
	(visit): Updated according to the changes in 
MessageDigestContext.

	* src/main.cc
	(main): Rewritten the portion of download loop. 
--lowest-speed-limit
	command-line option added.

	* src/DownloadEngine.h
	(SocketEntry): New class.
	(SocketEntries): New definition.
	(PairFind): Removed.
	(SockCmdMap): Removed.
	* src/DownloadEngine.cc
	(DownloadEngine): Rewritten.
	(~DownloadEngine): Rewritten.
	(run): Renamed activeCommandUuids as activeUuids.
	(SetDescriptor): Rewritten.
	(AccumulateActiveCommandUuid): Removed.
	(AccumulateActiveUuid): New function object.
	(waitData): Rewritten.
	(updateFdSet): Rewritten.
	(addSocket): Rewritten.
	(deleteSocket): Rewritten.
	(addSocketForReadCheck): Rewritten.
	(deleteSocketForReadCheck): Rewritten.
	(addSocketForWriteCheck): Rewritten.
	(deleteSocketForWriteCheck): Rewritten.
	
	* src/Xml2MetalinkProcessor.cc
	(getEntry): Rewritten the portion of MetalinkEntry creation.

	* src/DownloadCommand.cc
	(executeInternal): Added the check routine for lowest speed 
limit.

	* src/AbstractDiskWriter.cc
	(AbstractDiskWriter): Updated according to the changes in
	MessageDigestContext.
	(~AbstractDiskWriter): Updated according to the changes in
	MessageDigestContext.
	(sha1Sum): Updated according to the changes in 
MessageDigestContext.

	* src/RequestInfo.h: New class.

	* src/UrlRequestInfo.h: New class.
	* src/UrlRequestInfo.cc: New class.

	* src/TorrentRequestInfo.h: New class.
	* src/TorrentRequestInfo.cc: New class.

	* src/MetalinkRequestInfo.h: New class.
	* src/MetalinkRequestInfo.cc: New class.

	* src/Checksum.h: New class.

	* src/DownloadEngineFactory.h: New class.
	* src/DownloadEngineFactory.cc: New class.
Tatsuhiro Tsujikawa 19 лет назад
Родитель
Сommit
58dbaafc85

+ 116 - 0
ChangeLog

@@ -1,3 +1,119 @@
+2006-08-08  Tatsuhiro Tsujikawa  <tujikawa@rednoah.com>
+
+	* src/FtpNegotiateCommand.cc
+	(recvGreeting): Call disableWriteCheckSocket just after
+	socket->setBlockingMode(). This avoids unnecessary CPU-hog loop.
+
+2006-08-07  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
+
+	* src/PeerChokeCommand.h
+	(PeerChokeCommand): Rearranged the arguments.
+	* src/PeerChokeCommand.cc
+	(PeerChokeCommand): Rearranged the arguments.
+
+	* src/MetalinkEntry.h
+	(Checksum.h): Included.
+	(md5): Removed.
+	(sha1): Removed.
+	(checksum): New variable.
+	(operator=): Updated.
+	(check): Removed.
+
+	* src/prefs.h
+	(PREF_LOWEST_SPEED_LIMIT): New definition.
+	(PREF_FOLLOW_TORRENT): New definition.
+	(PREF_SELECT_FILE): New definition.
+	(PREF_FOLLOW_METALINK): New definition.
+
+	* src/MetalinkResource.h
+	(TYPE_HTTPS): Added to enum TYPE.
+
+	* src/TorrentMan.cc
+	(~TorrentMan): Rewritten.
+
+	* src/MultiDiskWriter.cc
+	(MultiDiskAdaptor): Updated according to the changes in
+	MessageDigestContext.
+	(~MultiDiskAdaptor): Updated according to the changes in
+	MessageDigestContext.
+	(hashUpdate): Updated according to the changes in MessageDigestContext.
+	(sha1Sum): Updated according to the changes in MessageDigestContext.
+
+	* src/Util.h
+	(fileChecksum): Updated according to the changes in
+	MessageDigestContext.
+	* src/Util.cc
+	(sha1Sum): Updated according to the changes in MessageDigestContext.
+	(fileChecksum): Updated according to the changes in
+	MessageDigestContext.
+
+	* src/messageDigest.h: Rewritten.
+
+	* src/MetalinkEntry.cc
+	(check): Removed.
+	(Supported): Updated.
+	(dropUnsupportedResource): Fixed a memory leak.
+
+	* src/ShaVisitor.cc
+	(ShaVisitor): Updated according to the changes in MessageDigestContext.
+	(~ShaVisitor): Updated according to the changes in
+	MessageDigestContext.
+	(visit): Updated according to the changes in MessageDigestContext.
+
+	* src/main.cc
+	(main): Rewritten the portion of download loop. --lowest-speed-limit
+	command-line option added.
+
+	* src/DownloadEngine.h
+	(SocketEntry): New class.
+	(SocketEntries): New definition.
+	(PairFind): Removed.
+	(SockCmdMap): Removed.
+	* src/DownloadEngine.cc
+	(DownloadEngine): Rewritten.
+	(~DownloadEngine): Rewritten.
+	(run): Renamed activeCommandUuids as activeUuids.
+	(SetDescriptor): Rewritten.
+	(AccumulateActiveCommandUuid): Removed.
+	(AccumulateActiveUuid): New function object.
+	(waitData): Rewritten.
+	(updateFdSet): Rewritten.
+	(addSocket): Rewritten.
+	(deleteSocket): Rewritten.
+	(addSocketForReadCheck): Rewritten.
+	(deleteSocketForReadCheck): Rewritten.
+	(addSocketForWriteCheck): Rewritten.
+	(deleteSocketForWriteCheck): Rewritten.
+	
+	* src/Xml2MetalinkProcessor.cc
+	(getEntry): Rewritten the portion of MetalinkEntry creation.
+
+	* src/DownloadCommand.cc
+	(executeInternal): Added the check routine for lowest speed limit.
+
+	* src/AbstractDiskWriter.cc
+	(AbstractDiskWriter): Updated according to the changes in
+	MessageDigestContext.
+	(~AbstractDiskWriter): Updated according to the changes in
+	MessageDigestContext.
+	(sha1Sum): Updated according to the changes in MessageDigestContext.
+
+	* src/RequestInfo.h: New class.
+
+	* src/UrlRequestInfo.h: New class.
+	* src/UrlRequestInfo.cc: New class.
+
+	* src/TorrentRequestInfo.h: New class.
+	* src/TorrentRequestInfo.cc: New class.
+
+	* src/MetalinkRequestInfo.h: New class.
+	* src/MetalinkRequestInfo.cc: New class.
+
+	* src/Checksum.h: New class.
+
+	* src/DownloadEngineFactory.h: New class.
+	* src/DownloadEngineFactory.cc: New class.
+	
 2006-08-03  Tatsuhiro Tsujikawa  <tujikawa at rednoah dot com>
 
 	* src/Option.h

+ 1 - 2
TODO

@@ -10,8 +10,7 @@
 * Add max peers command-line option
 * Refacturing HttpConnection and FtpConnection
 * Query resource by location
-* Log version
 * List available os, version, etc for metalink
-* bittorrent in metalink
 * rename Time to something appropriate
 * ipv6(RFC2428 for ftp)
+* add ru.po

+ 13 - 13
configure

@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.59 for aria2c 0.6.1.
+# Generated by GNU Autoconf 2.59 for aria2c 0.7.0.
 #
 # Report bugs to <tujikawa@rednoah.com>.
 #
@@ -269,8 +269,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
 # Identity of this package.
 PACKAGE_NAME='aria2c'
 PACKAGE_TARNAME='aria2c'
-PACKAGE_VERSION='0.6.1'
-PACKAGE_STRING='aria2c 0.6.1'
+PACKAGE_VERSION='0.7.0'
+PACKAGE_STRING='aria2c 0.7.0'
 PACKAGE_BUGREPORT='tujikawa@rednoah.com'
 
 ac_unique_file="src/Socket.h"
@@ -788,7 +788,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures aria2c 0.6.1 to adapt to many kinds of systems.
+\`configure' configures aria2c 0.7.0 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -854,7 +854,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of aria2c 0.6.1:";;
+     short | recursive ) echo "Configuration of aria2c 0.7.0:";;
    esac
   cat <<\_ACEOF
 
@@ -1000,7 +1000,7 @@ fi
 test -n "$ac_init_help" && exit 0
 if $ac_init_version; then
   cat <<\_ACEOF
-aria2c configure 0.6.1
+aria2c configure 0.7.0
 generated by GNU Autoconf 2.59
 
 Copyright (C) 2003 Free Software Foundation, Inc.
@@ -1014,7 +1014,7 @@ cat >&5 <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by aria2c $as_me 0.6.1, which was
+It was created by aria2c $as_me 0.7.0, which was
 generated by GNU Autoconf 2.59.  Invocation command line was
 
   $ $0 $@
@@ -1657,7 +1657,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='aria2c'
- VERSION='0.6.1'
+ VERSION='0.7.0'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -1927,7 +1927,7 @@ localedir=${datadir}/locale
 # Check whether --with-gnutls or --without-gnutls was given.
 if test "${with_gnutls+set}" = set; then
   withval="$with_gnutls"
-  with_gnutls=$enableval
+  with_gnutls=$withval
 else
   with_gnutls=yes
 fi;
@@ -1935,7 +1935,7 @@ fi;
 # Check whether --with-openssl or --without-openssl was given.
 if test "${with_openssl+set}" = set; then
   withval="$with_openssl"
-  with_openssl=$enableval
+  with_openssl=$withval
 else
   with_openssl=yes
 fi;
@@ -1943,7 +1943,7 @@ fi;
 # Check whether --with-libxml2 or --without-libxml2 was given.
 if test "${with_libxml2+set}" = set; then
   withval="$with_libxml2"
-  with_libxml2=$enableval
+  with_libxml2=$withval
 else
   with_libxml2=yes
 fi;
@@ -11943,7 +11943,7 @@ _ASBOX
 } >&5
 cat >&5 <<_CSEOF
 
-This file was extended by aria2c $as_me 0.6.1, which was
+This file was extended by aria2c $as_me 0.7.0, which was
 generated by GNU Autoconf 2.59.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -12006,7 +12006,7 @@ _ACEOF
 
 cat >>$CONFIG_STATUS <<_ACEOF
 ac_cs_version="\\
-aria2c config.status 0.6.1
+aria2c config.status 0.7.0
 configured by $0, generated by GNU Autoconf 2.59,
   with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
 

+ 4 - 4
configure.ac

@@ -2,7 +2,7 @@
 # Process this file with autoconf to produce a configure script.
 #
 AC_PREREQ(2.59)
-AC_INIT(aria2c, 0.6.1, tujikawa@rednoah.com)
+AC_INIT(aria2c, 0.7.0, tujikawa@rednoah.com)
 AM_INIT_AUTOMAKE()
 AM_PATH_CPPUNIT(1.10.2)
 AC_CONFIG_SRCDIR([src/Socket.h])
@@ -13,9 +13,9 @@ localedir=${datadir}/locale
 AC_SUBST(localedir)
 
 # Checks for arguments.
-AC_ARG_WITH([gnutls],  [  --with-gnutls              use gnutls library if installed. Default: yes], [with_gnutls=$enableval], [with_gnutls=yes])
-AC_ARG_WITH([openssl], [  --with-openssl             use openssl library if installed. Default: yes], [with_openssl=$enableval], [with_openssl=yes])
-AC_ARG_WITH([libxml2], [  --with-libxml2             use libxml2 library if installed. Default: yes], [with_libxml2=$enableval], [with_libxml2=yes])
+AC_ARG_WITH([gnutls],  [  --with-gnutls              use gnutls library if installed. Default: yes], [with_gnutls=$withval], [with_gnutls=yes])
+AC_ARG_WITH([openssl], [  --with-openssl             use openssl library if installed. Default: yes], [with_openssl=$withval], [with_openssl=yes])
+AC_ARG_WITH([libxml2], [  --with-libxml2             use libxml2 library if installed. Default: yes], [with_libxml2=$withval], [with_libxml2=yes])
 
 AC_ARG_ENABLE([bittorrent], [ --enable-bittorrent        enable BitTorrent support. Default: yes], [enable_bittorrent=$enableval], [enable_bittorrent=yes])
 AC_ARG_ENABLE([metalink], [ --enable-metalink          enable Metalink support. Default: yes], [enable_metalink=$enableval], [enable_metalink=yes])

+ 4 - 0
po/POTFILES

@@ -1,2 +1,6 @@
+     ../src/RequestInfo.h \
      ../src/message.h \
+     ../src/DownloadEngineFactory.cc \
+     ../src/TorrentRequestInfo.cc \
+     ../src/UrlRequestInfo.cc \
      ../src/main.cc

+ 4 - 0
po/POTFILES.in

@@ -1,2 +1,6 @@
+src/RequestInfo.h
 src/message.h
+src/DownloadEngineFactory.cc
+src/TorrentRequestInfo.cc
+src/UrlRequestInfo.cc
 src/main.cc

+ 118 - 99
po/aria2c.pot

@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: http://aria2.sourceforge.net/\n"
-"POT-Creation-Date: 2006-07-21 00:57+0900\n"
+"POT-Creation-Date: 2006-08-07 22:15+0900\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -16,6 +16,19 @@ msgstr ""
 "Content-Type: text/plain; charset=CHARSET\n"
 "Content-Transfer-Encoding: 8bit\n"
 
+#: src/RequestInfo.h:76
+#, c-format
+msgid ""
+"\n"
+"The download was complete. <%s>\n"
+msgstr ""
+
+#: src/RequestInfo.h:84
+msgid ""
+"\n"
+"The download was not complete because of errors. Check the log.\n"
+msgstr ""
+
 #: src/message.h:27
 #, c-format
 msgid "CUID#%d - The download for one segment completed successfully."
@@ -329,39 +342,34 @@ msgstr ""
 msgid "Failed to peek data, cause: %s"
 msgstr ""
 
-#: src/main.cc:76
-#, c-format
-msgid ""
-"\n"
-"The download was complete. <%s>\n"
+#: src/DownloadEngineFactory.cc:102
+msgid "Errors occurred while binding port.\n"
 msgstr ""
 
-#: src/main.cc:84
-msgid ""
-"\n"
-"The download was not complete because of errors. Check the log.\n"
+#: src/TorrentRequestInfo.cc:71
+msgid "Files:"
 msgstr ""
 
-#: src/main.cc:101
+#: src/UrlRequestInfo.cc:57
 msgid ""
 "\n"
 "stopping application...\n"
 msgstr ""
 
-#: src/main.cc:107
+#: src/UrlRequestInfo.cc:62
 msgid "done\n"
 msgstr ""
 
-#: src/main.cc:123
+#: src/UrlRequestInfo.cc:86
 #, c-format
 msgid "Unrecognized URL or unsupported protocol: %s\n"
 msgstr ""
 
-#: src/main.cc:129
+#: src/main.cc:71
 msgid " version "
 msgstr ""
 
-#: src/main.cc:133
+#: src/main.cc:78
 msgid ""
 "This program is free software; you can redistribute it and/or modify\n"
 "it under the terms of the GNU General Public License as published by\n"
@@ -378,50 +386,50 @@ msgid ""
 "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n"
 msgstr ""
 
-#: src/main.cc:147
+#: src/main.cc:92
 #, c-format
 msgid "Contact Info: %s\n"
 msgstr ""
 
-#: src/main.cc:153
+#: src/main.cc:98
 #, c-format
 msgid "Usage: %s [options] URL ...\n"
 msgstr ""
 
-#: src/main.cc:155
+#: src/main.cc:100
 #, c-format
 msgid "       %s [options] -T TORRENT_FILE FILE ...\n"
 msgstr ""
 
-#: src/main.cc:158
+#: src/main.cc:103
 #, c-format
 msgid "       %s [options] -M METALINK_FILE\n"
 msgstr ""
 
-#: src/main.cc:161
+#: src/main.cc:106
 msgid "Options:"
 msgstr ""
 
-#: src/main.cc:162
+#: src/main.cc:107
 msgid " -d, --dir=DIR                The directory to store downloaded file."
 msgstr ""
 
-#: src/main.cc:163
+#: src/main.cc:108
 msgid " -o, --out=FILE               The file name for downloaded file."
 msgstr ""
 
-#: src/main.cc:164
+#: src/main.cc:109
 msgid ""
 " -l, --log=LOG                The file path to store log. If '-' is "
 "specified,\n"
 "                              log is written to stdout."
 msgstr ""
 
-#: src/main.cc:166
+#: src/main.cc:111
 msgid " -D, --daemon                 Run as daemon."
 msgstr ""
 
-#: src/main.cc:167
+#: src/main.cc:112
 msgid ""
 " -s, --split=N                Download a file using N connections. N must "
 "be\n"
@@ -431,65 +439,65 @@ msgid ""
 "                              N connections."
 msgstr ""
 
-#: src/main.cc:171
+#: src/main.cc:116
 msgid ""
 " --retry-wait=SEC             Set amount of time in second between requests\n"
 "                              for errors. Specify a value between 0 and 60.\n"
 "                              Default: 5"
 msgstr ""
 
-#: src/main.cc:174
+#: src/main.cc:119
 msgid " -t, --timeout=SEC            Set timeout in second. Default: 60"
 msgstr ""
 
-#: src/main.cc:175
+#: src/main.cc:120
 msgid ""
 " -m, --max-tries=N            Set number of tries. 0 means unlimited.\n"
 "                              Default: 5"
 msgstr ""
 
-#: src/main.cc:177
+#: src/main.cc:122
 msgid ""
 " --min-segment-size=SIZE[K|M] Set minimum segment size. You can append\n"
 "                              K or M(1K = 1024, 1M = 1024K). This\n"
 "                              value must be greater than or equal to\n"
-"                              1024."
+"                              1024. Default: 1M"
 msgstr ""
 
-#: src/main.cc:181
+#: src/main.cc:126
 msgid ""
 " --http-proxy=HOST:PORT       Use HTTP proxy server. This affects to all\n"
 "                              URLs."
 msgstr ""
 
-#: src/main.cc:183
+#: src/main.cc:128
 msgid " --http-user=USER             Set HTTP user. This affects to all URLs."
 msgstr ""
 
-#: src/main.cc:184
+#: src/main.cc:129
 msgid ""
 " --http-passwd=PASSWD         Set HTTP password. This affects to all URLs."
 msgstr ""
 
-#: src/main.cc:185
+#: src/main.cc:130
 msgid ""
 " --http-proxy-user=USER       Set HTTP proxy user. This affects to all URLs"
 msgstr ""
 
-#: src/main.cc:186
+#: src/main.cc:131
 msgid ""
 " --http-proxy-passwd=PASSWD   Set HTTP proxy password. This affects to all "
 "URLs."
 msgstr ""
 
-#: src/main.cc:187
+#: src/main.cc:132
 msgid ""
 " --http-proxy-method=METHOD   Set the method to use in proxy request.\n"
 "                              METHOD is either 'get' or 'tunnel'.\n"
 "                              Default: tunnel"
 msgstr ""
 
-#: src/main.cc:190
+#: src/main.cc:135
 msgid ""
 " --http-auth-scheme=SCHEME    Set HTTP authentication scheme. Currently, "
 "basic\n"
@@ -497,23 +505,23 @@ msgid ""
 "                              Default: basic"
 msgstr ""
 
-#: src/main.cc:193
+#: src/main.cc:138
 msgid " --referer=REFERER            Set Referer. This affects to all URLs."
 msgstr ""
 
-#: src/main.cc:194
+#: src/main.cc:139
 msgid ""
 " --ftp-user=USER              Set FTP user. This affects to all URLs.\n"
 "                              Default: anonymous"
 msgstr ""
 
-#: src/main.cc:196
+#: src/main.cc:141
 msgid ""
 " --ftp-passwd=PASSWD          Set FTP password. This affects to all URLs.\n"
 "                              Default: ARIA2USER@"
 msgstr ""
 
-#: src/main.cc:198
+#: src/main.cc:143
 msgid ""
 " --ftp-type=TYPE              Set FTP transfer type. TYPE is either "
 "'binary'\n"
@@ -521,11 +529,11 @@ msgid ""
 "                              Default: binary"
 msgstr ""
 
-#: src/main.cc:201
+#: src/main.cc:146
 msgid " -p, --ftp-pasv               Use passive mode in FTP."
 msgstr ""
 
-#: src/main.cc:202
+#: src/main.cc:147
 msgid ""
 " --ftp-via-http-proxy=METHOD  Use HTTP proxy in FTP. METHOD is either 'get' "
 "or\n"
@@ -533,11 +541,26 @@ msgid ""
 "                              Default: tunnel"
 msgstr ""
 
-#: src/main.cc:206
+#: src/main.cc:150
+msgid ""
+" --lowest-speed-limit         Close connection if download speed is lower "
+"than\n"
+"                              or equal to this value. 0 means aria2 does "
+"not\n"
+"                              care lowest speed limit. You can use K or M "
+"in\n"
+"                              the same manner as in --min-segment-size "
+"option.\n"
+"                              This option does not affect BitTorrent "
+"download.\n"
+"                              Default: 0"
+msgstr ""
+
+#: src/main.cc:157
 msgid " -T, --torrent-file=TORRENT_FILE  The file path to .torrent file."
 msgstr ""
 
-#: src/main.cc:207
+#: src/main.cc:158
 msgid ""
 " --follow-torrent=true|false  Setting this option to false prevents aria2 "
 "to\n"
@@ -546,25 +569,25 @@ msgid ""
 "                              Default: true"
 msgstr ""
 
-#: src/main.cc:211
+#: src/main.cc:162
 msgid ""
 " -S, --show-files             Print file listing of .torrent file and exit."
 msgstr ""
 
-#: src/main.cc:212
+#: src/main.cc:163
 msgid ""
 " --direct-file-mapping=true|false Directly read from and write to each file\n"
 "                              mentioned in .torrent file.\n"
 "                              Default: true"
 msgstr ""
 
-#: src/main.cc:215
+#: src/main.cc:166
 msgid ""
 " --listen-port=PORT           Set port number to listen to for peer "
 "connection."
 msgstr ""
 
-#: src/main.cc:216
+#: src/main.cc:167
 msgid ""
 " --upload-limit=SPEED         Set upload speed limit in KB/sec. aria2 tries "
 "to\n"
@@ -572,7 +595,7 @@ msgid ""
 "unlimited."
 msgstr ""
 
-#: src/main.cc:218
+#: src/main.cc:169
 msgid ""
 " --select-file=INDEX...       Set file to download by specifing its index.\n"
 "                              You can know file index through --show-files\n"
@@ -584,11 +607,11 @@ msgid ""
 "                              ',' and '-' can be used together."
 msgstr ""
 
-#: src/main.cc:226
+#: src/main.cc:177
 msgid " -M, --metalink-file=METALINK_FILE The file path to .metalink file."
 msgstr ""
 
-#: src/main.cc:227
+#: src/main.cc:178
 msgid ""
 " -C, --metalink-servers=NUM_SERVERS The number of servers to connect to\n"
 "                              simultaneously. If more than one connection "
@@ -597,20 +620,20 @@ msgid ""
 "                              Default: 15"
 msgstr ""
 
-#: src/main.cc:231
+#: src/main.cc:182
 msgid " --metalink-version=VERSION   The version of file to download."
 msgstr ""
 
-#: src/main.cc:232
+#: src/main.cc:183
 msgid " --metalink-language=LANGUAGE The language of file to download."
 msgstr ""
 
-#: src/main.cc:233
+#: src/main.cc:184
 msgid ""
 " --metalink-os=OS             The operating system the file is targeted."
 msgstr ""
 
-#: src/main.cc:234
+#: src/main.cc:185
 msgid ""
 " --follow-metalink=true|false  Setting this option to false prevents aria2 "
 "to\n"
@@ -619,155 +642,151 @@ msgid ""
 "                              Default: true"
 msgstr ""
 
-#: src/main.cc:239
+#: src/main.cc:190
 msgid " -v, --version                Print the version number and exit."
 msgstr ""
 
-#: src/main.cc:240
+#: src/main.cc:191
 msgid " -h, --help                   Print this message and exit."
 msgstr ""
 
-#: src/main.cc:243
+#: src/main.cc:194
 msgid ""
 " You can specify multiple URLs. All URLs must point to the same file\n"
 " or downloading fails."
 msgstr ""
 
-#: src/main.cc:248
+#: src/main.cc:199
 msgid ""
 " Specify files in multi-file torrent to download. Use conjunction with\n"
 " -T option. This arguments are ignored if you specify --select-file option."
 msgstr ""
 
-#: src/main.cc:252
+#: src/main.cc:203
 msgid "Examples:"
 msgstr ""
 
-#: src/main.cc:253
+#: src/main.cc:204
 msgid " Download a file by 1 connection:"
 msgstr ""
 
-#: src/main.cc:255
+#: src/main.cc:206
 msgid " Download a file by 2 connections:"
 msgstr ""
 
-#: src/main.cc:257
+#: src/main.cc:208
 msgid " Download a file by 2 connections, each connects to a different server:"
 msgstr ""
 
-#: src/main.cc:259
+#: src/main.cc:210
 msgid " You can mix up different protocols:"
 msgstr ""
 
-#: src/main.cc:263
+#: src/main.cc:214
 msgid " Download a torrent:"
 msgstr ""
 
-#: src/main.cc:265
+#: src/main.cc:216
 msgid " Download a torrent using local .torrent file:"
 msgstr ""
 
-#: src/main.cc:267
+#: src/main.cc:218
 msgid " Download only selected files:"
 msgstr ""
 
-#: src/main.cc:269
+#: src/main.cc:220
 msgid " Print file listing of .torrent file:"
 msgstr ""
 
-#: src/main.cc:274
+#: src/main.cc:225
 msgid " Metalink downloading:"
 msgstr ""
 
-#: src/main.cc:276
+#: src/main.cc:227
 msgid " Download a file using local .metalink file:"
 msgstr ""
 
-#: src/main.cc:278
+#: src/main.cc:229
 msgid " Metalink downloading with preferences:"
 msgstr ""
 
-#: src/main.cc:282
+#: src/main.cc:233
 #, c-format
 msgid "Report bugs to %s"
 msgstr ""
 
-#: src/main.cc:446
+#: src/main.cc:358
 msgid "unrecognized proxy format"
 msgstr ""
 
-#: src/main.cc:473
+#: src/main.cc:385
 msgid "Currently, supported authentication scheme is basic."
 msgstr ""
 
-#: src/main.cc:482
+#: src/main.cc:394
 msgid "retry-wait must be between 0 and 60."
 msgstr ""
 
-#: src/main.cc:499
+#: src/main.cc:411
 msgid "ftp-type must be either 'binary' or 'ascii'."
 msgstr ""
 
-#: src/main.cc:508
+#: src/main.cc:420
 msgid "ftp-via-http-proxy must be either 'get' or 'tunnel'."
 msgstr ""
 
-#: src/main.cc:526
+#: src/main.cc:428
 msgid "min-segment-size invalid"
 msgstr ""
 
-#: src/main.cc:537
+#: src/main.cc:439
 msgid "http-proxy-method must be either 'get' or 'tunnel'."
 msgstr ""
 
-#: src/main.cc:545
+#: src/main.cc:447
 msgid "listen-port must be between 1024 and 65535."
 msgstr ""
 
-#: src/main.cc:556
+#: src/main.cc:460
 msgid "follow-torrent must be either 'true' or 'false'."
 msgstr ""
 
-#: src/main.cc:570
+#: src/main.cc:474
 msgid "direct-file-mapping must be either 'true' or 'false'."
 msgstr ""
 
-#: src/main.cc:578
+#: src/main.cc:482
 msgid "upload-limit must be greater than or equal to 0."
 msgstr ""
 
-#: src/main.cc:603
+#: src/main.cc:507
 msgid "follow-metalink must be either 'true' or 'false'."
 msgstr ""
 
-#: src/main.cc:630
+#: src/main.cc:515
+msgid "lowest-speed-limit must be greater than or equal to 0"
+msgstr ""
+
+#: src/main.cc:544
 msgid "split must be between 1 and 5."
 msgstr ""
 
-#: src/main.cc:640
+#: src/main.cc:556
 msgid "timeout must be between 1 and 600"
 msgstr ""
 
-#: src/main.cc:649
+#: src/main.cc:565
 msgid "max-tries invalid"
 msgstr ""
 
-#: src/main.cc:671
+#: src/main.cc:587
 msgid "metalink-servers must be greater than 0."
 msgstr ""
 
-#: src/main.cc:689
+#: src/main.cc:607
 msgid "specify at least one URL"
 msgstr ""
 
-#: src/main.cc:696
+#: src/main.cc:614
 msgid "daemon failed"
 msgstr ""
-
-#: src/main.cc:837
-msgid "Files:"
-msgstr ""
-
-#: src/main.cc:868
-msgid "Errors occurred while binding port.\n"
-msgstr ""


+ 126 - 105
po/de.po

@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: de\n"
 "Report-Msgid-Bugs-To: http://aria2.sourceforge.net/\n"
-"POT-Creation-Date: 2006-07-21 00:57+0900\n"
+"POT-Creation-Date: 2006-08-07 22:15+0900\n"
 "PO-Revision-Date: 2006-05-05 19:44+0900\n"
 "Last-Translator: Hermann J. Beckers <hj.beckers@onlinehome.de>\n"
 "Language-Team: deutsch <de@li.org>\n"
@@ -16,6 +16,23 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "X-Generator: KBabel 1.3\n"
 
+#: src/RequestInfo.h:76
+#, c-format
+msgid ""
+"\n"
+"The download was complete. <%s>\n"
+msgstr ""
+"\n"
+"Abruf ist vollständig. <%s>\n"
+
+#: src/RequestInfo.h:84
+msgid ""
+"\n"
+"The download was not complete because of errors. Check the log.\n"
+msgstr ""
+"\n"
+"Abruf wegen Fehlern nicht vollständig. Überprüfen Sie die Log-Datei.\n"
+
 #: src/message.h:27
 #, c-format
 msgid "CUID#%d - The download for one segment completed successfully."
@@ -338,24 +355,15 @@ msgstr "Konnte Daten nicht erhalten, Ursache: %s"
 msgid "Failed to peek data, cause: %s"
 msgstr "Datenermittelung fehlgeschlagen, Ursache: %s"
 
-#: src/main.cc:76
-#, c-format
-msgid ""
-"\n"
-"The download was complete. <%s>\n"
-msgstr ""
-"\n"
-"Abruf ist vollständig. <%s>\n"
+#: src/DownloadEngineFactory.cc:102
+msgid "Errors occurred while binding port.\n"
+msgstr "Fehler beim Binden an Port aufgetreten.\n"
 
-#: src/main.cc:84
-msgid ""
-"\n"
-"The download was not complete because of errors. Check the log.\n"
-msgstr ""
-"\n"
-"Abruf wegen Fehlern nicht vollständig. Überprüfen Sie die Log-Datei.\n"
+#: src/TorrentRequestInfo.cc:71
+msgid "Files:"
+msgstr "Dateien:"
 
-#: src/main.cc:101
+#: src/UrlRequestInfo.cc:57
 msgid ""
 "\n"
 "stopping application...\n"
@@ -363,20 +371,20 @@ msgstr ""
 "\n"
 "Anwendung wird gestoppt ...\n"
 
-#: src/main.cc:107
+#: src/UrlRequestInfo.cc:62
 msgid "done\n"
 msgstr "erledigt\n"
 
-#: src/main.cc:123
+#: src/UrlRequestInfo.cc:86
 #, c-format
 msgid "Unrecognized URL or unsupported protocol: %s\n"
 msgstr "URL nicht erkannt oder nicht unterstütztes Protokoll: %s\n"
 
-#: src/main.cc:129
+#: src/main.cc:71
 msgid " version "
 msgstr " Version "
 
-#: src/main.cc:133
+#: src/main.cc:78
 msgid ""
 "This program is free software; you can redistribute it and/or modify\n"
 "it under the terms of the GNU General Public License as published by\n"
@@ -406,41 +414,41 @@ msgstr ""
 "along with this program; if not, write to the Free Software\n"
 "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n"
 
-#: src/main.cc:147
+#: src/main.cc:92
 #, c-format
 msgid "Contact Info: %s\n"
 msgstr "Kontakt-Info: %s\n"
 
-#: src/main.cc:153
+#: src/main.cc:98
 #, c-format
 msgid "Usage: %s [options] URL ...\n"
 msgstr "Aufruf: %s [Optionen] URL ...\n"
 
-#: src/main.cc:155
+#: src/main.cc:100
 #, c-format
 msgid "       %s [options] -T TORRENT_FILE FILE ...\n"
 msgstr "       %s [Optionen] -T TORRENT_FILE FILE ...\n"
 
-#: src/main.cc:158
+#: src/main.cc:103
 #, fuzzy, c-format
 msgid "       %s [options] -M METALINK_FILE\n"
 msgstr "       %s [Optionen] -T TORRENT_FILE FILE ...\n"
 
-#: src/main.cc:161
+#: src/main.cc:106
 msgid "Options:"
 msgstr "Optionen:"
 
-#: src/main.cc:162
+#: src/main.cc:107
 msgid " -d, --dir=DIR                The directory to store downloaded file."
 msgstr ""
 " -d, --dir=DIR                Verzeichnis zum Speichern der abgerufenen "
 "Datei."
 
-#: src/main.cc:163
+#: src/main.cc:108
 msgid " -o, --out=FILE               The file name for downloaded file."
 msgstr " -o, --out=FILE               Dateiname für die abgerufene Datei."
 
-#: src/main.cc:164
+#: src/main.cc:109
 msgid ""
 " -l, --log=LOG                The file path to store log. If '-' is "
 "specified,\n"
@@ -451,11 +459,11 @@ msgstr ""
 "                              wird das Log auf die Standardausgabe "
 "geschrieben."
 
-#: src/main.cc:166
+#: src/main.cc:111
 msgid " -D, --daemon                 Run as daemon."
 msgstr " -D, --daemon                 Start als Daemon-Prozeß."
 
-#: src/main.cc:167
+#: src/main.cc:112
 msgid ""
 " -s, --split=N                Download a file using N connections. N must "
 "be\n"
@@ -471,7 +479,7 @@ msgstr ""
 "                              Daher verbindet sich aria2 zu jeder URL mit\n"
 "                              N Verbindungen."
 
-#: src/main.cc:171
+#: src/main.cc:116
 msgid ""
 " --retry-wait=SEC             Set amount of time in second between requests\n"
 "                              for errors. Specify a value between 0 and 60.\n"
@@ -483,12 +491,12 @@ msgstr ""
 "und 60 an.\n"
 "                              Fehlwert: 5"
 
-#: src/main.cc:174
+#: src/main.cc:119
 msgid " -t, --timeout=SEC            Set timeout in second. Default: 60"
 msgstr ""
 " -t, --timeout=SEC            Setzt Wartezeit in Sekunden. Fehlwert: 60"
 
-#: src/main.cc:175
+#: src/main.cc:120
 msgid ""
 " -m, --max-tries=N            Set number of tries. 0 means unlimited.\n"
 "                              Default: 5"
@@ -496,12 +504,13 @@ msgstr ""
 " -m, --max-tries=N            Anzahl Versuche. 0 bedeutet unbegrenzt.\n"
 "                              Fehlwert: 5"
 
-#: src/main.cc:177
+#: src/main.cc:122
+#, fuzzy
 msgid ""
 " --min-segment-size=SIZE[K|M] Set minimum segment size. You can append\n"
 "                              K or M(1K = 1024, 1M = 1024K). This\n"
 "                              value must be greater than or equal to\n"
-"                              1024."
+"                              1024. Default: 1M"
 msgstr ""
 " --min-segment-size=SIZE[K|M] Setzt die minimale Segment-Größe. Sie können \n"
 "                              K oder M(1K = 1024, 1M = 1024K) anhängen. "
@@ -509,7 +518,7 @@ msgstr ""
 "                              Wert muss größer oder gleich \n"
 "                              1024 sein."
 
-#: src/main.cc:181
+#: src/main.cc:126
 msgid ""
 " --http-proxy=HOST:PORT       Use HTTP proxy server. This affects to all\n"
 "                              URLs."
@@ -517,26 +526,26 @@ msgstr ""
 " --http-proxy=HOST:PORT       HTTP-Proxyserver benutzen. Dies betrifft alle\n"
 "                              URLs."
 
-#: src/main.cc:183
+#: src/main.cc:128
 msgid " --http-user=USER             Set HTTP user. This affects to all URLs."
 msgstr ""
 " --http-user=USER             HTTP-Anwendername angeben. Dies betrifft alle "
 "URLs."
 
-#: src/main.cc:184
+#: src/main.cc:129
 msgid ""
 " --http-passwd=PASSWD         Set HTTP password. This affects to all URLs."
 msgstr ""
 " --http-passwd=PASSWD         HTTP-Passwort setzen. Dies betrifft alle URLs."
 
-#: src/main.cc:185
+#: src/main.cc:130
 msgid ""
 " --http-proxy-user=USER       Set HTTP proxy user. This affects to all URLs"
 msgstr ""
 " --http-proxy-user=USER       HTTP-Proxy-Anwender setzen. Dies betrifft alle "
 "URLs."
 
-#: src/main.cc:186
+#: src/main.cc:131
 msgid ""
 " --http-proxy-passwd=PASSWD   Set HTTP proxy password. This affects to all "
 "URLs."
@@ -544,7 +553,7 @@ msgstr ""
 " --http-proxy-passwd=PASSWD   HTTP-Proxy-Passwort setzen. Dies betrifft alle "
 "URLs."
 
-#: src/main.cc:187
+#: src/main.cc:132
 msgid ""
 " --http-proxy-method=METHOD   Set the method to use in proxy request.\n"
 "                              METHOD is either 'get' or 'tunnel'.\n"
@@ -555,7 +564,7 @@ msgstr ""
 "                              METHOD ist entweder 'get' oder 'tunnel'.\n"
 "                              Fehlwert: tunnel"
 
-#: src/main.cc:190
+#: src/main.cc:135
 msgid ""
 " --http-auth-scheme=SCHEME    Set HTTP authentication scheme. Currently, "
 "basic\n"
@@ -567,11 +576,11 @@ msgstr ""
 "                              das einzig zulässige Schema.\n"
 "                              Fehlwert: basic"
 
-#: src/main.cc:193
+#: src/main.cc:138
 msgid " --referer=REFERER            Set Referer. This affects to all URLs."
 msgstr " --referer=REFERER            Referer setzen. Dies betrifft alle URLs."
 
-#: src/main.cc:194
+#: src/main.cc:139
 msgid ""
 " --ftp-user=USER              Set FTP user. This affects to all URLs.\n"
 "                              Default: anonymous"
@@ -579,7 +588,7 @@ msgstr ""
 " --ftp-user=USER              FTP-Anwender setzen. Dies betrifft alle URLs.\n"
 "                              Fehlwert: anonymous"
 
-#: src/main.cc:196
+#: src/main.cc:141
 msgid ""
 " --ftp-passwd=PASSWD          Set FTP password. This affects to all URLs.\n"
 "                              Default: ARIA2USER@"
@@ -587,7 +596,7 @@ msgstr ""
 " --ftp-passwd=PASSWD          FTP-Passwort setzen. Dies betrifft alle URLs.\n"
 "                              Fehlwert: ARIA2USER@"
 
-#: src/main.cc:198
+#: src/main.cc:143
 msgid ""
 " --ftp-type=TYPE              Set FTP transfer type. TYPE is either "
 "'binary'\n"
@@ -599,11 +608,11 @@ msgstr ""
 "                              oder 'ascii'.\n"
 "                              Fehlwert: binary"
 
-#: src/main.cc:201
+#: src/main.cc:146
 msgid " -p, --ftp-pasv               Use passive mode in FTP."
 msgstr " -p, --ftp-pasv               Passiv-Modus für FTP benutzen."
 
-#: src/main.cc:202
+#: src/main.cc:147
 msgid ""
 " --ftp-via-http-proxy=METHOD  Use HTTP proxy in FTP. METHOD is either 'get' "
 "or\n"
@@ -615,11 +624,26 @@ msgstr ""
 "                              'tunnel'.\n"
 "                              Fehlwert: tunnel"
 
-#: src/main.cc:206
+#: src/main.cc:150
+msgid ""
+" --lowest-speed-limit         Close connection if download speed is lower "
+"than\n"
+"                              or equal to this value. 0 means aria2 does "
+"not\n"
+"                              care lowest speed limit. You can use K or M "
+"in\n"
+"                              the same manner as in --min-segment-size "
+"option.\n"
+"                              This option does not affect BitTorrent "
+"download.\n"
+"                              Default: 0"
+msgstr ""
+
+#: src/main.cc:157
 msgid " -T, --torrent-file=TORRENT_FILE  The file path to .torrent file."
 msgstr " -T, --torrent-file=TORRENT_FILE  Datenpfad zur torrent-Datei."
 
-#: src/main.cc:207
+#: src/main.cc:158
 msgid ""
 " --follow-torrent=true|false  Setting this option to false prevents aria2 "
 "to\n"
@@ -634,14 +658,14 @@ msgstr ""
 "                              auf .torrent endet.\n"
 "                              Fehlwert: true"
 
-#: src/main.cc:211
+#: src/main.cc:162
 msgid ""
 " -S, --show-files             Print file listing of .torrent file and exit."
 msgstr ""
 " -S, --show-files             Dateiliste der .torrent-Datei ausgeben und "
 "beenden."
 
-#: src/main.cc:212
+#: src/main.cc:163
 msgid ""
 " --direct-file-mapping=true|false Directly read from and write to each file\n"
 "                              mentioned in .torrent file.\n"
@@ -651,7 +675,7 @@ msgstr ""
 "                              .torrent-Datei erwähnten Datei.\n"
 "                              Fehlwert: true"
 
-#: src/main.cc:215
+#: src/main.cc:166
 msgid ""
 " --listen-port=PORT           Set port number to listen to for peer "
 "connection."
@@ -659,7 +683,7 @@ msgstr ""
 " --listen-port=PORT           Port-Nummer zum Lauschen auf Peer-Verbindungen "
 "setzen."
 
-#: src/main.cc:216
+#: src/main.cc:167
 msgid ""
 " --upload-limit=SPEED         Set upload speed limit in KB/sec. aria2 tries "
 "to\n"
@@ -671,7 +695,7 @@ msgstr ""
 "                              Sendegeschwindigkeit unter SPEED zu halten. 0 "
 "bedeutet keine Begrenzung."
 
-#: src/main.cc:218
+#: src/main.cc:169
 msgid ""
 " --select-file=INDEX...       Set file to download by specifing its index.\n"
 "                              You can know file index through --show-files\n"
@@ -691,12 +715,12 @@ msgstr ""
 "                              Sie können auch '-' verwenden wie in \"1-5\".\n"
 "                              ',' und '-' können zusammen benutzt werden."
 
-#: src/main.cc:226
+#: src/main.cc:177
 #, fuzzy
 msgid " -M, --metalink-file=METALINK_FILE The file path to .metalink file."
 msgstr " -T, --torrent-file=TORRENT_FILE  Datenpfad zur torrent-Datei."
 
-#: src/main.cc:227
+#: src/main.cc:178
 #, fuzzy
 msgid ""
 " -C, --metalink-servers=NUM_SERVERS The number of servers to connect to\n"
@@ -712,20 +736,20 @@ msgstr ""
 "                              auf .torrent endet.\n"
 "                              Fehlwert: true"
 
-#: src/main.cc:231
+#: src/main.cc:182
 msgid " --metalink-version=VERSION   The version of file to download."
 msgstr ""
 
-#: src/main.cc:232
+#: src/main.cc:183
 msgid " --metalink-language=LANGUAGE The language of file to download."
 msgstr ""
 
-#: src/main.cc:233
+#: src/main.cc:184
 msgid ""
 " --metalink-os=OS             The operating system the file is targeted."
 msgstr ""
 
-#: src/main.cc:234
+#: src/main.cc:185
 #, fuzzy
 msgid ""
 " --follow-metalink=true|false  Setting this option to false prevents aria2 "
@@ -741,15 +765,15 @@ msgstr ""
 "                              auf .torrent endet.\n"
 "                              Fehlwert: true"
 
-#: src/main.cc:239
+#: src/main.cc:190
 msgid " -v, --version                Print the version number and exit."
 msgstr " -v, --version                Versionsnummer ausgeben und beenden."
 
-#: src/main.cc:240
+#: src/main.cc:191
 msgid " -h, --help                   Print this message and exit."
 msgstr " -h, --help                   Diese Anzeige ausgeben und beenden."
 
-#: src/main.cc:243
+#: src/main.cc:194
 msgid ""
 " You can specify multiple URLs. All URLs must point to the same file\n"
 " or downloading fails."
@@ -758,7 +782,7 @@ msgstr ""
 "verweisen\n"
 "oder der Abruf schlägt fehl."
 
-#: src/main.cc:248
+#: src/main.cc:199
 msgid ""
 " Specify files in multi-file torrent to download. Use conjunction with\n"
 " -T option. This arguments are ignored if you specify --select-file option."
@@ -768,140 +792,137 @@ msgstr ""
 " -T-Option. Diese Argumente werden ignoriert, wenn sie die Option --select-"
 "file angeben."
 
-#: src/main.cc:252
+#: src/main.cc:203
 msgid "Examples:"
 msgstr "Beispiele:"
 
-#: src/main.cc:253
+#: src/main.cc:204
 msgid " Download a file by 1 connection:"
 msgstr " Abruf einer Datei über 1 Verbindung:"
 
-#: src/main.cc:255
+#: src/main.cc:206
 msgid " Download a file by 2 connections:"
 msgstr " Abruf einer Datei mit 2 Verbindungen:"
 
-#: src/main.cc:257
+#: src/main.cc:208
 msgid " Download a file by 2 connections, each connects to a different server:"
 msgstr ""
 " Abruf einer Datei über 2 Verbindungen, jede verbindet zu einem anderen "
 "Server:"
 
-#: src/main.cc:259
+#: src/main.cc:210
 msgid " You can mix up different protocols:"
 msgstr " Sie können verschiedene Protokolle mischen:"
 
-#: src/main.cc:263
+#: src/main.cc:214
 msgid " Download a torrent:"
 msgstr " Einen torrent abrufen:"
 
-#: src/main.cc:265
+#: src/main.cc:216
 msgid " Download a torrent using local .torrent file:"
 msgstr " Einen torrent mit einer lokalen .torrent-Datei abrufen:"
 
-#: src/main.cc:267
+#: src/main.cc:218
 msgid " Download only selected files:"
 msgstr " Nur ausgewählte Dateien abrufen:"
 
-#: src/main.cc:269
+#: src/main.cc:220
 msgid " Print file listing of .torrent file:"
 msgstr " Dateiliste einer .torrent-Datei ausgeben:"
 
-#: src/main.cc:274
+#: src/main.cc:225
 msgid " Metalink downloading:"
 msgstr ""
 
-#: src/main.cc:276
+#: src/main.cc:227
 #, fuzzy
 msgid " Download a file using local .metalink file:"
 msgstr " Einen torrent mit einer lokalen .torrent-Datei abrufen:"
 
-#: src/main.cc:278
+#: src/main.cc:229
 msgid " Metalink downloading with preferences:"
 msgstr ""
 
-#: src/main.cc:282
+#: src/main.cc:233
 #, c-format
 msgid "Report bugs to %s"
 msgstr "Fehler an %s melden"
 
-#: src/main.cc:446
+#: src/main.cc:358
 msgid "unrecognized proxy format"
 msgstr "nicht erkanntes Proxy-Format"
 
-#: src/main.cc:473
+#: src/main.cc:385
 msgid "Currently, supported authentication scheme is basic."
 msgstr "Derzeit unterstütztes Authentifizierungsschema ist basic."
 
-#: src/main.cc:482
+#: src/main.cc:394
 msgid "retry-wait must be between 0 and 60."
 msgstr "retry-wait muss zwischen 0 und 60 liegen."
 
-#: src/main.cc:499
+#: src/main.cc:411
 msgid "ftp-type must be either 'binary' or 'ascii'."
 msgstr "ftp-type muss entweder 'binary' oder 'ascii' sein."
 
-#: src/main.cc:508
+#: src/main.cc:420
 msgid "ftp-via-http-proxy must be either 'get' or 'tunnel'."
 msgstr "ftp-via-http-proxy muss entweder 'get' oder 'tunnel' sein."
 
-#: src/main.cc:526
+#: src/main.cc:428
 msgid "min-segment-size invalid"
 msgstr "min-segment-size ungültig"
 
-#: src/main.cc:537
+#: src/main.cc:439
 msgid "http-proxy-method must be either 'get' or 'tunnel'."
 msgstr "http-proxy-method muss entweder 'get' oder 'tunnel' sein."
 
-#: src/main.cc:545
+#: src/main.cc:447
 msgid "listen-port must be between 1024 and 65535."
 msgstr "listen-port muss zwischen 1024 und 65535 liegen."
 
-#: src/main.cc:556
+#: src/main.cc:460
 msgid "follow-torrent must be either 'true' or 'false'."
 msgstr "follow-torrent muss entweder 'true' oder 'false' sein."
 
-#: src/main.cc:570
+#: src/main.cc:474
 msgid "direct-file-mapping must be either 'true' or 'false'."
 msgstr "direct-file-mapping muss entweder 'true' oder 'false' sein."
 
-#: src/main.cc:578
+#: src/main.cc:482
 msgid "upload-limit must be greater than or equal to 0."
 msgstr "upload-limit muss größer oder gleich 0 sein."
 
-#: src/main.cc:603
+#: src/main.cc:507
 #, fuzzy
 msgid "follow-metalink must be either 'true' or 'false'."
 msgstr "follow-torrent muss entweder 'true' oder 'false' sein."
 
-#: src/main.cc:630
+#: src/main.cc:515
+#, fuzzy
+msgid "lowest-speed-limit must be greater than or equal to 0"
+msgstr "upload-limit muss größer oder gleich 0 sein."
+
+#: src/main.cc:544
 msgid "split must be between 1 and 5."
 msgstr "split muss zwischen 1 und 5 liegen."
 
-#: src/main.cc:640
+#: src/main.cc:556
 msgid "timeout must be between 1 and 600"
 msgstr "timeout muss zwischen 1 und 600 liegen."
 
-#: src/main.cc:649
+#: src/main.cc:565
 msgid "max-tries invalid"
 msgstr "max-tries ungültig"
 
-#: src/main.cc:671
+#: src/main.cc:587
 #, fuzzy
 msgid "metalink-servers must be greater than 0."
 msgstr "upload-limit muss größer oder gleich 0 sein."
 
-#: src/main.cc:689
+#: src/main.cc:607
 msgid "specify at least one URL"
 msgstr "Geben Sie zumindest eine URL an"
 
-#: src/main.cc:696
+#: src/main.cc:614
 msgid "daemon failed"
 msgstr "Daemon-Start nicht erfolgreich"
-
-#: src/main.cc:837
-msgid "Files:"
-msgstr "Dateien:"
-
-#: src/main.cc:868
-msgid "Errors occurred while binding port.\n"
-msgstr "Fehler beim Binden an Port aufgetreten.\n"


+ 126 - 105
po/ja.po

@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: aria2c 0.2.1\n"
 "Report-Msgid-Bugs-To: http://aria2.sourceforge.net/\n"
-"POT-Creation-Date: 2006-07-21 00:57+0900\n"
+"POT-Creation-Date: 2006-08-07 22:15+0900\n"
 "PO-Revision-Date: 2006-07-04 01:41+0900\n"
 "Last-Translator: Tatsuhiro Tsujikawa <tujikawa@rednoah.com>\n"
 "Language-Team: Japanese <ja@li.org>\n"
@@ -16,6 +16,23 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
 
+#: src/RequestInfo.h:76
+#, c-format
+msgid ""
+"\n"
+"The download was complete. <%s>\n"
+msgstr ""
+"\n"
+"<%s> のダウンロードが完了しました.\n"
+
+#: src/RequestInfo.h:84
+msgid ""
+"\n"
+"The download was not complete because of errors. Check the log.\n"
+msgstr ""
+"\n"
+"ダウンロードはエラーのため完了していません. ログを確認してください.\n"
+
 #: src/message.h:27
 #, c-format
 msgid "CUID#%d - The download for one segment completed successfully."
@@ -341,24 +358,15 @@ msgstr "
 msgid "Failed to peek data, cause: %s"
 msgstr "データの peek に失敗しました. 原因: %s"
 
-#: src/main.cc:76
-#, c-format
-msgid ""
-"\n"
-"The download was complete. <%s>\n"
-msgstr ""
-"\n"
-"<%s> のダウンロードが完了しました.\n"
+#: src/DownloadEngineFactory.cc:102
+msgid "Errors occurred while binding port.\n"
+msgstr "ポートをバインド中にエラーが発生しました.\n"
 
-#: src/main.cc:84
-msgid ""
-"\n"
-"The download was not complete because of errors. Check the log.\n"
-msgstr ""
-"\n"
-"ダウンロードはエラーのため完了していません. ログを確認してください.\n"
+#: src/TorrentRequestInfo.cc:71
+msgid "Files:"
+msgstr "ファイル:"
 
-#: src/main.cc:101
+#: src/UrlRequestInfo.cc:57
 msgid ""
 "\n"
 "stopping application...\n"
@@ -366,22 +374,22 @@ msgstr ""
 "\n"
 "アプリケーションを終了しています...\n"
 
-#: src/main.cc:107
+#: src/UrlRequestInfo.cc:62
 msgid "done\n"
 msgstr "完了\n"
 
-#: src/main.cc:123
+#: src/UrlRequestInfo.cc:86
 #, c-format
 msgid "Unrecognized URL or unsupported protocol: %s\n"
 msgstr ""
 "%s は, 理解できない URL フォーマット, または, サポートされないプロトコルで"
 "す.\n"
 
-#: src/main.cc:129
+#: src/main.cc:71
 msgid " version "
 msgstr " バージョン "
 
-#: src/main.cc:133
+#: src/main.cc:78
 msgid ""
 "This program is free software; you can redistribute it and/or modify\n"
 "it under the terms of the GNU General Public License as published by\n"
@@ -411,41 +419,41 @@ msgstr ""
 "along with this program; if not, write to the Free Software\n"
 "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n"
 
-#: src/main.cc:147
+#: src/main.cc:92
 #, c-format
 msgid "Contact Info: %s\n"
 msgstr "連絡先: %s\n"
 
-#: src/main.cc:153
+#: src/main.cc:98
 #, c-format
 msgid "Usage: %s [options] URL ...\n"
 msgstr "使い方: %s [オプション] URL ...\n"
 
-#: src/main.cc:155
+#: src/main.cc:100
 #, c-format
 msgid "       %s [options] -T TORRENT_FILE FILE ...\n"
 msgstr "        %s [オプション] -T TORRENT_FILE FILE ...\n"
 
-#: src/main.cc:158
+#: src/main.cc:103
 #, c-format
 msgid "       %s [options] -M METALINK_FILE\n"
 msgstr "        %s [オプション] -M METALINK_FILE\n"
 
-#: src/main.cc:161
+#: src/main.cc:106
 msgid "Options:"
 msgstr "オプション:"
 
-#: src/main.cc:162
+#: src/main.cc:107
 msgid " -d, --dir=DIR                The directory to store downloaded file."
 msgstr ""
 " -d, --dir=DIR                ダウンロードしたファイルを保存するディレクトリ."
 
-#: src/main.cc:163
+#: src/main.cc:108
 msgid " -o, --out=FILE               The file name for downloaded file."
 msgstr ""
 " -o, --out=FILE               ダウンロードしたファイルの保存先ファイル名."
 
-#: src/main.cc:164
+#: src/main.cc:109
 msgid ""
 " -l, --log=LOG                The file path to store log. If '-' is "
 "specified,\n"
@@ -455,11 +463,11 @@ msgstr ""
 "力\n"
 "                              に出力します."
 
-#: src/main.cc:166
+#: src/main.cc:111
 msgid " -D, --daemon                 Run as daemon."
 msgstr " -D, --daemon                 デーモンとして起動します."
 
-#: src/main.cc:167
+#: src/main.cc:112
 msgid ""
 " -s, --split=N                Download a file using N connections. N must "
 "be\n"
@@ -478,7 +486,7 @@ msgstr ""
 "ショ\n"
 "                              ンを確立します."
 
-#: src/main.cc:171
+#: src/main.cc:116
 msgid ""
 " --retry-wait=SEC             Set amount of time in second between requests\n"
 "                              for errors. Specify a value between 0 and 60.\n"
@@ -489,13 +497,13 @@ msgstr ""
 "                              す. 0 - 60 の値を指定してください.\n"
 "                              デフォルト値: 5"
 
-#: src/main.cc:174
+#: src/main.cc:119
 msgid " -t, --timeout=SEC            Set timeout in second. Default: 60"
 msgstr ""
 " -t, --timeout=SEC            タイムアウトとなる時間を秒で指定します.\n"
 "                              デフォルト値: 60"
 
-#: src/main.cc:175
+#: src/main.cc:120
 msgid ""
 " -m, --max-tries=N            Set number of tries. 0 means unlimited.\n"
 "                              Default: 5"
@@ -504,12 +512,13 @@ msgstr ""
 "行\n"
 "                              します. デフォルト値: 5"
 
-#: src/main.cc:177
+#: src/main.cc:122
+#, fuzzy
 msgid ""
 " --min-segment-size=SIZE[K|M] Set minimum segment size. You can append\n"
 "                              K or M(1K = 1024, 1M = 1024K). This\n"
 "                              value must be greater than or equal to\n"
-"                              1024."
+"                              1024. Default: 1M"
 msgstr ""
 " --min-segment-size=SIZE[K|M] 最小のセグメント・サイズを指定します. K または "
 "M\n"
@@ -517,7 +526,7 @@ msgstr ""
 "1024K).\n"
 "                              1024 以上の値を指定してください."
 
-#: src/main.cc:181
+#: src/main.cc:126
 msgid ""
 " --http-proxy=HOST:PORT       Use HTTP proxy server. This affects to all\n"
 "                              URLs."
@@ -526,14 +535,14 @@ msgstr ""
 "シ\n"
 "                              ョンはすべての URL に影響します."
 
-#: src/main.cc:183
+#: src/main.cc:128
 msgid " --http-user=USER             Set HTTP user. This affects to all URLs."
 msgstr ""
 " --http-user=USER             HTTP での認証ユーザーを指定します. このオプショ"
 "ン\n"
 "                              はすべての URL に影響します."
 
-#: src/main.cc:184
+#: src/main.cc:129
 msgid ""
 " --http-passwd=PASSWD         Set HTTP password. This affects to all URLs."
 msgstr ""
@@ -541,7 +550,7 @@ msgstr ""
 "ショ\n"
 "                              ンはすべての URL に影響します."
 
-#: src/main.cc:185
+#: src/main.cc:130
 msgid ""
 " --http-proxy-user=USER       Set HTTP proxy user. This affects to all URLs"
 msgstr ""
@@ -551,7 +560,7 @@ msgstr ""
 "ま\n"
 "                              す."
 
-#: src/main.cc:186
+#: src/main.cc:131
 msgid ""
 " --http-proxy-passwd=PASSWD   Set HTTP proxy password. This affects to all "
 "URLs."
@@ -562,7 +571,7 @@ msgstr ""
 "し\n"
 "                              ます."
 
-#: src/main.cc:187
+#: src/main.cc:132
 msgid ""
 " --http-proxy-method=METHOD   Set the method to use in proxy request.\n"
 "                              METHOD is either 'get' or 'tunnel'.\n"
@@ -573,7 +582,7 @@ msgstr ""
 "                              す. 'get' または 'tunnel' を指定してください.\n"
 "                              デフォルト値: tunnel"
 
-#: src/main.cc:190
+#: src/main.cc:135
 msgid ""
 " --http-auth-scheme=SCHEME    Set HTTP authentication scheme. Currently, "
 "basic\n"
@@ -585,14 +594,14 @@ msgstr ""
 "                              いるのは basic です. \n"
 "                              デフォルト値: basic"
 
-#: src/main.cc:193
+#: src/main.cc:138
 msgid " --referer=REFERER            Set Referer. This affects to all URLs."
 msgstr ""
 " --referer=REFERER            リファラーを指定します. このオプションはすべて"
 "の\n"
 "                               URL に影響します."
 
-#: src/main.cc:194
+#: src/main.cc:139
 msgid ""
 " --ftp-user=USER              Set FTP user. This affects to all URLs.\n"
 "                              Default: anonymous"
@@ -602,7 +611,7 @@ msgstr ""
 "                              はすべての URL に影響します.\n"
 "                              デフォルト値: anonymous"
 
-#: src/main.cc:196
+#: src/main.cc:141
 msgid ""
 " --ftp-passwd=PASSWD          Set FTP password. This affects to all URLs.\n"
 "                              Default: ARIA2USER@"
@@ -612,7 +621,7 @@ msgstr ""
 "                              ンはすべての URL に影響します.\n"
 "                              デフォルト値: ARIA2USER@"
 
-#: src/main.cc:198
+#: src/main.cc:143
 msgid ""
 " --ftp-type=TYPE              Set FTP transfer type. TYPE is either "
 "'binary'\n"
@@ -623,11 +632,11 @@ msgstr ""
 "                              'ascii' を指定してください. デフォルト値: "
 "binary"
 
-#: src/main.cc:201
+#: src/main.cc:146
 msgid " -p, --ftp-pasv               Use passive mode in FTP."
 msgstr " -p, --ftp-pasv               FTP で passive モードを使用します."
 
-#: src/main.cc:202
+#: src/main.cc:147
 msgid ""
 " --ftp-via-http-proxy=METHOD  Use HTTP proxy in FTP. METHOD is either 'get' "
 "or\n"
@@ -640,11 +649,26 @@ msgstr ""
 "く\n"
 "                              ださい. デフォルト値: tunnel"
 
-#: src/main.cc:206
+#: src/main.cc:150
+msgid ""
+" --lowest-speed-limit         Close connection if download speed is lower "
+"than\n"
+"                              or equal to this value. 0 means aria2 does "
+"not\n"
+"                              care lowest speed limit. You can use K or M "
+"in\n"
+"                              the same manner as in --min-segment-size "
+"option.\n"
+"                              This option does not affect BitTorrent "
+"download.\n"
+"                              Default: 0"
+msgstr ""
+
+#: src/main.cc:157
 msgid " -T, --torrent-file=TORRENT_FILE  The file path to .torrent file."
 msgstr " -T, --torrent-file=TORRENT_FILE  .torrent ファイルのパスを指定."
 
-#: src/main.cc:207
+#: src/main.cc:158
 msgid ""
 " --follow-torrent=true|false  Setting this option to false prevents aria2 "
 "to\n"
@@ -659,7 +683,7 @@ msgstr ""
 "                              は, BitTorrent モードに入りません.\n"
 "                              デフォルト値: true"
 
-#: src/main.cc:211
+#: src/main.cc:162
 msgid ""
 " -S, --show-files             Print file listing of .torrent file and exit."
 msgstr ""
@@ -667,7 +691,7 @@ msgstr ""
 "し\n"
 "                              終了します."
 
-#: src/main.cc:212
+#: src/main.cc:163
 msgid ""
 " --direct-file-mapping=true|false Directly read from and write to each file\n"
 "                              mentioned in .torrent file.\n"
@@ -678,14 +702,14 @@ msgstr ""
 "                              します.\n"
 "                              デフォルト値: true"
 
-#: src/main.cc:215
+#: src/main.cc:166
 msgid ""
 " --listen-port=PORT           Set port number to listen to for peer "
 "connection."
 msgstr ""
 " --listen-port=PORT           ピアからの接続を受け付けるポート番号を指定."
 
-#: src/main.cc:216
+#: src/main.cc:167
 msgid ""
 " --upload-limit=SPEED         Set upload speed limit in KB/sec. aria2 tries "
 "to\n"
@@ -698,7 +722,7 @@ msgstr ""
 "し\n"
 "                               ます. 0 は速度無制限を意味します."
 
-#: src/main.cc:218
+#: src/main.cc:169
 msgid ""
 " --select-file=INDEX...       Set file to download by specifing its index.\n"
 "                              You can know file index through --show-files\n"
@@ -719,11 +743,11 @@ msgstr ""
 "                              また, '-' を使って範囲指定もできます: \"1-5\"\n"
 "                              ',' と '-' は組み合わせて使うことができます."
 
-#: src/main.cc:226
+#: src/main.cc:177
 msgid " -M, --metalink-file=METALINK_FILE The file path to .metalink file."
 msgstr " -M, --metalink-file=METALINK_FILE .metalink ファイルのパスを指定."
 
-#: src/main.cc:227
+#: src/main.cc:178
 msgid ""
 " -C, --metalink-servers=NUM_SERVERS The number of servers to connect to\n"
 "                              simultaneously. If more than one connection "
@@ -737,15 +761,15 @@ msgstr ""
 "                              使用してください.\n"
 "                              デフォルト値: 15"
 
-#: src/main.cc:231
+#: src/main.cc:182
 msgid " --metalink-version=VERSION   The version of file to download."
 msgstr " --metalink-version=VERSION   ダウンロードするファイルのバージョン."
 
-#: src/main.cc:232
+#: src/main.cc:183
 msgid " --metalink-language=LANGUAGE The language of file to download."
 msgstr " --metalink-language=LANGUAGE ダウンロードするファイルの言語."
 
-#: src/main.cc:233
+#: src/main.cc:184
 msgid ""
 " --metalink-os=OS             The operating system the file is targeted."
 msgstr ""
@@ -753,7 +777,7 @@ msgstr ""
 "レー\n"
 "                              ティング・システム."
 
-#: src/main.cc:234
+#: src/main.cc:185
 msgid ""
 " --follow-metalink=true|false  Setting this option to false prevents aria2 "
 "to\n"
@@ -768,16 +792,16 @@ msgstr ""
 "                              は, Metalink モードに入りません.\n"
 "                              デフォルト値: true"
 
-#: src/main.cc:239
+#: src/main.cc:190
 msgid " -v, --version                Print the version number and exit."
 msgstr " -v, --version                バージョン番号を表示し, 終了します."
 
-#: src/main.cc:240
+#: src/main.cc:191
 msgid " -h, --help                   Print this message and exit."
 msgstr ""
 " -h, --help                   このヘルプメッセージを表示し, 終了します."
 
-#: src/main.cc:243
+#: src/main.cc:194
 msgid ""
 " You can specify multiple URLs. All URLs must point to the same file\n"
 " or downloading fails."
@@ -786,7 +810,7 @@ msgstr ""
 "れ\n"
 " ばなりません. さもなくばダウンロードは失敗します."
 
-#: src/main.cc:248
+#: src/main.cc:199
 msgid ""
 " Specify files in multi-file torrent to download. Use conjunction with\n"
 " -T option. This arguments are ignored if you specify --select-file option."
@@ -795,135 +819,132 @@ msgstr ""
 "ン\n"
 " と共に使用します. --select-file オプションと併用はできません."
 
-#: src/main.cc:252
+#: src/main.cc:203
 msgid "Examples:"
 msgstr "例:"
 
-#: src/main.cc:253
+#: src/main.cc:204
 msgid " Download a file by 1 connection:"
 msgstr " 1 コネクションでのダウンロード:"
 
-#: src/main.cc:255
+#: src/main.cc:206
 msgid " Download a file by 2 connections:"
 msgstr " 2 コネクションでのダウンロード:"
 
-#: src/main.cc:257
+#: src/main.cc:208
 msgid " Download a file by 2 connections, each connects to a different server:"
 msgstr " 二つの異なるサーバーに接続してダウンロード:"
 
-#: src/main.cc:259
+#: src/main.cc:210
 msgid " You can mix up different protocols:"
 msgstr " 異なるプロトコルを混合させてダウンロード:"
 
-#: src/main.cc:263
+#: src/main.cc:214
 msgid " Download a torrent:"
 msgstr " torrent をダウンロード:"
 
-#: src/main.cc:265
+#: src/main.cc:216
 msgid " Download a torrent using local .torrent file:"
 msgstr " ローカル .torrent ファイルを使ってダウンロード:"
 
-#: src/main.cc:267
+#: src/main.cc:218
 msgid " Download only selected files:"
 msgstr " ファイルを指定してダウンロード:"
 
-#: src/main.cc:269
+#: src/main.cc:220
 msgid " Print file listing of .torrent file:"
 msgstr " この .torrent ファイルに含まれるファイルリストを表示:"
 
-#: src/main.cc:274
+#: src/main.cc:225
 msgid " Metalink downloading:"
 msgstr " Metalink でダウンロード:"
 
-#: src/main.cc:276
+#: src/main.cc:227
 msgid " Download a file using local .metalink file:"
 msgstr " ローカル .metalink ファイルを使ってダウンロード:"
 
-#: src/main.cc:278
+#: src/main.cc:229
 msgid " Metalink downloading with preferences:"
 msgstr " ユーザ設定による Metalink ダウンロード:"
 
-#: src/main.cc:282
+#: src/main.cc:233
 #, c-format
 msgid "Report bugs to %s"
 msgstr "バグレポートはこちらへ: %s"
 
-#: src/main.cc:446
+#: src/main.cc:358
 msgid "unrecognized proxy format"
 msgstr "理解できないProxyフォーマットです."
 
-#: src/main.cc:473
+#: src/main.cc:385
 msgid "Currently, supported authentication scheme is basic."
 msgstr "現在サポートされている認証方法は basic です."
 
-#: src/main.cc:482
+#: src/main.cc:394
 msgid "retry-wait must be between 0 and 60."
 msgstr "retry-wait は 0 から 60 の間で指定してください."
 
-#: src/main.cc:499
+#: src/main.cc:411
 msgid "ftp-type must be either 'binary' or 'ascii'."
 msgstr "ftp-type は 'binary' または 'ascii' を指定してください."
 
-#: src/main.cc:508
+#: src/main.cc:420
 msgid "ftp-via-http-proxy must be either 'get' or 'tunnel'."
 msgstr "ftp-via-http-proxy は 'get' または 'tunnel' を指定してください."
 
-#: src/main.cc:526
+#: src/main.cc:428
 msgid "min-segment-size invalid"
 msgstr "min-segment-size が不正です."
 
-#: src/main.cc:537
+#: src/main.cc:439
 msgid "http-proxy-method must be either 'get' or 'tunnel'."
 msgstr "http-proxy-method は 'get' または 'tunnel' を指定してください."
 
-#: src/main.cc:545
+#: src/main.cc:447
 msgid "listen-port must be between 1024 and 65535."
 msgstr "listen-port は 1024 - 65535 の値を指定してください."
 
-#: src/main.cc:556
+#: src/main.cc:460
 msgid "follow-torrent must be either 'true' or 'false'."
 msgstr "follow-torrent は 'true' または 'false を指定してください."
 
-#: src/main.cc:570
+#: src/main.cc:474
 msgid "direct-file-mapping must be either 'true' or 'false'."
 msgstr "direct-file-mapping は 'true' または 'false を指定してください."
 
-#: src/main.cc:578
+#: src/main.cc:482
 msgid "upload-limit must be greater than or equal to 0."
 msgstr "upload-limit は 0 以上の数を指定してください."
 
-#: src/main.cc:603
+#: src/main.cc:507
 msgid "follow-metalink must be either 'true' or 'false'."
 msgstr "follow-metalink は 'true' または 'false を指定してください."
 
-#: src/main.cc:630
+#: src/main.cc:515
+#, fuzzy
+msgid "lowest-speed-limit must be greater than or equal to 0"
+msgstr "upload-limit は 0 以上の数を指定してください."
+
+#: src/main.cc:544
 msgid "split must be between 1 and 5."
 msgstr "split は 1 - 5 の値を指定してください."
 
-#: src/main.cc:640
+#: src/main.cc:556
 msgid "timeout must be between 1 and 600"
 msgstr "timeout は 1 - 600 の値を指定してください."
 
-#: src/main.cc:649
+#: src/main.cc:565
 msgid "max-tries invalid"
 msgstr "max-tries が不正です."
 
-#: src/main.cc:671
+#: src/main.cc:587
 msgid "metalink-servers must be greater than 0."
 msgstr "metalink-servers は 0 以上の数を指定してください."
 
-#: src/main.cc:689
+#: src/main.cc:607
 msgid "specify at least one URL"
 msgstr "一個以上の URL を指定してください."
 
-#: src/main.cc:696
+#: src/main.cc:614
 msgid "daemon failed"
 msgstr "デーモン起動に失敗"
-
-#: src/main.cc:837
-msgid "Files:"
-msgstr "ファイル:"
-
-#: src/main.cc:868
-msgid "Errors occurred while binding port.\n"
-msgstr "ポートをバインド中にエラーが発生しました.\n"

+ 12 - 8
src/AbstractDiskWriter.cc

@@ -30,17 +30,21 @@
 #include <errno.h>
 #include <fcntl.h>
 
-AbstractDiskWriter::AbstractDiskWriter():fd(0) {
+AbstractDiskWriter::AbstractDiskWriter():
+  fd(0)
+#ifdef ENABLE_MESSAGE_DIGEST				       
+  ,ctx(DIGEST_ALGO_SHA1)
+#endif // ENABLE_MESSAGE_DIGEST
+{
 #ifdef ENABLE_MESSAGE_DIGEST
-  ctx.setAlgo(MessageDigestContext::ALGO_SHA1);
-  digestInit(ctx);
+  ctx.digestInit();
 #endif // ENABLE_MESSAGE_DIGEST
 }
 
 AbstractDiskWriter::~AbstractDiskWriter() {
   closeFile();
 #ifdef ENABLE_MESSAGE_DIGEST
-  digestFree(ctx);
+  ctx.digestFree();
 #endif // ENABLE_MESSAGE_DIGEST
 }
 
@@ -100,7 +104,7 @@ int AbstractDiskWriter::readDataInternal(char* data, int len) {
 
 string AbstractDiskWriter::sha1Sum(long long int offset, long long int length) {
 #ifdef ENABLE_MESSAGE_DIGEST
-  digestReset(ctx);
+  ctx.digestReset();
   try {
     int BUFSIZE = 16*1024;
     char buf[BUFSIZE];
@@ -108,7 +112,7 @@ string AbstractDiskWriter::sha1Sum(long long int offset, long long int length) {
       if(BUFSIZE != readData(buf, BUFSIZE, offset)) {
 	throw string("error");
       }
-      digestUpdate(ctx, buf, BUFSIZE);
+      ctx.digestUpdate(buf, BUFSIZE);
       offset += BUFSIZE;
     }
     int r = length%BUFSIZE;
@@ -116,10 +120,10 @@ string AbstractDiskWriter::sha1Sum(long long int offset, long long int length) {
       if(r != readData(buf, r, offset)) {
 	throw string("error");
       }
-      digestUpdate(ctx, buf, r);
+      ctx.digestUpdate(buf, r);
     }
     unsigned char hashValue[20];
-    digestFinal(ctx, hashValue);
+    ctx.digestFinal(hashValue);
     return Util::toHex(hashValue, 20);
   } catch(string ex) {
     throw new DlAbortEx(EX_FILE_SHA1SUM, filename.c_str(), strerror(errno));

+ 64 - 0
src/Checksum.h

@@ -0,0 +1,64 @@
+/* <!-- 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_CHECKSUM_H_
+#define _D_CHECKSUM_H_
+
+#include "common.h"
+#include "messageDigest.h"
+
+#ifdef ENABLE_MESSAGE_DIGEST
+class Checksum {
+private:
+  string md;
+  MessageDigestContext::DigestAlgo algo;
+public:
+  Checksum(const string& md, MessageDigestContext::DigestAlgo algo):
+    md(md),
+    algo(algo) {}
+  Checksum():
+    algo(DIGEST_ALGO_SHA1) {}
+  ~Checksum() {}
+
+  bool isEmpty() const {
+    return md.size() == 0;
+  }
+
+  void setMessageDigest(const string& md) {
+    this->md = md;
+  }
+  const string& getMessageDigest() const {
+    return md;
+  }
+  
+  void setDigestAlgo(MessageDigestContext::DigestAlgo algo) {
+    this->algo = algo;
+  }
+  const MessageDigestContext::DigestAlgo& getDigestAlgo() const {
+    return algo;
+  }
+};
+#else
+class Checksum {
+};
+#endif // ENABLE_MESSAGE_DIGEST
+
+#endif // _D_CHECKSUM_H_

+ 10 - 1
src/DownloadCommand.cc

@@ -20,12 +20,14 @@
  */
 /* copyright --> */
 #include "DownloadCommand.h"
-#include <sys/time.h>
 #include "Util.h"
 #include "DlRetryEx.h"
+#include "DlAbortEx.h"
 #include "HttpInitiateConnectionCommand.h"
 #include "InitiateConnectionCommandFactory.h"
 #include "message.h"
+#include "prefs.h"
+#include <sys/time.h>
 
 DownloadCommand::DownloadCommand(int cuid, Request* req, DownloadEngine* e,
 				 const SocketHandle& s):
@@ -59,6 +61,13 @@ bool DownloadCommand::executeInternal(Segment seg) {
     seg.speed = (int)((seg.ds-lastSize)/(diff*1.0));
     sw.reset();
     lastSize = seg.ds;
+    int lowestLimit = e->option->getAsInt(PREF_LOWEST_SPEED_LIMIT);
+    if(lowestLimit > 0 && seg.speed <= lowestLimit) {
+      throw new DlAbortEx("CUID#%d - Too slow Downloading speed: %d <= %d(B/s)",
+			  cuid,
+			  seg.speed,
+			  lowestLimit);
+    }
   }
   if(e->segmentMan->totalSize != 0 && bufSize == 0) {
     throw new DlRetryEx(EX_GOT_EOF);

+ 90 - 69
src/DownloadEngine.cc

@@ -32,14 +32,13 @@
 
 using namespace std;
 
-DownloadEngine::DownloadEngine():noWait(false), segmentMan(NULL) {
+DownloadEngine::DownloadEngine():noWait(false), segmentMan(0) {
   logger = LogFactory::getInstance();
 }
 
 DownloadEngine::~DownloadEngine() {
-  if(segmentMan != NULL) {
-    delete segmentMan;
-  }
+  delete segmentMan;
+  cleanQueue();
 }
 
 void DownloadEngine::cleanQueue() {
@@ -66,7 +65,7 @@ public:
 void DownloadEngine::run() {
   initStatistics();
   Time cp;
-  CommandUuids activeCommandUuids;
+  CommandUuids activeUuids;
   while(!commands.empty()) {
     if(cp.elapsed(1)) {
       cp.reset();
@@ -79,8 +78,8 @@ void DownloadEngine::run() {
 	}
       }
     } else {
-      for(CommandUuids::iterator itr = activeCommandUuids.begin();
-	  itr != activeCommandUuids.end(); itr++) {
+      for(CommandUuids::iterator itr = activeUuids.begin();
+	  itr != activeUuids.end(); itr++) {
 	Commands::iterator comItr = find_if(commands.begin(), commands.end(),
 					    FindCommand(*itr));
 	assert(comItr != commands.end());
@@ -92,9 +91,9 @@ void DownloadEngine::run() {
       }
     }
     afterEachIteration();
-    activeCommandUuids.clear();
+    activeUuids.clear();
     if(!noWait && !commands.empty()) {
-      waitData(activeCommandUuids);
+      waitData(activeUuids);
     }
     noWait = false;
     calculateStatistics();
@@ -113,63 +112,86 @@ void DownloadEngine::shortSleep() const {
 
 class SetDescriptor {
 private:
-  fd_set* fds_ptr;
   int* max_ptr;
+  fd_set* rfds_ptr;
+  fd_set* wfds_ptr;
 public:
-  SetDescriptor(int* max_ptr, fd_set* fds_ptr)
-    :fds_ptr(fds_ptr), max_ptr(max_ptr) {}
-
-  void operator()(const SockCmdMap::value_type& pa) {
-    int fd = pa.first->getSockfd();
-    FD_SET(fd, fds_ptr);
+  SetDescriptor(int* max_ptr, fd_set* rfds_ptr, fd_set* wfds_ptr):
+    max_ptr(max_ptr),
+    rfds_ptr(rfds_ptr),
+    wfds_ptr(wfds_ptr) {}
+
+  void operator()(const SocketEntry& entry) {
+    int fd = entry.socket->getSockfd();
+    switch(entry.type) {
+    case SocketEntry::TYPE_RD:
+      FD_SET(fd, rfds_ptr);
+      break;
+    case SocketEntry::TYPE_WR:
+      FD_SET(fd, wfds_ptr);
+      break;
+    }
     if(*max_ptr < fd) {
       *max_ptr = fd;
     }
   }
 };
 
-class AccumulateActiveCommandUuid {
+class AccumulateActiveUuid {
 private:
-  CommandUuids* activeCommandUuids_ptr;
-  fd_set* fds_ptr;
+  CommandUuids* activeUuids_ptr;
+  fd_set* rfds_ptr;
+  fd_set* wfds_ptr;
 public:
-  AccumulateActiveCommandUuid(CommandUuids* activeCommandUuids_ptr,
-			      fd_set* fds_ptr)
-    :activeCommandUuids_ptr(activeCommandUuids_ptr), fds_ptr(fds_ptr) {}
-
-  void operator()(const SockCmdMap::value_type& pa) {
-    if(FD_ISSET(pa.first->getSockfd(), fds_ptr)) {
-      activeCommandUuids_ptr->push_back(pa.second);
+  AccumulateActiveUuid(CommandUuids* activeUuids_ptr,
+		       fd_set* rfds_ptr,
+		       fd_set* wfds_ptr):
+    activeUuids_ptr(activeUuids_ptr),
+    rfds_ptr(rfds_ptr),
+    wfds_ptr(wfds_ptr) {}
+
+  void operator()(const SocketEntry& entry) {
+    if(FD_ISSET(entry.socket->getSockfd(), rfds_ptr) ||
+       FD_ISSET(entry.socket->getSockfd(), wfds_ptr)) {
+      activeUuids_ptr->push_back(entry.commandUuid);
     }
+    /*
+    switch(entry.type) {
+    case SocketEntry::TYPE_RD:
+      if(FD_ISSET(entry.socket->getSockfd(), rfds_ptr)) {
+	activeUuids_ptr->push_back(entry.commandUuid);
+      }
+      break;
+    case SocketEntry::TYPE_WR:
+      if(FD_ISSET(entry.socket->getSockfd(), wfds_ptr)) {
+	activeUuids_ptr->push_back(entry.commandUuid);
+      }
+      break;
+    }
+    */
   }
 };
 
-void DownloadEngine::waitData(CommandUuids& activeCommandUuids) {
+void DownloadEngine::waitData(CommandUuids& activeUuids) {
   fd_set rfds;
   fd_set wfds;
   int retval = 0;
-  while(1) {
-    struct timeval tv;
-    
-    memcpy(&rfds, &rfdset, sizeof(fd_set));
-    memcpy(&wfds, &wfdset, sizeof(fd_set));
-
-    tv.tv_sec = 1;
-    tv.tv_usec = 0;
-    retval = select(fdmax+1, &rfds, &wfds, NULL, &tv);
-    if(retval != -1 || errno != EINTR) {
-      break;
-    }
-  }
+  struct timeval tv;
+  
+  memcpy(&rfds, &rfdset, sizeof(fd_set));
+  memcpy(&wfds, &wfdset, sizeof(fd_set));
+  
+  tv.tv_sec = 1;
+  tv.tv_usec = 0;
+  retval = select(fdmax+1, &rfds, &wfds, NULL, &tv);
   if(retval > 0) {
-    for_each(rsockmap.begin(), rsockmap.end(),
-	     AccumulateActiveCommandUuid(&activeCommandUuids, &rfds));
-    for_each(wsockmap.begin(), wsockmap.end(),
-	     AccumulateActiveCommandUuid(&activeCommandUuids, &wfds));
-    sort(activeCommandUuids.begin(), activeCommandUuids.end());
-    activeCommandUuids.erase(unique(activeCommandUuids.begin(),
-				activeCommandUuids.end()),
-			 activeCommandUuids.end());
+    for_each(socketEntries.begin(), socketEntries.end(),
+	     AccumulateActiveUuid(&activeUuids, &rfds, &wfds));
+	  
+    sort(activeUuids.begin(), activeUuids.end());
+    activeUuids.erase(unique(activeUuids.begin(),
+			     activeUuids.end()),
+		      activeUuids.end());
   }
 }
 
@@ -177,18 +199,15 @@ void DownloadEngine::updateFdSet() {
   fdmax = 0;
   FD_ZERO(&rfdset);
   FD_ZERO(&wfdset);
-  for_each(rsockmap.begin(), rsockmap.end(), SetDescriptor(&fdmax, &rfdset));
-  for_each(wsockmap.begin(), wsockmap.end(), SetDescriptor(&fdmax, &wfdset));
+  for_each(socketEntries.begin(), socketEntries.end(),
+	   SetDescriptor(&fdmax, &rfdset, &wfdset));
 }
 
-bool DownloadEngine::addSocket(SockCmdMap& sockmap,
-			       const SocketHandle& socket,
-			       const CommandUuid& commandUuid) {
-  SockCmdMap::iterator itr = find_if(sockmap.begin(), sockmap.end(),
-				     PairFind<SocketHandle, CommandUuid>(socket, commandUuid));
-  if(itr == sockmap.end()) {
-    SockCmdMap::value_type vt(socket, commandUuid);
-    sockmap.insert(vt);
+bool DownloadEngine::addSocket(const SocketEntry& entry) {
+  SocketEntries::iterator itr =
+    find(socketEntries.begin(), socketEntries.end(), entry);
+  if(itr == socketEntries.end()) {
+    socketEntries.push_back(entry);
     updateFdSet();
     return true;
   } else {
@@ -196,15 +215,13 @@ bool DownloadEngine::addSocket(SockCmdMap& sockmap,
   }
 }
 
-bool DownloadEngine::deleteSocket(SockCmdMap& sockmap,
-				  const SocketHandle& socket,
-				  const CommandUuid& commandUuid) {
-  SockCmdMap::iterator itr = find_if(sockmap.begin(), sockmap.end(),
-				     PairFind<SocketHandle, CommandUuid>(socket, commandUuid));
-  if(itr == sockmap.end()) {
+bool DownloadEngine::deleteSocket(const SocketEntry& entry) {
+  SocketEntries::iterator itr =
+    find(socketEntries.begin(), socketEntries.end(), entry);
+  if(itr == socketEntries.end()) {
     return false;
   } else {
-    sockmap.erase(itr);
+    socketEntries.erase(itr);
     updateFdSet();
     return true;
   }
@@ -212,20 +229,24 @@ bool DownloadEngine::deleteSocket(SockCmdMap& sockmap,
 
 bool DownloadEngine::addSocketForReadCheck(const SocketHandle& socket,
 					   const CommandUuid& commandUuid) {
-  return addSocket(rsockmap, socket, commandUuid);
+  SocketEntry entry(socket, commandUuid, SocketEntry::TYPE_RD);
+  return addSocket(entry);
 }
 
 bool DownloadEngine::deleteSocketForReadCheck(const SocketHandle& socket,
 					      const CommandUuid& commandUuid) {
-  return deleteSocket(rsockmap, socket, commandUuid);
+  SocketEntry entry(socket, commandUuid, SocketEntry::TYPE_RD);
+  return deleteSocket(entry);
 }
 
 bool DownloadEngine::addSocketForWriteCheck(const SocketHandle& socket,
 					    const CommandUuid& commandUuid) {
-  return addSocket(wsockmap, socket, commandUuid);
+  SocketEntry entry(socket, commandUuid, SocketEntry::TYPE_WR);
+  return addSocket(entry);
 }
 
 bool DownloadEngine::deleteSocketForWriteCheck(const SocketHandle& socket,
 					       const CommandUuid& commandUuid) {
-  return deleteSocket(wsockmap, socket, commandUuid);
+  SocketEntry entry(socket, commandUuid, SocketEntry::TYPE_WR);
+  return deleteSocket(entry);
 }

+ 30 - 25
src/DownloadEngine.h

@@ -32,22 +32,44 @@
 typedef deque<SocketHandle> Sockets;
 typedef deque<Command*> Commands;
 typedef deque<CommandUuid> CommandUuids;
-typedef multimap<SocketHandle, int> SockCmdMap;
+
+class SocketEntry {
+public:
+  enum TYPE {
+    TYPE_RD,
+    TYPE_WR,
+  };
+
+  SocketHandle socket;
+  CommandUuid commandUuid;
+  TYPE type;
+public:
+  SocketEntry(const SocketHandle& socket,
+	      const CommandUuid& commandUuid,
+	      TYPE type):
+    socket(socket), commandUuid(commandUuid), type(type) {}
+  ~SocketEntry() {}
+
+  bool operator==(const SocketEntry& entry) {
+    return socket == entry.socket &&
+      commandUuid == entry.commandUuid &&
+      type == entry.type;
+  }
+};
+
+typedef deque<SocketEntry> SocketEntries;
 
 class DownloadEngine {
 private:
-  void waitData(CommandUuids& activeCommandUuids);
-  SockCmdMap rsockmap;
-  SockCmdMap wsockmap;
+  void waitData(CommandUuids& activeUuids);
+  SocketEntries socketEntries;
   fd_set rfdset;
   fd_set wfdset;
   int fdmax;
 
   void shortSleep() const;
-  bool addSocket(SockCmdMap& sockmap, const SocketHandle& socket,
-		 const CommandUuid& commandUuid);
-  bool deleteSocket(SockCmdMap& sockmap, const SocketHandle& socket,
-		    const CommandUuid& commandUuid);
+  bool addSocket(const SocketEntry& socketEntry);
+  bool deleteSocket(const SocketEntry& socketEntry);
 protected:
   const Logger* logger;
   virtual void initStatistics() = 0;
@@ -80,22 +102,5 @@ public:
   
 };
 
-template<class T1, class T2>
-class PairFind {
-private:
-  T1 first;
-  T2 second;
-public:
-  PairFind(T1 t1, T2 t2):first(t1), second(t2) {}
-
-  bool operator()(const pair<T1, T2>& pa) {
-    if(pa.first == first && pa.second == second) {
-      return true;
-    } else {
-      return false;
-    }
-  }
-};
-
 #endif // _D_DOWNLOAD_ENGINE_H_
 

+ 123 - 0
src/DownloadEngineFactory.cc

@@ -0,0 +1,123 @@
+/* <!-- 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 "DownloadEngineFactory.h"
+#include "prefs.h"
+#include "DefaultDiskWriter.h"
+#include "SplitSlowestSegmentSplitter.h"
+#include "InitiateConnectionCommandFactory.h"
+#include "ByteArrayDiskWriter.h"
+#include "Util.h"
+#ifdef ENABLE_BITTORRENT
+# include "PeerListenCommand.h"
+# include "TrackerWatcherCommand.h"
+# include "TrackerUpdateCommand.h"
+# include "TorrentAutoSaveCommand.h"
+# include "PeerChokeCommand.h"
+# include "HaveEraseCommand.h"
+#endif // ENABLE_BITTORRENT
+
+ConsoleDownloadEngine*
+DownloadEngineFactory::newConsoleEngine(const Option* op,
+					const Requests& requests,
+					const Requests& reserved)
+{
+  ConsoleDownloadEngine* e = new ConsoleDownloadEngine();
+  e->option = op;
+  e->segmentMan = new SegmentMan();
+  e->segmentMan->diskWriter = new DefaultDiskWriter();
+  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));
+  e->segmentMan->reserved = reserved;
+  
+  int cuidCounter = 1;
+  for(Requests::const_iterator itr = requests.begin();
+      itr != requests.end();
+      itr++, cuidCounter++) {
+    e->commands.push_back(InitiateConnectionCommandFactory::createInitiateConnectionCommand(cuidCounter, *itr, e));
+  }
+  return e;
+}
+
+#ifdef ENABLE_BITTORRENT
+TorrentConsoleDownloadEngine*
+DownloadEngineFactory::newTorrentConsoleEngine(const Option* op,
+					       const string& torrentFile,
+					       const Strings& targetFiles)
+{
+  Request* req = new Request();
+  req->isTorrent = true;
+  req->setTrackerEvent(Request::STARTED);
+  TorrentConsoleDownloadEngine* te = new TorrentConsoleDownloadEngine();
+  te->option = op;
+  ByteArrayDiskWriter* byteArrayDiskWriter = new ByteArrayDiskWriter();
+  te->segmentMan = new SegmentMan();
+  te->segmentMan->diskWriter = byteArrayDiskWriter;
+  te->segmentMan->option = op;
+  te->segmentMan->splitter = new SplitSlowestSegmentSplitter();
+  te->segmentMan->splitter->setMinSegmentSize(op->getAsLLInt(PREF_MIN_SEGMENT_SIZE));
+  te->torrentMan = new TorrentMan();
+  te->torrentMan->setStoreDir(op->get(PREF_DIR));
+  te->torrentMan->option = op;
+  te->torrentMan->req = req;
+  Integers selectIndexes;
+  Util::unfoldRange(op->get(PREF_SELECT_FILE), selectIndexes);
+  if(selectIndexes.size()) {
+    te->torrentMan->setup(torrentFile, selectIndexes);
+  } else {
+    te->torrentMan->setup(torrentFile, targetFiles);
+  }
+
+  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 {
+    port = listenCommand->bindPort(listenPort, listenPort);
+  }
+  if(port == -1) {
+    printf(_("Errors occurred while binding port.\n"));
+    exit(EXIT_FAILURE);
+  }
+  te->torrentMan->setPort(port);
+  te->commands.push_back(listenCommand);
+  
+  te->commands.push_back(new TrackerWatcherCommand(te->torrentMan->getNewCuid(),
+						   te,
+						   te->torrentMan->minInterval));
+  te->commands.push_back(new TrackerUpdateCommand(te->torrentMan->getNewCuid(),
+						  te));
+  te->commands.push_back(new TorrentAutoSaveCommand(te->torrentMan->getNewCuid(),
+						    te,
+						    op->getAsInt(PREF_AUTO_SAVE_INTERVAL)));
+  te->commands.push_back(new PeerChokeCommand(te->torrentMan->getNewCuid(),
+					      te, 10));
+  te->commands.push_back(new HaveEraseCommand(te->torrentMan->getNewCuid(),
+					      te, 10));
+  
+  return te;
+}
+#endif // ENABLE_BITTORRENT

+ 46 - 0
src/DownloadEngineFactory.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_DOWNLOAD_ENGINE_FACTORY_H_
+#define _D_DOWNLOAD_ENGINE_FACTORY_H_
+
+#include "common.h"
+#include "ConsoleDownloadEngine.h"
+#ifdef ENABLE_BITTORRENT
+# include "TorrentConsoleDownloadEngine.h"
+#endif // ENABLE_BITTORRENT
+
+class DownloadEngineFactory {
+public:
+  static ConsoleDownloadEngine*
+  newConsoleEngine(const Option* option,
+		   const Requests& requests,
+		   const Requests& reserved);
+
+#ifdef ENABLE_BITTORRENT
+  static TorrentConsoleDownloadEngine*
+  newTorrentConsoleEngine(const Option* option,
+			  const string& torrentFile,
+			  const Strings& targetFiles);
+#endif // ENABLE_BITTORRENT
+};
+
+#endif // _D_DOWNLOAD_ENGINE_FACTORY_H_

+ 3 - 3
src/FtpNegotiationCommand.cc

@@ -57,6 +57,9 @@ bool FtpNegotiationCommand::executeInternal(Segment segment) {
 
 bool FtpNegotiationCommand::recvGreeting() {
   socket->setBlockingMode();
+  disableWriteCheckSocket();
+  setReadCheckSocket(socket);
+
   int status = ftp->receiveResponse();
   if(status == 0) {
     return false;
@@ -66,9 +69,6 @@ bool FtpNegotiationCommand::recvGreeting() {
   }
   sequence = SEQ_SEND_USER;
 
-  setReadCheckSocket(socket);
-  disableWriteCheckSocket();
-
   return true;
 }
 

+ 10 - 5
src/Makefile.am

@@ -52,7 +52,10 @@ SRCS =  Socket.h\
 	NullLogger.h\
 	Time.cc Time.h\
 	SharedHandle.h\
-	FeatureConfig.cc FeatureConfig.h
+	FeatureConfig.cc FeatureConfig.h\
+	DownloadEngineFactory.cc DownloadEngineFactory.h\
+	RequestInfo.h\
+	UrlRequestInfo.cc UrlRequestInfo.h
 
 if ENABLE_BITTORRENT
 SRCS += MetaEntry.h\
@@ -108,7 +111,8 @@ SRCS += MetaEntry.h\
 	SuggestPieceMessage.cc SuggestPieceMessage.h\
 	SimplePeerMessage.cc SimplePeerMessage.h\
 	PeerMessageFactory.cc PeerMessageFactory.h\
-	HaveEraseCommand.cc HaveEraseCommand.h
+	HaveEraseCommand.cc HaveEraseCommand.h\
+	TorrentRequestInfo.cc TorrentRequestInfo.h
 endif # ENABLE_BITTORRENT
 
 if ENABLE_METALINK
@@ -116,15 +120,16 @@ SRCS += Metalinker.cc Metalinker.h\
 	MetalinkEntry.cc MetalinkEntry.h\
 	MetalinkResource.cc MetalinkResource.h\
 	MetalinkProcessor.h\
-	Xml2MetalinkProcessor.cc Xml2MetalinkProcessor.h
+	Xml2MetalinkProcessor.cc Xml2MetalinkProcessor.h\
+	MetalinkRequestInfo.cc MetalinkRequestInfo.h
 endif # ENABLE_METALINK
 
 noinst_LIBRARIES = libaria2c.a
 libaria2c_a_SOURCES = $(SRCS)
 aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\
 	@LIBGCRYPT_LIBS@ @OPENSSL_LIBS@ @XML_LIBS@
-aria2c_LDFLAGS = -pg
+#aria2c_LDFLAGS = -pg
 AM_CPPFLAGS =  -Wall\
 	-I../lib -I../intl -I$(top_srcdir)/intl\
 	@LIBGNUTLS_CFLAGS@ @LIBGCRYPT_CFLAGS@ @OPENSSL_CFLAGS@ @XML_CPPFLAGS@\
-	-D_FILE_OFFSET_BITS=64 -DLOCALEDIR=\"$(localedir)\" @DEFS@ -pg
+	-D_FILE_OFFSET_BITS=64 -DLOCALEDIR=\"$(localedir)\" @DEFS@# -pg

+ 31 - 17
src/Makefile.in

@@ -91,13 +91,15 @@ bin_PROGRAMS = aria2c$(EXEEXT)
 @ENABLE_BITTORRENT_TRUE@	SuggestPieceMessage.cc SuggestPieceMessage.h\
 @ENABLE_BITTORRENT_TRUE@	SimplePeerMessage.cc SimplePeerMessage.h\
 @ENABLE_BITTORRENT_TRUE@	PeerMessageFactory.cc PeerMessageFactory.h\
-@ENABLE_BITTORRENT_TRUE@	HaveEraseCommand.cc HaveEraseCommand.h
+@ENABLE_BITTORRENT_TRUE@	HaveEraseCommand.cc HaveEraseCommand.h\
+@ENABLE_BITTORRENT_TRUE@	TorrentRequestInfo.cc TorrentRequestInfo.h
 
 @ENABLE_METALINK_TRUE@am__append_2 = Metalinker.cc Metalinker.h\
 @ENABLE_METALINK_TRUE@	MetalinkEntry.cc MetalinkEntry.h\
 @ENABLE_METALINK_TRUE@	MetalinkResource.cc MetalinkResource.h\
 @ENABLE_METALINK_TRUE@	MetalinkProcessor.h\
-@ENABLE_METALINK_TRUE@	Xml2MetalinkProcessor.cc Xml2MetalinkProcessor.h
+@ENABLE_METALINK_TRUE@	Xml2MetalinkProcessor.cc Xml2MetalinkProcessor.h\
+@ENABLE_METALINK_TRUE@	MetalinkRequestInfo.cc MetalinkRequestInfo.h
 
 subdir = src
 DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in alloca.c
@@ -155,13 +157,14 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
 	AbstractDiskWriter.h File.cc File.h Option.cc Option.h \
 	Base64.cc Base64.h CookieBox.cc CookieBox.h messageDigest.h \
 	LogFactory.cc LogFactory.h NullLogger.h Time.cc Time.h \
-	SharedHandle.h FeatureConfig.cc FeatureConfig.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 TorrentMan.cc TorrentMan.h \
-	PeerConnection.cc PeerConnection.h PeerMessageUtil.cc \
-	PeerMessageUtil.h PeerAbstractCommand.cc PeerAbstractCommand.h \
-	PeerInitiateConnectionCommand.cc \
+	SharedHandle.h FeatureConfig.cc FeatureConfig.h \
+	DownloadEngineFactory.cc DownloadEngineFactory.h RequestInfo.h \
+	UrlRequestInfo.cc UrlRequestInfo.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 \
+	TorrentMan.cc TorrentMan.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 BitfieldMan.cc \
 	BitfieldMan.h TorrentDownloadEngine.cc TorrentDownloadEngine.h \
@@ -191,9 +194,11 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
 	SuggestPieceMessage.cc SuggestPieceMessage.h \
 	SimplePeerMessage.cc SimplePeerMessage.h PeerMessageFactory.cc \
 	PeerMessageFactory.h HaveEraseCommand.cc HaveEraseCommand.h \
-	Metalinker.cc Metalinker.h MetalinkEntry.cc MetalinkEntry.h \
+	TorrentRequestInfo.cc TorrentRequestInfo.h Metalinker.cc \
+	Metalinker.h MetalinkEntry.cc MetalinkEntry.h \
 	MetalinkResource.cc MetalinkResource.h MetalinkProcessor.h \
-	Xml2MetalinkProcessor.cc Xml2MetalinkProcessor.h
+	Xml2MetalinkProcessor.cc Xml2MetalinkProcessor.h \
+	MetalinkRequestInfo.cc MetalinkRequestInfo.h
 @ENABLE_BITTORRENT_TRUE@am__objects_1 = Data.$(OBJEXT) \
 @ENABLE_BITTORRENT_TRUE@	Dictionary.$(OBJEXT) List.$(OBJEXT) \
 @ENABLE_BITTORRENT_TRUE@	MetaFileUtil.$(OBJEXT) \
@@ -241,11 +246,13 @@ am__libaria2c_a_SOURCES_DIST = Socket.h SocketCore.cc SocketCore.h \
 @ENABLE_BITTORRENT_TRUE@	SuggestPieceMessage.$(OBJEXT) \
 @ENABLE_BITTORRENT_TRUE@	SimplePeerMessage.$(OBJEXT) \
 @ENABLE_BITTORRENT_TRUE@	PeerMessageFactory.$(OBJEXT) \
-@ENABLE_BITTORRENT_TRUE@	HaveEraseCommand.$(OBJEXT)
+@ENABLE_BITTORRENT_TRUE@	HaveEraseCommand.$(OBJEXT) \
+@ENABLE_BITTORRENT_TRUE@	TorrentRequestInfo.$(OBJEXT)
 @ENABLE_METALINK_TRUE@am__objects_2 = Metalinker.$(OBJEXT) \
 @ENABLE_METALINK_TRUE@	MetalinkEntry.$(OBJEXT) \
 @ENABLE_METALINK_TRUE@	MetalinkResource.$(OBJEXT) \
-@ENABLE_METALINK_TRUE@	Xml2MetalinkProcessor.$(OBJEXT)
+@ENABLE_METALINK_TRUE@	Xml2MetalinkProcessor.$(OBJEXT) \
+@ENABLE_METALINK_TRUE@	MetalinkRequestInfo.$(OBJEXT)
 am__objects_3 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \
 	AbstractCommand.$(OBJEXT) \
 	InitiateConnectionCommandFactory.$(OBJEXT) \
@@ -269,7 +276,8 @@ am__objects_3 = SocketCore.$(OBJEXT) Command.$(OBJEXT) \
 	PreAllocationDiskWriter.$(OBJEXT) AbstractDiskWriter.$(OBJEXT) \
 	File.$(OBJEXT) Option.$(OBJEXT) Base64.$(OBJEXT) \
 	CookieBox.$(OBJEXT) LogFactory.$(OBJEXT) Time.$(OBJEXT) \
-	FeatureConfig.$(OBJEXT) $(am__objects_1) $(am__objects_2)
+	FeatureConfig.$(OBJEXT) DownloadEngineFactory.$(OBJEXT) \
+	UrlRequestInfo.$(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)"
@@ -459,17 +467,19 @@ SRCS = Socket.h SocketCore.cc SocketCore.h Command.cc Command.h \
 	Base64.cc Base64.h CookieBox.cc CookieBox.h messageDigest.h \
 	LogFactory.cc LogFactory.h NullLogger.h Time.cc Time.h \
 	SharedHandle.h FeatureConfig.cc FeatureConfig.h \
-	$(am__append_1) $(am__append_2)
+	DownloadEngineFactory.cc DownloadEngineFactory.h RequestInfo.h \
+	UrlRequestInfo.cc UrlRequestInfo.h $(am__append_1) \
+	$(am__append_2)
 noinst_LIBRARIES = libaria2c.a
 libaria2c_a_SOURCES = $(SRCS)
 aria2c_LDADD = libaria2c.a @LIBINTL@ @ALLOCA@ @LIBGNUTLS_LIBS@\
 	@LIBGCRYPT_LIBS@ @OPENSSL_LIBS@ @XML_LIBS@
 
-aria2c_LDFLAGS = -pg
+#aria2c_LDFLAGS = -pg
 AM_CPPFLAGS = -Wall\
 	-I../lib -I../intl -I$(top_srcdir)/intl\
 	@LIBGNUTLS_CFLAGS@ @LIBGCRYPT_CFLAGS@ @OPENSSL_CFLAGS@ @XML_CPPFLAGS@\
-	-D_FILE_OFFSET_BITS=64 -DLOCALEDIR=\"$(localedir)\" @DEFS@ -pg
+	-D_FILE_OFFSET_BITS=64 -DLOCALEDIR=\"$(localedir)\" @DEFS@# -pg
 
 all: all-am
 
@@ -567,6 +577,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DiskAdaptor.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DownloadCommand.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DownloadEngine.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/DownloadEngineFactory.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FeatureConfig.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/File.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FtpConnection.Po@am__quote@
@@ -595,6 +606,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/LogFactory.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetaFileUtil.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkEntry.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkRequestInfo.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetalinkResource.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Metalinker.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MultiDiskAdaptor.Po@am__quote@
@@ -635,9 +647,11 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentConsoleDownloadEngine.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentDownloadEngine.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentMan.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TorrentRequestInfo.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TrackerUpdateCommand.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TrackerWatcherCommand.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UnchokeMessage.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UrlRequestInfo.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Util.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xml2MetalinkProcessor.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@

+ 5 - 24
src/MetalinkEntry.cc

@@ -29,30 +29,6 @@ MetalinkEntry::~MetalinkEntry() {
   for_each(resources.begin(), resources.end(), Deleter());
 }
 
-bool MetalinkEntry::check(const string& filename) const {
-#ifdef ENABLE_MESSAGE_DIGEST
-  unsigned char buf[20];
-  int digestLength;
-  const string* digestPtr;
-  MessageDigestContext::HashAlgo algo;
-  if(!sha1.empty()) {
-    digestLength = 20;
-    algo = MessageDigestContext::ALGO_SHA1;
-    digestPtr = &sha1;
-  } else if(!md5.empty()) {
-    digestLength = 16;
-    algo = MessageDigestContext::ALGO_MD5;
-    digestPtr = &md5;
-  } else {
-    return true;
-  }
-  Util::fileChecksum(filename, buf, algo);
-  return *digestPtr == Util::toHex(buf, digestLength);
-#else
-  return true;
-#endif //ENABLE_MESSAGE_DIGEST
-}
-
 class PrefOrder {
 public:
   bool operator()(const MetalinkResource* res1, const MetalinkResource* res2) {
@@ -71,6 +47,10 @@ public:
     switch(res->type) {
     case MetalinkResource::TYPE_FTP:
     case MetalinkResource::TYPE_HTTP:
+    case MetalinkResource::TYPE_HTTPS:
+#ifdef ENABLE_BITTORRENT
+    case MetalinkResource::TYPE_BITTORRENT:
+#endif // ENABLE_BITTORRENT
       return true;
     default:
       return false;
@@ -81,5 +61,6 @@ public:
 void MetalinkEntry::dropUnsupportedResource() {
   MetalinkResources::iterator split =
     partition(resources.begin(), resources.end(), Supported());
+  for_each(split, resources.end(), Deleter());
   resources.erase(split, resources.end());
 }

+ 3 - 6
src/MetalinkEntry.h

@@ -24,6 +24,7 @@
 
 #include "common.h"
 #include "MetalinkResource.h"
+#include "Checksum.h"
 #include <deque>
 
 typedef deque<MetalinkResource*> MetalinkResources;
@@ -35,8 +36,7 @@ public:
   string language;
   string os;
   long long int size;
-  string  md5;
-  string  sha1;
+  Checksum checksum;
 public:
   MetalinkResources resources;
 public:
@@ -50,14 +50,11 @@ public:
       this->language = metalinkEntry.language;
       this->os = metalinkEntry.os;
       this->size = metalinkEntry.size;
-      this->md5 = metalinkEntry.md5;
-      this->sha1 = metalinkEntry.sha1;
+      this->checksum = metalinkEntry.checksum;
     }
     return *this;
   }
 
-  bool check(const string& filename) const;
-
   void dropUnsupportedResource();
 
   void reorderResourcesByPreference();

+ 111 - 0
src/MetalinkRequestInfo.cc

@@ -0,0 +1,111 @@
+/* <!-- 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 "MetalinkRequestInfo.h"
+#include "Xml2MetalinkProcessor.h"
+#include "prefs.h"
+#include "DlAbortEx.h"
+#include "UrlRequestInfo.h"
+
+class AccumulateNonP2PUrl {
+private:
+  Strings* urlsPtr;
+  int split;
+public:
+  AccumulateNonP2PUrl(Strings* urlsPtr,
+		int split)
+    :urlsPtr(urlsPtr),
+     split(split) {}
+
+  void operator()(const MetalinkResource* resource) {
+    switch(resource->type) {
+    case MetalinkResource::TYPE_HTTP:
+    case MetalinkResource::TYPE_HTTPS:
+    case MetalinkResource::TYPE_FTP:
+      for(int s = 1; s <= split; s++) {
+	urlsPtr->push_back(resource->url);
+      }
+      break;
+    }
+  }
+};
+
+class FindBitTorrentUrl {
+public:
+  FindBitTorrentUrl() {}
+
+  bool operator()(const MetalinkResource* resource) {
+    if(resource->type == MetalinkResource::TYPE_BITTORRENT) {
+      return true;
+    } else {
+      return false;
+    }
+  }
+};
+
+RequestInfo* MetalinkRequestInfo::execute() {
+  RequestInfo* next = 0;
+  Xml2MetalinkProcessor proc;
+  Metalinker* metalinker = 0;
+  try {
+    metalinker = proc.parseFile(metalinkFile);
+    
+    MetalinkEntry* entry =
+      metalinker->queryEntry(op->get(PREF_METALINK_VERSION),
+			     op->get(PREF_METALINK_LANGUAGE),
+			     op->get(PREF_METALINK_OS));
+    if(entry == 0) {
+      printf("No file matched with your preference.\n");
+      throw new DlAbortEx("No file matched with your preference.");
+    }
+    entry->dropUnsupportedResource();
+    MetalinkResources::iterator itr =
+      find_if(entry->resources.begin(),
+	      entry->resources.end(),
+	      FindBitTorrentUrl());
+    Strings urls;
+    int maxConnection = 0;
+    Checksum checksum;
+    if(itr == entry->resources.end()) {
+      entry->reorderResourcesByPreference();
+	
+      for_each(entry->resources.begin(), entry->resources.end(),
+	       AccumulateNonP2PUrl(&urls, op->getAsInt(PREF_SPLIT)));
+      maxConnection =
+	op->getAsInt(PREF_METALINK_SERVERS)*op->getAsInt(PREF_SPLIT);
+	
+      // TODO
+      // set checksum
+      checksum = entry->checksum;
+    } else {
+      // BitTorrent downloading
+      urls.push_back((*itr)->url);
+    }
+    next = new UrlRequestInfo(urls, maxConnection, op);
+    next->setChecksum(checksum);
+  } catch(Exception* e) {
+    logger->error("Exception caught", e);
+    delete e;
+    fail = true;
+  }
+  delete metalinker;
+  return next;
+}

+ 41 - 0
src/MetalinkRequestInfo.h

@@ -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 --> */
+#ifndef _D_METALINK_REQUEST_INFO_H_
+#define _D_METALINK_REQUEST_INFO_H_
+
+#include "RequestInfo.h"
+
+class MetalinkRequestInfo : public RequestInfo {
+private:
+  string metalinkFile;
+public:
+  MetalinkRequestInfo(const string& metalinkFile, const Option* op):
+    RequestInfo(op),
+    metalinkFile(metalinkFile) {}
+  virtual ~MetalinkRequestInfo() {}
+
+  virtual RequestInfo* execute();
+
+  virtual DownloadEngine* getDownloadEngine() { return 0; }
+};
+
+#endif // _D_METALINK_REQUEST_INFO_H_

+ 1 - 0
src/MetalinkResource.h

@@ -29,6 +29,7 @@ public:
   enum TYPE {
     TYPE_FTP,
     TYPE_HTTP,
+    TYPE_HTTPS,
     TYPE_BITTORRENT,
     TYPE_NOT_SUPPORTED
   };

+ 9 - 18
src/MultiDiskWriter.cc

@@ -25,18 +25,15 @@
 #include "message.h"
 #include <errno.h>
 
-MultiDiskWriter::MultiDiskWriter(int pieceLength):pieceLength(pieceLength) {
-#ifdef ENABLE_MESSAGE_DIGEST
-  ctx.setAlgo(MessageDigestContext::ALGO_SHA1);
-  digestInit(ctx);
-#endif // ENABLE_MESSAGE_DIGEST
+MultiDiskWriter::MultiDiskWriter(int pieceLength):
+  pieceLength(pieceLength),
+  ctx(DIGEST_ALGO_SHA1) {
+  ctx.digestInit();
 }
 
 MultiDiskWriter::~MultiDiskWriter() {
   clearEntries();
-#ifdef ENABLE_MESSAGE_DIGEST
-  digestFree(ctx);
-#endif // ENABLE_MESSAGE_DIGEST
+  ctx.digestFree();
 }
 
 void MultiDiskWriter::clearEntries() {
@@ -143,7 +140,6 @@ int MultiDiskWriter::readData(char* data, int len, long long int offset) {
   return totalReadLength;
 }
 
-#ifdef ENABLE_MESSAGE_DIGEST
 void MultiDiskWriter::hashUpdate(DiskWriterEntry* entry, long long int offset, long long int length) {
   int BUFSIZE = 16*1024;
   char buf[BUFSIZE];
@@ -151,7 +147,7 @@ void MultiDiskWriter::hashUpdate(DiskWriterEntry* entry, long long int offset, l
     if(BUFSIZE != entry->diskWriter->readData(buf, BUFSIZE, offset)) {
       throw string("error");
     }
-    digestUpdate(ctx, buf, BUFSIZE);
+    ctx.digestUpdate(buf, BUFSIZE);
     offset += BUFSIZE;
   }
   int r = length%BUFSIZE;
@@ -159,17 +155,15 @@ void MultiDiskWriter::hashUpdate(DiskWriterEntry* entry, long long int offset, l
     if(r != entry->diskWriter->readData(buf, r, offset)) {
       throw string("error");
     }
-    digestUpdate(ctx, buf, r);
+    ctx.digestUpdate(buf, r);
   }
 }
-#endif // ENABLE_MESSAGE_DIGEST
 
 string MultiDiskWriter::sha1Sum(long long int offset, long long int length) {
-#ifdef ENABLE_MESSAGE_DIGEST
   long long int fileOffset = offset;
   bool reading = false;
   int rem = length;
-  digestReset(ctx);
+  ctx.digestReset();
   try {
     for(DiskWriterEntries::iterator itr = diskWriterEntries.begin();
 	itr != diskWriterEntries.end() && rem != 0; itr++) {
@@ -187,13 +181,10 @@ string MultiDiskWriter::sha1Sum(long long int offset, long long int length) {
       throw new DlAbortEx(EX_FILE_OFFSET_OUT_OF_RANGE, offset);
     }
     unsigned char hashValue[20];
-    digestFinal(ctx, hashValue);
+    ctx.digestFinal(hashValue);
     return Util::toHex(hashValue, 20);
   } catch(string ex) {
     throw new DlAbortEx(EX_FILE_SHA1SUM, "", strerror(errno));
   }
-#else
-  return "";
-#endif // ENABLE_MESSAGE_DIGEST
 }
 

+ 0 - 2
src/MultiDiskWriter.h

@@ -48,10 +48,8 @@ private:
   bool isInRange(const DiskWriterEntry* entry, long long int offset) const;
   int calculateLength(const DiskWriterEntry* entry, long long int fileOffset, int rem) const;
   void clearEntries();
-#ifdef ENABLE_MESSAGE_DIGEST
   MessageDigestContext ctx;
   void hashUpdate(DiskWriterEntry* entry, long long int offset, long long int length);
-#endif // ENABLE_MESSAGE_DIGEST
 
 public:
   MultiDiskWriter(int pieceLength);

+ 1 - 1
src/PeerChokeCommand.cc

@@ -22,7 +22,7 @@
 #include "PeerChokeCommand.h"
 #include "Util.h"
 
-PeerChokeCommand::PeerChokeCommand(int cuid, int interval, TorrentDownloadEngine* e):Command(cuid), interval(interval), e(e), rotate(0) {}
+PeerChokeCommand::PeerChokeCommand(int cuid, TorrentDownloadEngine* e, int interval):Command(cuid), interval(interval), e(e), rotate(0) {}
 
 PeerChokeCommand::~PeerChokeCommand() {}
 

+ 1 - 1
src/PeerChokeCommand.h

@@ -38,7 +38,7 @@ private:
   void optUnchokingPeer(Peers& peers) const;
 
 public:
-  PeerChokeCommand(int cuid, int interval, TorrentDownloadEngine* e);
+  PeerChokeCommand(int cuid, TorrentDownloadEngine* e, int interval);
   virtual ~PeerChokeCommand();
 
   bool execute();

+ 116 - 0
src/RequestInfo.h

@@ -0,0 +1,116 @@
+/* <!-- 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_REQUEST_INFO_H_
+#define _D_REQUEST_INFO_H_
+
+#include "common.h"
+#include "LogFactory.h"
+#include "Option.h"
+#include "DownloadEngine.h"
+#include "Util.h"
+#include "Checksum.h"
+#include <signal.h>
+
+class FileInfo {
+public:
+  string filename;
+  long long int length;
+  Checksum checksum;
+public:
+  FileInfo():length(0) {}
+  ~FileInfo() {}
+
+  bool isEmpty() const {
+    return filename.size() == 0 && length == 0;
+  }
+
+  bool checkReady() const {
+#ifdef ENABLE_MESSAGE_DIGEST
+    return !isEmpty() && !checksum.isEmpty();
+#else
+    return false;
+#endif // ENABLE_MESSAGE_DIGEST
+  }
+
+  bool check() const {
+#ifdef ENABLE_MESSAGE_DIGEST
+    unsigned char md[MAX_MD_LENGTH];
+    Util::fileChecksum(filename, md, checksum.getDigestAlgo());
+    return Util::toHex(md,
+		       MessageDigestContext::digestLength(checksum.getDigestAlgo()))
+      == checksum.getMessageDigest();
+#else
+    return false;
+#endif // ENABLE_MESSAGE_DIGEST
+  }
+
+  bool isTorrentFile() const {
+    return Util::endsWith(filename, ".torrent");
+  }
+
+  bool isMetalinkFile() const {
+    return Util::endsWith(filename, ".metalink");
+  }
+};
+
+class RequestInfo {
+protected:
+  const Option* op;
+  const Logger* logger;
+  Checksum checksum;
+  FileInfo fileInfo;
+  bool fail;
+
+  void printDownloadCompeleteMessage(const string& filename) {
+    printf(_("\nThe download was complete. <%s>\n"), filename.c_str());
+  }
+  
+  void printDownloadCompeleteMessage() {
+    printf("\nThe download was complete.\n");
+  }
+  
+  void printDownloadAbortMessage() {
+    printf(_("\nThe download was not complete because of errors. Check the log.\n"));
+  }
+public:
+  RequestInfo(const Option* op):
+    op(op),
+    fail(false)
+  {
+    logger = LogFactory::getInstance();
+  }
+  virtual ~RequestInfo() {}
+
+  virtual RequestInfo* execute() = 0;
+
+  virtual DownloadEngine* getDownloadEngine() = 0;
+
+  bool isFail() const { return fail; }
+
+  void setChecksum(const Checksum& checksum) {
+    this->checksum = checksum;
+  }
+  const Checksum& getChecksum() const { return checksum; }
+  const FileInfo& getFileInfo() const { return fileInfo; }
+};
+
+#endif // _D_REQUEST_INFO_H_

+ 18 - 31
src/ShaVisitor.cc

@@ -22,60 +22,49 @@
 #include "ShaVisitor.h"
 #include "Util.h"
 
-ShaVisitor::ShaVisitor() {
-#ifdef ENABLE_MESSAGE_DIGEST
-  ctx.setAlgo(MessageDigestContext::ALGO_SHA1);
-  digestInit(ctx);
-  digestReset(ctx);
-#endif // ENABLE_MESSAGE_DIGEST
+ShaVisitor::ShaVisitor():
+  ctx(DIGEST_ALGO_SHA1) {
+  ctx.digestInit();
 }
 
 ShaVisitor::~ShaVisitor() {
-#ifdef ENABLE_MESSAGE_DIGEST
-  digestFree(ctx);
-#endif // ENABLE_MESSAGE_DIGEST
+  ctx.digestFree();
 }
 
 void ShaVisitor::visit(const Data* d) {
-#ifdef ENABLE_MESSAGE_DIGEST
   if(d->isNumber()) {
-    digestUpdate(ctx, "i", 1);
+    ctx.digestUpdate("i", 1);
   } else {
     string lenStr = Util::llitos(d->getLen());
-    digestUpdate(ctx, lenStr.c_str(), lenStr.size());
-    digestUpdate(ctx, ":", 1);
+    ctx.digestUpdate(lenStr.c_str(), lenStr.size());
+    ctx.digestUpdate(":", 1);
   }
-  digestUpdate(ctx, d->getData(), d->getLen());
+  ctx.digestUpdate(d->getData(), d->getLen());
   if(d->isNumber()) {
-    digestUpdate(ctx, "e", 1);
+    ctx.digestUpdate("e", 1);
   }
-#endif // ENABLE_MESSAGE_DIGEST
 }
 
 void ShaVisitor::visit(const Dictionary* d) {
-#ifdef ENABLE_MESSAGE_DIGEST
-  digestUpdate(ctx, "d", 1);
+  ctx.digestUpdate("d", 1);
   const Order& v = d->getOrder();
   for(Order::const_iterator itr = v.begin(); itr != v.end(); itr++) {
     string lenStr = Util::llitos(itr->size());
-    digestUpdate(ctx, lenStr.c_str(), lenStr.size());
-    digestUpdate(ctx, ":", 1);
-    digestUpdate(ctx, itr->c_str(), itr->size());
+    ctx.digestUpdate(lenStr.c_str(), lenStr.size());
+    ctx.digestUpdate(":", 1);
+    ctx.digestUpdate(itr->c_str(), itr->size());
     const MetaEntry* e = d->get(*itr);
     this->visit(e);
   }
-  digestUpdate(ctx, "e", 1);
-#endif // ENABLE_MESSAGE_DIGEST
+  ctx.digestUpdate("e", 1);
 }
 
 void ShaVisitor::visit(const List* l) {
-#ifdef ENABLE_MESSAGE_DIGEST
-  digestUpdate(ctx, "l", 1);
+  ctx.digestUpdate("l", 1);
   for(MetaList::const_iterator itr = l->getList().begin(); itr != l->getList().end(); itr++) {
     this->visit(*itr);
   }
-  digestUpdate(ctx, "e", 1);
-#endif // ENABLE_MESSAGE_DIGEST
+  ctx.digestUpdate("e", 1);
 }
 
 void ShaVisitor::visit(const MetaEntry* e) {
@@ -89,8 +78,6 @@ void ShaVisitor::visit(const MetaEntry* e) {
 }
 
 void ShaVisitor::getHash(unsigned char* hashValue, int& len) {
-#ifdef ENABLE_MESSAGE_DIGEST
-  digestFinal(ctx, hashValue);
-  len = 20;
-#endif // ENABLE_MESSAGE_DIGEST
+  len = ctx.digestLength();
+  ctx.digestFinal(hashValue);
 }

+ 0 - 4
src/ShaVisitor.h

@@ -27,15 +27,11 @@
 #include "Dictionary.h"
 #include "List.h"
 #include "common.h"
-#ifdef ENABLE_MESSAGE_DIGEST
 #include "messageDigest.h"
-#endif // ENABLE_MESSAGE_DIGEST
 
 class ShaVisitor : public MetaEntryVisitor {
 private:
-#ifdef ENABLE_MESSAGE_DIGEST
   MessageDigestContext ctx;
-#endif // ENABLE_MESSAGE_DIGEST
 public:
   ShaVisitor();
   ~ShaVisitor();

+ 6 - 8
src/TorrentMan.cc

@@ -43,7 +43,7 @@
 
 extern PeerHandle nullPeer;
 
-TorrentMan::TorrentMan():bitfield(NULL),
+TorrentMan::TorrentMan():bitfield(0),
 			 peerEntryIdCounter(0),
 			 cuidCounter(0),
 			 downloadLength(0),
@@ -61,18 +61,16 @@ TorrentMan::TorrentMan():bitfield(NULL),
 			 incomplete(0),
 			 connections(0),
 			 trackers(0),
-			 diskAdaptor(NULL)
+			 req(0),
+			 diskAdaptor(0)
 {
   logger = LogFactory::getInstance();
 }
 
 TorrentMan::~TorrentMan() {
-  if(bitfield != NULL) {
-    delete bitfield;
-  }
-  if(diskAdaptor != NULL) {
-    delete diskAdaptor;
-  }
+  delete bitfield;
+  delete diskAdaptor;
+  delete req;
 }
 
 // TODO do not use this method in application code

+ 81 - 0
src/TorrentRequestInfo.cc

@@ -0,0 +1,81 @@
+/* <!-- 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 "TorrentRequestInfo.h"
+#include "DownloadEngineFactory.h"
+#include "prefs.h"
+#include "Util.h"
+
+extern RequestInfo* requestInfo;
+extern void setSignalHander(int signal, void (*handler)(int), int flags);
+
+void torrentHandler(int signal) {
+  ((TorrentDownloadEngine*)requestInfo->getDownloadEngine())->
+    torrentMan->setHalt(true);
+}
+
+RequestInfo* TorrentRequestInfo::execute() {
+  if(op->get(PREF_SHOW_FILES) == V_TRUE) {
+    showFileEntry();
+    return 0;
+  }
+  e = DownloadEngineFactory::newTorrentConsoleEngine(op,
+						     torrentFile,
+						     targetFiles);
+  setSignalHander(SIGINT, torrentHandler, SA_RESETHAND);
+  setSignalHander(SIGTERM, torrentHandler, SA_RESETHAND);
+    
+  try {
+    e->run();
+    if(e->torrentMan->downloadComplete()) {
+      printDownloadCompeleteMessage();
+    }
+  } catch(Exception* e) {
+    logger->error("Exception caught", e);
+    delete e;
+    fail = true;
+  }
+  setSignalHander(SIGINT, SIG_DFL, 0);
+  setSignalHander(SIGTERM, SIG_DFL, 0);
+  delete e;
+  
+  return 0;
+}
+
+// TODO should be const TorrentMan* torrentMan
+void TorrentRequestInfo::showFileEntry()
+{
+  TorrentMan torrentMan;
+  torrentMan.option = op;
+
+  FileEntries fileEntries =
+    torrentMan.readFileEntryFromMetaInfoFile(torrentFile);
+  cout << _("Files:") << endl;
+  cout << "idx|path/length" << endl;
+  cout << "===+===========================================================================" << endl;
+  int count = 1;
+  for(FileEntries::const_iterator itr = fileEntries.begin();
+      itr != fileEntries.end(); count++, itr++) {
+    printf("%3d|%s\n   |%s Bytes\n", count, itr->path.c_str(),
+	   Util::llitos(itr->length, true).c_str());
+    cout << "---+---------------------------------------------------------------------------" << endl;
+  }
+}

+ 51 - 0
src/TorrentRequestInfo.h

@@ -0,0 +1,51 @@
+/* <!-- 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_TORRENT_REQUEST_INFO_H_
+#define _D_TORRENT_REQUEST_INFO_H_
+
+#include "RequestInfo.h"
+#include "TorrentDownloadEngine.h"
+
+class TorrentRequestInfo : public RequestInfo {
+private:
+  string torrentFile;
+  TorrentDownloadEngine* e;
+  Strings targetFiles;
+
+  void showFileEntry();
+public:
+  TorrentRequestInfo(const string& torrentFile, const Option* op):
+    RequestInfo(op),
+    torrentFile(torrentFile),
+    e(0) {}
+  virtual ~TorrentRequestInfo() {}
+
+  virtual RequestInfo* execute();
+
+  void setTargetFiles(const Strings& targetFiles) {
+    this->targetFiles = targetFiles;
+  }
+  virtual DownloadEngine* getDownloadEngine() { return e; }
+
+};
+
+#endif // _D_TORRENT_REQUEST_INFO_H_

+ 146 - 0
src/UrlRequestInfo.cc

@@ -0,0 +1,146 @@
+/* <!-- 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 "UrlRequestInfo.h"
+#include "TorrentRequestInfo.h"
+#include "MetalinkRequestInfo.h"
+#include "prefs.h"
+#include "DownloadEngineFactory.h"
+
+extern RequestInfo* requestInfo;
+extern void setSignalHander(int signal, void (*handler)(int), int flags);
+
+void UrlRequestInfo::adjustRequestSize(Requests& requests,
+				       Requests& reserved,
+				       int maxConnections) const
+{
+  if(maxConnections > 0 && (int)requests.size() > maxConnections) {
+    copy(requests.begin()+maxConnections, requests.end(),
+	 back_inserter(reserved));
+    //insert_iterator<Requests>(reserved, reserved.end()));
+    requests.erase(requests.begin()+maxConnections, requests.end());
+  }
+}
+
+RequestInfo* UrlRequestInfo::createNextRequestInfo() const
+{
+#ifdef ENABLE_BITTORRENT
+  if(op->getAsBool(PREF_FOLLOW_TORRENT) &&
+     Util::endsWith(fileInfo.filename, ".torrent")) {
+    return new TorrentRequestInfo(fileInfo.filename, op);
+  } else
+#endif // ENABLE_BITTORRENT
+#ifdef ENABLE_METALINK
+    if(op->getAsBool(PREF_FOLLOW_METALINK) &&
+       Util::endsWith(fileInfo.filename, ".metalink")) {
+      return new MetalinkRequestInfo(fileInfo.filename, op);
+    } else
+#endif // ENABLE_METALINK
+      {
+	return 0;
+      }
+}
+
+void handler(int signal) {
+  printf(_("\nstopping application...\n"));
+  fflush(stdout);
+  requestInfo->getDownloadEngine()->segmentMan->save();
+  requestInfo->getDownloadEngine()->segmentMan->diskWriter->closeFile();
+  delete requestInfo->getDownloadEngine();
+  printf(_("done\n"));
+  exit(EXIT_SUCCESS);
+}
+
+class CreateRequest {
+private:
+  Requests* requestsPtr;
+  string referer;
+  int split;
+public:
+  CreateRequest(Requests* requestsPtr,
+		const string& referer,
+		int split)
+    :requestsPtr(requestsPtr),
+     referer(referer),
+     split(split) {}
+
+  void operator()(const string& url) {
+    for(int s = 1; s <= split; s++) {
+      Request* req = new Request();
+      req->setReferer(referer);
+      if(req->setUrl(url)) {
+	requestsPtr->push_back(req);
+      } else {
+	fprintf(stderr, _("Unrecognized URL or unsupported protocol: %s\n"),
+		req->getUrl().c_str());
+	delete req;
+      }
+    }
+  }
+};
+
+RequestInfo* UrlRequestInfo::execute() {
+  Requests requests;
+  Requests reserved;
+  for_each(urls.begin(), urls.end(),
+	   CreateRequest(&requests,
+			 op->get(PREF_REFERER),
+			 op->getAsInt(PREF_SPLIT)));
+  
+  adjustRequestSize(requests, reserved, maxConnections);
+  
+  e = DownloadEngineFactory::newConsoleEngine(op, requests, reserved);
+  
+  setSignalHander(SIGINT, handler, 0);
+  setSignalHander(SIGTERM, handler, 0);
+  
+  RequestInfo* next = 0;
+  try {
+    e->run();
+    
+    if(e->segmentMan->finished()) {
+      printDownloadCompeleteMessage(e->segmentMan->getFilePath());
+      fileInfo.filename = e->segmentMan->getFilePath();
+      fileInfo.length = e->segmentMan->totalSize;
+      fileInfo.checksum = checksum;
+      
+      next = createNextRequestInfo();
+    } else {
+      e->segmentMan->save();
+      e->segmentMan->diskWriter->closeFile();
+      printDownloadAbortMessage();
+    }
+  } catch(Exception *e) {
+    logger->error("Exception caught", e);
+    delete e;
+    fail = true;
+  }
+  for_each(requests.begin(), requests.end(), Deleter());
+  for_each(reserved.begin(), reserved.end(), Deleter());
+  
+  setSignalHander(SIGINT, SIG_DFL, 0);
+  setSignalHander(SIGTERM, SIG_DFL, 0);
+  
+  delete e;
+  e = 0;
+  
+  return next;
+}

+ 52 - 0
src/UrlRequestInfo.h

@@ -0,0 +1,52 @@
+/* <!-- 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_URL_REQUEST_INFO_H_
+#define _D_URL_REQUEST_INFO_H_
+
+#include "RequestInfo.h"
+
+class UrlRequestInfo : public RequestInfo {
+private:
+  Strings urls;
+  int maxConnections;
+  DownloadEngine* e;
+
+  RequestInfo* createNextRequestInfo() const;
+  void adjustRequestSize(Requests& requests,
+			 Requests& reserved,
+			 int maxConnections) const;
+public:
+  UrlRequestInfo(const Strings& urls, int maxConnections, const Option* op):
+    RequestInfo(op),
+    urls(urls),
+    maxConnections(maxConnections),
+    e(0) {}
+  virtual ~UrlRequestInfo() {}
+
+  virtual RequestInfo* execute();
+
+  virtual DownloadEngine* getDownloadEngine() {
+    return e;
+  }
+};
+
+#endif // _D_URL_REQUEST_INFO_H_

+ 11 - 12
src/Util.cc

@@ -363,21 +363,20 @@ string Util::getContentDispositionFilename(const string& header) {
 
 #ifdef ENABLE_MESSAGE_DIGEST
 void Util::sha1Sum(unsigned char* digest, const void* data, int dataLength) {
-  MessageDigestContext ctx(MessageDigestContext::ALGO_SHA1);
-  digestInit(ctx);
-  digestReset(ctx);
-  digestUpdate(ctx, data, dataLength);
-  digestFinal(ctx, digest);
-  digestFree(ctx);
+  MessageDigestContext ctx(DIGEST_ALGO_SHA1);
+  ctx.digestInit();
+  ctx.digestUpdate(data, dataLength);
+  ctx.digestFinal(digest);
+  ctx.digestFree();
 }
 #endif // ENABLE_MESSAGE_DIGEST
 
 #ifdef ENABLE_MESSAGE_DIGEST
 void Util::fileChecksum(const string& filename, unsigned char* digest,
-			MessageDigestContext::HashAlgo algo) {
+			MessageDigestContext::DigestAlgo algo) {
   MessageDigestContext ctx(algo);
-  digestInit(ctx);
-  digestReset(ctx);
+  ctx.digestInit();
+  ctx.digestReset();
 
   int BUFLEN = 4096;
   char buf[BUFLEN];
@@ -396,14 +395,14 @@ void Util::fileChecksum(const string& filename, unsigned char* digest,
 	throw new DlAbortEx(EX_FILE_READ, filename.c_str(), strerror(errno));
       }
     } else if(size > 0) {
-      digestUpdate(ctx, buf, size);
+      ctx.digestUpdate(buf, size);
     }
     if(size < BUFLEN) {
       break;
     }
   }
-  digestFinal(ctx, digest);
-  digestFree(ctx);
+  ctx.digestFinal(digest);
+  ctx.digestFree();
 }
 #endif // ENABLE_MESSAGE_DIGEST
 

+ 1 - 1
src/Util.h

@@ -92,7 +92,7 @@ public:
   // For sha1, you need 20 bytes. For md5, 16 bytes.
 #ifdef ENABLE_MESSAGE_DIGEST
   static void fileChecksum(const string& filename, unsigned char* digest,
-			   MessageDigestContext::HashAlgo algo);
+			   MessageDigestContext::DigestAlgo algo);
 #endif // ENABLE_MESSAGE_DIGEST
 
 #ifdef ENABLE_BITTORRENT

+ 16 - 2
src/Xml2MetalinkProcessor.cc

@@ -88,8 +88,20 @@ MetalinkEntry* Xml2MetalinkProcessor::getEntry(const string& xpath) {
     entry->version = Util::trim(xpathContent(xpath+"/m:version"));
     entry->language = Util::trim(xpathContent(xpath+"/m:language"));
     entry->os = Util::trim(xpathContent(xpath+"/m:os"));
-    entry->md5 = Util::toLower(Util::trim(xpathContent(xpath+"/m:verification/m:hash[@type=\"md5\"]")));
-    entry->sha1 = Util::toLower(Util::trim(xpathContent(xpath+"/m:verification/m:hash[@type=\"sha1\"]")));
+#ifdef ENABLE_MESSAGE_DIGEST
+    string md;
+    md = Util::toLower(Util::trim(xpathContent(xpath+"/m:verification/m:hash[@type=\"sha1\"]")));
+    if(md.size() > 0) {
+      entry->checksum.setMessageDigest(md);
+      entry->checksum.setDigestAlgo(DIGEST_ALGO_SHA1);
+    } else {
+      md = Util::toLower(Util::trim(xpathContent(xpath+"/m:verification/m:hash[@type=\"md5\"]")));
+      if(md.size() > 0) {
+	entry->checksum.setMessageDigest(md);
+	entry->checksum.setDigestAlgo(DIGEST_ALGO_MD5);
+      }
+    }
+#endif // ENABLE_MESSAGE_DIGEST
     for(int index = 1; 1; index++) {
       MetalinkResource* resource =
 	getResource(xpath+"/m:resources/m:url["+Util::itos(index)+"]");
@@ -121,6 +133,8 @@ MetalinkResource* Xml2MetalinkProcessor::getResource(const string& xpath) {
       resource->type = MetalinkResource::TYPE_FTP;
     } else if(type == "http") {
       resource->type = MetalinkResource::TYPE_HTTP;
+    } else if(type == "https") {
+      resource->type = MetalinkResource::TYPE_HTTPS;
     } else if(type == "bittorrent") {
       resource->type = MetalinkResource::TYPE_BITTORRENT;
     } else {

+ 95 - 310
src/main.cc

@@ -30,23 +30,11 @@
 #include "InitiateConnectionCommandFactory.h"
 #include "prefs.h"
 #include "FeatureConfig.h"
-
-#ifdef ENABLE_BITTORRENT
-# include "TorrentConsoleDownloadEngine.h"
-# include "TorrentMan.h"
-# include "PeerListenCommand.h"
-# include "TorrentAutoSaveCommand.h"
-# include "TrackerWatcherCommand.h"
-# include "TrackerUpdateCommand.h"
-# include "HaveEraseCommand.h"
-# include "ByteArrayDiskWriter.h"
-# include "PeerChokeCommand.h"
-#endif // ENABLE_BITTORRENT
-
-#ifdef ENABLE_METALINK
-# include "Xml2MetalinkProcessor.h"
-#endif // ENABLE_METALINK
-
+#include "DownloadEngineFactory.h"
+#include "UrlRequestInfo.h"
+#include "TorrentRequestInfo.h"
+#include "MetalinkRequestInfo.h"
+#include "Xml2MetalinkProcessor.h"
 #include <deque>
 #include <algorithm>
 #include <time.h>
@@ -69,22 +57,7 @@ extern int optind, opterr, optopt;
 
 using namespace std;
 
-bool readyToTorrentMode = false;
-string downloadedTorrentFile;
-bool readyToMetalinkMode = false;
-string downloadedMetalinkFile;
-
-void printDownloadCompeleteMessage(string filename) {
-  printf(_("\nThe download was complete. <%s>\n"), filename.c_str());
-}
-
-void printDownloadCompeleteMessage() {
-  printf("\nThe download was complete.\n");
-}
-
-void printDownloadAbortMessage() {
-  printf(_("\nThe download was not complete because of errors. Check the log.\n"));
-}
+RequestInfo* requestInfo;
 
 void setSignalHander(int signal, void (*handler)(int), int flags) {
   struct sigaction sigact;
@@ -94,39 +67,6 @@ void setSignalHander(int signal, void (*handler)(int), int flags) {
   sigaction(signal, &sigact, NULL);
 }
 
-DownloadEngine* e;
-#ifdef ENABLE_BITTORRENT
-TorrentDownloadEngine* te;
-#endif // ENABLE_BITTORRENT
-
-void handler(int signal) {
-  printf(_("\nstopping application...\n"));
-  fflush(stdout);
-  e->segmentMan->save();
-  e->segmentMan->diskWriter->closeFile();
-  e->cleanQueue();
-  delete e;
-  printf(_("done\n"));
-  exit(EXIT_SUCCESS);
-}
-
-#ifdef ENABLE_BITTORRENT
-void torrentHandler(int signal) {
-  te->torrentMan->setHalt(true);
-}
-#endif // ENABLE_BITTORRENT
-
-void createRequest(int cuid, const string& url, string referer, Requests& requests) {
-  Request* req = new Request();
-  req->setReferer(referer);
-  if(req->setUrl(url)) {
-    requests.push_back(req);
-  } else {
-    fprintf(stderr, _("Unrecognized URL or unsupported protocol: %s\n"), req->getUrl().c_str());
-    delete(req);
-  }
-}
-
 void showVersion() {
   cout << PACKAGE << _(" version ") << PACKAGE_VERSION << endl;
   cout << "Copyright (C) 2006 Tatsuhiro Tsujikawa" << endl;
@@ -182,7 +122,7 @@ void showUsage() {
   cout << _(" --min-segment-size=SIZE[K|M] Set minimum segment size. You can append\n"
 	    "                              K or M(1K = 1024, 1M = 1024K). This\n"
 	    "                              value must be greater than or equal to\n"
-	    "                              1024.") << endl;
+	    "                              1024. Default: 1M") << endl;
   cout << _(" --http-proxy=HOST:PORT       Use HTTP proxy server. This affects to all\n"
 	    "                              URLs.") << endl;
   cout << _(" --http-user=USER             Set HTTP user. This affects to all URLs.") << endl;
@@ -207,6 +147,12 @@ void showUsage() {
   cout << _(" --ftp-via-http-proxy=METHOD  Use HTTP proxy in FTP. METHOD is either 'get' or\n"
 	    "                              'tunnel'.\n"
 	    "                              Default: tunnel") << endl;
+  cout << _(" --lowest-speed-limit         Close connection if download speed is lower than\n"
+	    "                              or equal to this value. 0 means aria2 does not\n"
+	    "                              care lowest speed limit. You can use K or M in\n"
+	    "                              the same manner as in --min-segment-size option.\n"
+	    "                              This option does not affect BitTorrent download.\n"
+	    "                              Default: 0") << 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"
@@ -288,52 +234,19 @@ void showUsage() {
   cout << endl;
 }
 
-bool normalDownload(const Requests& requests,
-		    const Requests& reserved,
-		    Option* op,
-		    string& downloadedFilename) {
-  setSignalHander(SIGINT, handler, 0);
-  setSignalHander(SIGTERM, handler, 0);
-  
-  e = new ConsoleDownloadEngine();
-  e->option = op;
-  e->segmentMan = new SegmentMan();
-  e->segmentMan->diskWriter = new DefaultDiskWriter();
-  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));
-  e->segmentMan->reserved = reserved;
-  
-  int cuidCounter = 1;
-  for(Requests::const_iterator itr = requests.begin();
-      itr != requests.end();
-      itr++, cuidCounter++) {
-    e->commands.push_back(InitiateConnectionCommandFactory::createInitiateConnectionCommand(cuidCounter, *itr, e));
-  }
-  e->run();
-  bool success = false;
-  if(e->segmentMan->finished()) {
-    printDownloadCompeleteMessage(e->segmentMan->getFilePath());
-    if(Util::endsWith(e->segmentMan->getFilePath(), ".torrent")) {
-      downloadedTorrentFile = e->segmentMan->getFilePath();
-      readyToTorrentMode = true;
-    } else if(Util::endsWith(e->segmentMan->getFilePath(), ".metalink")) {
-      downloadedMetalinkFile = e->segmentMan->getFilePath();
-      readyToMetalinkMode = true;
+long long int getRealSize(char* optarg) {
+  string::size_type p = string(optarg).find_first_of("KM");
+  int mult = 1;
+  if(p != string::npos) {
+    if(optarg[p] == 'K') {
+      mult = 1024;
+    } else if(optarg[p] == 'M') {
+      mult = 1024*1024;
     }
-    downloadedFilename = e->segmentMan->getFilePath();
-    success = true;
-  } else {
-    e->segmentMan->save();
-    e->segmentMan->diskWriter->closeFile();
-    printDownloadAbortMessage();
+    optarg[p] = '\0';
   }
-  e->cleanQueue();
-  delete e;
-
-  return success;
+  long long int size = strtoll(optarg, NULL, 10)*mult;
+  return size;
 }
 
 int main(int argc, char* argv[]) {
@@ -343,18 +256,6 @@ int main(int argc, char* argv[]) {
   bindtextdomain (PACKAGE, LOCALEDIR);
   textdomain (PACKAGE);
 #endif // ENABLE_NLS
-  Integers selectFileIndexes;
-#ifdef ENABLE_BITTORRENT
-  bool followTorrent = true;
-#else
-  bool followTorrent = false;
-#endif // ENABLE_BITTORRENT
-#ifdef ENABLE_METALINK
-  bool followMetalink = true;
-#else
-  bool followMetalink = false;
-#endif // ENABLE_METALINK
-
   int c;
   Option* op = new Option();
   op->put(PREF_STDOUT_LOG, V_FALSE);
@@ -363,6 +264,20 @@ int main(int argc, char* argv[]) {
   op->put(PREF_DAEMON, V_FALSE);
   op->put(PREF_LISTEN_PORT, "-1");
   op->put(PREF_METALINK_SERVERS, "15");
+  op->put(PREF_FOLLOW_TORRENT,
+#ifdef ENABLE_BITTORRENT
+	  V_TRUE
+#else
+	  V_FALSE
+#endif // ENABLE_BITTORRENT
+	  );
+  op->put(PREF_FOLLOW_METALINK,
+#ifdef ENABLE_METALINK
+	  V_TRUE
+#else
+	  V_FALSE
+#endif // ENABLE_METALINK
+	  );
   op->put(PREF_RETRY_WAIT, "5");
   op->put(PREF_TIMEOUT, "60");
   op->put(PREF_PEER_CONNECTION_TIMEOUT, "60");
@@ -377,6 +292,7 @@ int main(int argc, char* argv[]) {
   op->put(PREF_AUTO_SAVE_INTERVAL, "60");
   op->put(PREF_DIRECT_FILE_MAPPING, V_TRUE);
   op->put(PREF_UPLOAD_LIMIT, "0");
+  op->put(PREF_LOWEST_SPEED_LIMIT, "4000");
   while(1) {
     int optIndex = 0;
     int lopt;
@@ -403,6 +319,7 @@ int main(int argc, char* argv[]) {
       { "ftp-via-http-proxy", required_argument, &lopt, 12 },
       { "min-segment-size", required_argument, &lopt, 13 },
       { "http-proxy-method", required_argument, &lopt, 14 },
+      { "lowest-speed-limit", required_argument, &lopt, 200 },
 #ifdef ENABLE_BITTORRENT
       { "torrent-file", required_argument, NULL, 'T' },
       { "listen-port", required_argument, &lopt, 15 },
@@ -506,17 +423,7 @@ int main(int argc, char* argv[]) {
 	}
 	break;
       case 13: {
-	string::size_type p = string(optarg).find_first_of("KM");
-	int mult = 1;
-	if(p != string::npos) {
-	  if(optarg[p] == 'K') {
-	    mult = 1024;
-	  } else if(optarg[p] == 'M') {
-	    mult = 1024*1024;
-	  }
-	  optarg[p] = '\0';
-	}
-	long long int size = strtoll(optarg, NULL, 10)*mult;
+	long long int size = getRealSize(optarg);
 	if(size < 1024) {
 	  cerr << _("min-segment-size invalid") << endl;
 	  showUsage();
@@ -546,9 +453,9 @@ int main(int argc, char* argv[]) {
       }
       case 16:
 	if(string(optarg) == "true") {
-	  followTorrent = true;
+	  op->put(PREF_FOLLOW_TORRENT, V_TRUE);
 	} else if(string(optarg) == "false") {
-	  followTorrent = false;
+	  op->put(PREF_FOLLOW_TORRENT, V_FALSE);
 	} else {
 	  cerr << _("follow-torrent must be either 'true' or 'false'.") << endl;
 	  showUsage();
@@ -580,7 +487,7 @@ int main(int argc, char* argv[]) {
 	break;
       }
       case 21:
-	Util::unfoldRange(optarg, selectFileIndexes);
+	op->put(PREF_SELECT_FILE, optarg);
 	break;
       case 100:
 	op->put(PREF_METALINK_VERSION, optarg);
@@ -593,15 +500,25 @@ int main(int argc, char* argv[]) {
 	break;
       case 103:
 	if(string(optarg) == "true") {
-	  followMetalink = true;
+	  op->put(PREF_FOLLOW_METALINK, V_TRUE);
 	} else if(string(optarg) == "false") {
-	  followMetalink = false;
+	  op->put(PREF_FOLLOW_METALINK, V_FALSE);
 	} else {
 	  cerr << _("follow-metalink must be either 'true' or 'false'.") << endl;
 	  showUsage();
 	  exit(EXIT_FAILURE);
 	}
 	break;
+      case 200: {
+	int limit = getRealSize(optarg);
+	if(limit < 0) {
+	  cerr << _("lowest-speed-limit must be greater than or equal to 0") << endl;
+	  showUsage();
+	  exit(EXIT_FAILURE);
+	}
+	op->put(PREF_LOWEST_SPEED_LIMIT, Util::itos(limit));
+	break;
+      }
       }
       break;
     }
@@ -720,190 +637,58 @@ int main(int argc, char* argv[]) {
   }
   // make sure logger is configured properly.
   try {
-    LogFactory::getInstance();
-  } catch(Exception* ex) {
-    cerr << ex->getMsg() << endl;
-    delete ex;
-    exit(EXIT_FAILURE);
-  }
+    Logger* logger = LogFactory::getInstance();
+    logger->info("%s %s", PACKAGE, PACKAGE_VERSION);
+    logger->info("Logging started.");
 
-  setSignalHander(SIGPIPE, SIG_IGN, 0);
+    setSignalHander(SIGPIPE, SIG_IGN, 0);
 
-  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 <= op->getAsInt(PREF_SPLIT); s++) {
-	createRequest(cuidCounter, *itr, op->get(PREF_REFERER), requests); 
-	cuidCounter++;
+    requestInfo = 0;
+#ifdef ENABLE_BITTORRENT
+    if(op->defined(PREF_TORRENT_FILE)) {
+      requestInfo = new TorrentRequestInfo(op->get(PREF_TORRENT_FILE),
+					   op);
+      Strings targetFiles;
+      if(op->defined(PREF_TORRENT_FILE) && !args.empty()) {
+	targetFiles = args;
       }
+      ((TorrentRequestInfo*)requestInfo)->setTargetFiles(targetFiles);
     }
-    setSignalHander(SIGINT, handler, 0);
-    setSignalHander(SIGTERM, handler, 0);
-
-    Requests reserved;
-    string downloadedFilename;
-    normalDownload(requests, reserved, op, downloadedFilename);
-
-    for_each(requests.begin(), requests.end(), Deleter());
-    for_each(reserved.begin(), reserved.end(), Deleter());
-    requests.clear();
-  }
+    else
+#endif // ENABLE_BITTORRENT
 #ifdef ENABLE_METALINK
-  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(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);
-    }
-    entry->dropUnsupportedResource();
-    entry->reorderResourcesByPreference();
-    Requests requests;
-    int cuidCounter = 1;
-    for(MetalinkResources::const_iterator itr = entry->resources.begin();
-	itr != entry->resources.end(); itr++) {
-      MetalinkResource* resource = *itr;
-      for(int s = 1; s <= op->getAsInt(PREF_SPLIT); s++) {
-	createRequest(cuidCounter, resource->url,
-		      op->get(PREF_REFERER), requests); 
-	cuidCounter++;
-      }
-    }
-    Requests reserved;
-    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()));
-      requests.erase(requests.begin()+maxConnection, requests.end());
-    }
-
-    setSignalHander(SIGINT, handler, 0);
-    setSignalHander(SIGTERM, handler, 0);
-
-    string downloadedFilename;
-    bool success = normalDownload(requests, reserved, op, downloadedFilename);
-
-    for_each(requests.begin(), requests.end(), Deleter());
-    for_each(reserved.begin(), reserved.end(), Deleter());
-    requests.clear();
+      if(op->defined(PREF_METALINK_FILE)) {
+      requestInfo = new MetalinkRequestInfo(op->get(PREF_METALINK_FILE),
+					    op);
+      } else
+#endif // ENABLE_METALINK
+	{
+	  requestInfo = new UrlRequestInfo(args, 0, op);
+	}
 
-    if(success) {
-#ifdef ENABLE_MESSAGE_DIGEST
-      if(entry->check(downloadedFilename)) {
-	printf("checksum OK.\n");
-      } else {
-	printf("checksum ERROR.\n");
+    while(requestInfo) {
+      RequestInfo* next = requestInfo->execute();
+      if(requestInfo->isFail()) {
+	delete requestInfo;
 	exit(EXIT_FAILURE);
       }
-#endif // ENABLE_MESSAGE_DIGEST
-    }
-
-    delete metalinker;
-  }
-#endif // ENABLE_METALINK
-#ifdef ENABLE_BITTORRENT
-  if(op->defined(PREF_TORRENT_FILE) ||
-     followTorrent && readyToTorrentMode) {
-    try {
-      //op->put(PREF_MAX_TRIES, "0");
-      setSignalHander(SIGINT, torrentHandler, SA_RESETHAND);
-      setSignalHander(SIGTERM, torrentHandler, SA_RESETHAND);
-
-      Request* req = new Request();
-      req->isTorrent = true;
-      req->setTrackerEvent(Request::STARTED);
-      te = new TorrentConsoleDownloadEngine();
-      te->option = op;
-      ByteArrayDiskWriter* byteArrayDiskWriter = new ByteArrayDiskWriter();
-      te->segmentMan = new SegmentMan();
-      te->segmentMan->diskWriter = byteArrayDiskWriter;
-      te->segmentMan->option = op;
-      te->segmentMan->splitter = new SplitSlowestSegmentSplitter();
-      te->segmentMan->splitter->setMinSegmentSize(op->getAsLLInt(PREF_MIN_SEGMENT_SIZE));
-      te->torrentMan = new TorrentMan();
-      te->torrentMan->setStoreDir(op->get(PREF_DIR));
-      te->torrentMan->option = op;
-      te->torrentMan->req = req;
-      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);
-	cout << _("Files:") << endl;
-	cout << "idx|path/length" << endl;
-	cout << "===+===========================================================================" << endl;
-	int count = 1;
-	for(FileEntries::const_iterator itr = fileEntries.begin();
-	    itr != fileEntries.end(); count++, itr++) {
-	  printf("%3d|%s\n   |%s Bytes\n", count, itr->path.c_str(),
-		 Util::llitos(itr->length, true).c_str());
-	  cout << "---+---------------------------------------------------------------------------" << endl;
-	}
-	exit(EXIT_SUCCESS);
-      } else {
-	if(selectFileIndexes.empty()) {
-	  Strings targetFiles;
-	  if(op->defined(PREF_TORRENT_FILE) && !args.empty()) {
-	    targetFiles = args;
-	  }
-	  te->torrentMan->setup(targetTorrentFile, targetFiles);
+      if(requestInfo->getFileInfo().checkReady()) {
+	if(requestInfo->getFileInfo().check()) {
+	  printf("checksum OK.\n");
 	} else {
-	  te->torrentMan->setup(targetTorrentFile, selectFileIndexes);
+	  // TODO
+	  printf("checksum ERROR.\n");
+	  exit(EXIT_FAILURE);
 	}
       }
-      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 {
-	port = listenCommand->bindPort(listenPort, listenPort);
-      }
-      if(port == -1) {
-	printf(_("Errors occurred while binding port.\n"));
-	exit(EXIT_FAILURE);
-      }
-      te->torrentMan->setPort(port);
-      te->commands.push_back(listenCommand);
-
-      te->commands.push_back(new TrackerWatcherCommand(te->torrentMan->getNewCuid(),
-						       te,
-						       te->torrentMan->minInterval));
-      te->commands.push_back(new TrackerUpdateCommand(te->torrentMan->getNewCuid(),
-						      te));
-      te->commands.push_back(new TorrentAutoSaveCommand(te->torrentMan->getNewCuid(),
-							te,
-							op->getAsInt(PREF_AUTO_SAVE_INTERVAL)));
-      te->commands.push_back(new PeerChokeCommand(te->torrentMan->getNewCuid(),
-						  10, te));
-      te->commands.push_back(new HaveEraseCommand(te->torrentMan->getNewCuid(),
-						  te, 10));
-      te->run();
-      
-      if(te->torrentMan->downloadComplete()) {
-	printDownloadCompeleteMessage();
-      }
-      delete req;
-      te->cleanQueue();
-      delete te;
-    } catch(Exception* ex) {
-      cerr << ex->getMsg() << endl;
-      delete ex;
-      exit(EXIT_FAILURE);
+      delete requestInfo;
+      requestInfo = next;
     }
+  } catch(Exception* ex) {
+    cerr << ex->getMsg() << endl;
+    delete ex;
+    exit(EXIT_FAILURE);
   }
-#endif // ENABLE_BITTORRENT
   delete op;
   LogFactory::release();
 #ifdef HAVE_LIBGNUTLS

+ 64 - 55
src/messageDigest.h

@@ -26,6 +26,8 @@
 
 #ifdef ENABLE_SSL
 
+#define MAX_MD_LENGTH (16+20)
+
 #ifdef HAVE_LIBSSL
 #include <openssl/evp.h>
 #endif // HAVE_LIBSSL
@@ -36,73 +38,80 @@
 
 class MessageDigestContext {
 public:
-  enum HashAlgo {
-    ALGO_MD5,
-    ALGO_SHA1
-  };
 #ifdef HAVE_LIBSSL
-  EVP_MD_CTX ctx;
-  const EVP_MD* algo;
+  typedef const EVP_MD* DigestAlgo;
+# define DIGEST_ALGO_MD5 EVP_md5()
+# define DIGEST_ALGO_SHA1 EVP_sha1()
 #endif // HAVE_LIBSSL
 #ifdef HAVE_LIBGCRYPT
-  gcry_md_hd_t ctx;
-  int algo;
+  typedef int DigestAlgo;
+# define DIGEST_ALGO_MD5 GCRY_MD_MD5
+# define DIGEST_ALGO_SHA1 GCRY_MD_SHA1
 #endif // HAVE_LIBGCRYPT
-
-  MessageDigestContext() {}
-  MessageDigestContext(HashAlgo algo) {
-    setAlgo(algo);
-  }
-
-  void setAlgo(HashAlgo algo) {
-    switch(algo) {
-    case ALGO_MD5:
+private:
 #ifdef HAVE_LIBSSL
-      this->algo = EVP_md5();
-#endif // HAVE_LIBSSL
-#ifdef HAVE_LIBGCRYPT
-      this->algo = GCRY_MD_MD5;
-#endif // HAVE_LIBGCRYPT
-      break;
-    case ALGO_SHA1:
-#ifdef HAVE_LIBSSL
-      this->algo = EVP_sha1();
+  EVP_MD_CTX ctx;
 #endif // HAVE_LIBSSL
 #ifdef HAVE_LIBGCRYPT
-      this->algo = GCRY_MD_SHA1;
-#endif // HAVE_LIBGCRYPT
-      break;
-    default:
-      break;
-    }
-  }
-};
+  gcry_md_hd_t ctx;
+#endif // HAVE_LIBGCRYPT  
+  DigestAlgo algo;
+public:
+  MessageDigestContext():
+    algo(DIGEST_ALGO_SHA1) {}
+  MessageDigestContext(DigestAlgo algo):
+    algo(algo) {}
 
 #ifdef HAVE_LIBSSL
-#define digestInit(CTX) EVP_MD_CTX_init(&CTX.ctx)
-#define digestReset(CTX) EVP_DigestInit_ex(&CTX.ctx, CTX.algo, NULL)
-#define digestUpdate(CTX, DATA, LENGTH) EVP_DigestUpdate(&CTX.ctx, DATA, LENGTH)
-#define digestFinal(CTX, HASH) \
-{\
-int len;\
-EVP_DigestFinal_ex(&CTX.ctx, HASH, (unsigned int*)&len);\
-}
-#define digestFree(CTX) EVP_MD_CTX_cleanup(&CTX.ctx)
-
+  void digestInit() {
+    EVP_MD_CTX_init(&ctx);
+    digestReset();
+  }
+  void digestReset() {
+    EVP_DigestInit_ex(&ctx, algo, 0);
+  }
+  void digestUpdate(const void* data, int length) {
+    EVP_DigestUpdate(&ctx, data, length);
+  }
+  void digestFinal(unsigned char* md) {
+    int len;
+    EVP_DigestFinal_ex(&ctx, md, (unsigned int*)&len);
+  }
+  void digestFree() {
+    EVP_MD_CTX_cleanup(&ctx);
+  }
+  int digestLength() const {
+    return digestLength(algo);
+  }
+  static int digestLength(DigestAlgo algo) {
+    return EVP_MD_size(algo);
+  }
 #endif // HAVE_LIBSSL
 
 #ifdef HAVE_LIBGCRYPT
-#define digestInit(CTX) gcry_md_open(&CTX.ctx, CTX.algo, 0)
-#define digestReset(CTX) gcry_md_reset(CTX.ctx)
-#define digestUpdate(CTX, DATA, LENGTH) gcry_md_write(CTX.ctx, DATA, LENGTH)
-#define digestFinal(CTX, HASH) \
-{\
-gcry_md_final(CTX.ctx);\
-memcpy(HASH, gcry_md_read(CTX.ctx, 0), gcry_md_get_algo_dlen(CTX.algo));\
-}
-#define digestFree(CTX) gcry_md_close(CTX.ctx)
+  void digestInit() {
+    gcry_md_open(&ctx, algo, 0);
+  }
+  void digestReset() {
+    gcry_md_reset(ctx);
+  }
+  void digestUpdate(const void* data, int length) {
+    gcry_md_write(ctx, data, length);
+  }
+  void digestFinal(unsigned char* md) {
+    gcry_md_final(ctx);
+    memcpy(md, gcry_md_read(ctx, 0), gcry_md_get_algo_dlen(algo));
+  }
+  void digestFree() {
+    gcry_md_close(ctx);
+  }
+  int digestLength() const {
+    return digestLength(algo);
+  }
+  static int digestLength(DigestAlgo algo) {
+    return gcry_md_get_algo_dlen(algo);
+  }
 #endif // HAVE_LIBGCRYPT
-
+};
 #endif // ENABLE_SSL
-
 #endif // _D_MESSAGE_DIGEST_H_

+ 8 - 0
src/prefs.h

@@ -57,6 +57,8 @@
 #define PREF_DAEMON "daemon"
 // value: a string
 #define PREF_REFERER "referer"
+// value' 1*digit
+#define PREF_LOWEST_SPEED_LIMIT "lowest_speed_limit"
 
 /**
  * FTP related preferences
@@ -116,6 +118,10 @@
 #define PREF_TORRENT_FILE "torrent_file"
 // values: 1*digit
 #define PREF_LISTEN_PORT "listen_port"
+// values: true | false
+#define PREF_FOLLOW_TORRENT "follow_torrent"
+// values: 1*digit *( (,|-) 1*digit)
+#define PREF_SELECT_FILE "select_file"
 
 /**
  * Metalink related preferences
@@ -130,5 +136,7 @@
 #define PREF_METALINK_OS "metalink_os"
 // values: 1*digit
 #define PREF_METALINK_SERVERS "metalink_servers"
+// values: true | false
+#define PREF_FOLLOW_METALINK "follow_metalink"
 
 #endif // _D_PREFS_H_

+ 15 - 4
test/MetalinkEntryTest.cc

@@ -48,11 +48,17 @@ MetalinkEntry* createTestEntry() {
   res4->type = MetalinkResource::TYPE_NOT_SUPPORTED;
   res4->location = "ad";
   res4->preference = 10;
+  MetalinkResource* res5 = new MetalinkResource();
+  res5->url = "https://myhost/aria2.tar.bz2";
+  res5->type = MetalinkResource::TYPE_HTTPS;
+  res5->location = "jp";
+  res5->preference = 90;
 
   entry->resources.push_back(res1);
   entry->resources.push_back(res2);
   entry->resources.push_back(res3);
   entry->resources.push_back(res4);
+  entry->resources.push_back(res5);
   return entry;
 }
 
@@ -61,12 +67,16 @@ void MetalinkEntryTest::testDropUnsupportedResource() {
 
   entry->dropUnsupportedResource();
 
-  CPPUNIT_ASSERT_EQUAL(2, (int)entry->resources.size());
+  CPPUNIT_ASSERT_EQUAL(4, (int)entry->resources.size());
   
   CPPUNIT_ASSERT_EQUAL((int)MetalinkResource::TYPE_FTP,
 		       entry->resources.at(0)->type);
   CPPUNIT_ASSERT_EQUAL((int)MetalinkResource::TYPE_HTTP,
 		       entry->resources.at(1)->type);
+  CPPUNIT_ASSERT_EQUAL((int)MetalinkResource::TYPE_BITTORRENT,
+		       entry->resources.at(2)->type);
+  CPPUNIT_ASSERT_EQUAL((int)MetalinkResource::TYPE_HTTPS,
+		       entry->resources.at(3)->type);
 }
 
 void MetalinkEntryTest::testReorderResourcesByPreference() {
@@ -75,9 +85,10 @@ void MetalinkEntryTest::testReorderResourcesByPreference() {
   entry->reorderResourcesByPreference();
 
   CPPUNIT_ASSERT_EQUAL(100, entry->resources.at(0)->preference);
-  CPPUNIT_ASSERT_EQUAL(60, entry->resources.at(1)->preference);
-  CPPUNIT_ASSERT_EQUAL(50, entry->resources.at(2)->preference);
-  CPPUNIT_ASSERT_EQUAL(10, entry->resources.at(3)->preference);
+  CPPUNIT_ASSERT_EQUAL(90, entry->resources.at(1)->preference);
+  CPPUNIT_ASSERT_EQUAL(60, entry->resources.at(2)->preference);
+  CPPUNIT_ASSERT_EQUAL(50, entry->resources.at(3)->preference);
+  CPPUNIT_ASSERT_EQUAL(10, entry->resources.at(4)->preference);
 }
 
 void MetalinkEntryTest::testCheck() {

+ 2 - 2
test/UtilTest.cc

@@ -224,12 +224,12 @@ void UtilTest::testRandomAlpha() {
 void UtilTest::testFileChecksum() {
   unsigned char buf[20];
   string filename = "4096chunk.txt";
-  Util::fileChecksum(filename, buf, MessageDigestContext::ALGO_SHA1);
+  Util::fileChecksum(filename, buf, DIGEST_ALGO_SHA1);
   string sha1 = Util::toHex(buf, 20);
   CPPUNIT_ASSERT_EQUAL(string("608cabc0f2fa18c260cafd974516865c772363d5"),
 		       sha1);
 
-  Util::fileChecksum(filename, buf, MessageDigestContext::ALGO_MD5);
+  Util::fileChecksum(filename, buf, DIGEST_ALGO_MD5);
   string md5 = Util::toHex(buf, 16);
   CPPUNIT_ASSERT_EQUAL(string("82a7348c2e03731109d0cf45a7325b88"),
 		       md5);