Browse Source

2010-03-12 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>

	Resurrected --http-proxy-user and --http-proxy-passwd option.
	Added --https-proxy-user, --https-proxy-passwd, --ftp-proxy-user,
	--ftp-proxy-passwd, --all-proxy-user, --all-proxy-passwd option.
	* doc/aria2c.1.txt
	* src/OptionHandlerFactory.cc
	* src/OptionHandlerImpl.h
	* src/prefs.cc
	* src/prefs.h
	* src/usage_text.h
	* test/OptionHandlerTest.cc
Tatsuhiro Tsujikawa 15 years ago
parent
commit
ca2b33c3da
10 changed files with 560 additions and 9 deletions
  1. 13 0
      ChangeLog
  2. 90 3
      doc/aria2c.1
  3. 91 1
      doc/aria2c.1.html
  4. 54 1
      doc/aria2c.1.txt
  5. 70 0
      src/OptionHandlerFactory.cc
  6. 116 4
      src/OptionHandlerImpl.h
  7. 8 0
      src/prefs.cc
  8. 8 0
      src/prefs.h
  9. 16 0
      src/usage_text.h
  10. 94 0
      test/OptionHandlerTest.cc

+ 13 - 0
ChangeLog

@@ -1,3 +1,16 @@
+2010-03-12  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
+
+	Resurrected --http-proxy-user and --http-proxy-passwd option.
+	Added --https-proxy-user, --https-proxy-passwd, --ftp-proxy-user,
+	--ftp-proxy-passwd, --all-proxy-user, --all-proxy-passwd option.
+	* doc/aria2c.1.txt
+	* src/OptionHandlerFactory.cc
+	* src/OptionHandlerImpl.h
+	* src/prefs.cc
+	* src/prefs.h
+	* src/usage_text.h
+	* test/OptionHandlerTest.cc
+
 2010-03-10  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
 
 	Updated Russian and Simplified Chinese translation. Thanks to all

+ 90 - 3
doc/aria2c.1

@@ -2,12 +2,12 @@
 .\"     Title: aria2c
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
 .\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
-.\"      Date: 03/09/2010
+.\"      Date: 03/12/2010
 .\"    Manual: Aria2 Manual
-.\"    Source: Aria2 1.9.0a
+.\"    Source: Aria2 1.9.0
 .\"  Language: English
 .\"
-.TH "ARIA2C" "1" "03/09/2010" "Aria2 1\&.9\&.0a" "Aria2 Manual"
+.TH "ARIA2C" "1" "03/12/2010" "Aria2 1\&.9\&.0" "Aria2 Manual"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -114,6 +114,36 @@ and
 \fB\-\-ftp\-proxy\fR
 options\&. This affects all URLs\&. The format of PROXY is [http://][USER:PASSWORD@]HOST[:PORT]
 .RE
+.if n \{\
+.sp
+.\}
+.RS 4
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
+\fBNote\fR
+.ps -1
+.br
+.sp
+If user and password are embedded in proxy URI and they are also specified by \fB\-\-{http,https,ftp,all}\-proxy\-{user,passwd}\fR options, those appeared later have precedence\&. For example, you have http\-proxy\-user="myname", http\-proxy\-passwd="mypass" in aria2\&.conf and you specify \-\-http\-proxy="http://proxy" in command\-line, then you get HTTP proxy "http://proxy" with user "myname" and password "mypass"\&. Another example: if you specified in command\-line \-\-http\-proxy="http://user:pass@proxy" \-\-http\-proxy\-user="myname" \-\-http\-proxy\-passwd="mypass", then you will get HTTP proxy "http://proxy" with user "myname" and password "mypass"\&. One more example: if you specified in command\-line \-\-http\-proxy\-user="myname" \-\-http\-proxy\-passwd="mypass" \-\-http\-proxy="http://user:pass@proxy", then you get HTTP proxy "http://proxy" with user "user" and password "pass"\&.
+.sp .5v
+.RE
+.PP
+\fB\-\-all\-proxy\-passwd\fR=PASSWD
+.RS 4
+Set password for
+\fB\-\-all\-proxy\fR
+option\&.
+.RE
+.PP
+\fB\-\-all\-proxy\-user\fR=USER
+.RS 4
+Set user for
+\fB\-\-all\-proxy\fR
+option\&.
+.RE
 .PP
 \fB\-\-connect\-timeout\fR=SEC
 .RS 4
@@ -339,6 +369,25 @@ Use this proxy server for HTTP\&. To erase previously defined proxy, use ""\&. S
 option\&. This affects all URLs\&. The format of PROXY is [http://][USER:PASSWORD@]HOST[:PORT]
 .RE
 .PP
+\fB\-\-http\-proxy\-passwd\fR=PASSWD
+.RS 4
+Set password for
+\fB\-\-http\-proxy\fR
+option\&.
+.RE
+.sp
+\fB\-\-http\-proxy\-user\fR=USER:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+Set user for *\-\-http\-proxy* option\&.
+.fi
+.if n \{\
+.RE
+.\}
+.PP
 \fB\-\-https\-proxy\fR=PROXY
 .RS 4
 Use this proxy server for HTTPS\&. To erase previously defined proxy, use ""\&. See also
@@ -346,6 +395,20 @@ Use this proxy server for HTTPS\&. To erase previously defined proxy, use ""\&.
 option\&. This affects all URLs\&. The format of PROXY is [http://][USER:PASSWORD@]HOST[:PORT]
 .RE
 .PP
+\fB\-\-https\-proxy\-passwd\fR=PASSWD
+.RS 4
+Set password for
+\fB\-\-https\-proxy\fR
+option\&.
+.RE
+.PP
+\fB\-\-https\-proxy\-user\fR=USER
+.RS 4
+Set user for
+\fB\-\-https\-proxy\fR
+option\&.
+.RE
+.PP
 \fB\-\-private\-key\fR=FILE
 .RS 4
 Use the private key in FILE\&. The private key must be decrypted and in PEM format\&. The behavior when encrypted one is given is undefined\&. See also
@@ -444,6 +507,20 @@ Use this proxy server for FTP\&. To erase previously defined proxy, use ""\&. Se
 option\&. This affects all URLs\&. The format of PROXY is [http://][USER:PASSWORD@]HOST[:PORT]
 .RE
 .PP
+\fB\-\-ftp\-proxy\-passwd\fR=PASSWD
+.RS 4
+Set password for
+\fB\-\-ftp\-proxy\fR
+option\&.
+.RE
+.PP
+\fB\-\-ftp\-proxy\-user\fR=USER
+.RS 4
+Set user for
+\fB\-\-ftp\-proxy\fR
+option\&.
+.RE
+.PP
 \fB\-\-ftp\-type\fR=TYPE
 .RS 4
 Set FTP transfer type\&. TYPE is either
@@ -2889,6 +2966,16 @@ aria2c \-\-http\-proxy="http://username:password@proxy:8080" "http://host/file"
 .if n \{\
 .RE
 .\}
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+aria2c \-\-http\-proxy="http://proxy:8080" \-\-http\-proxy\-user="username" \-\-http\-proxy\-passwd="password" "http://host/file"
+.fi
+.if n \{\
+.RE
+.\}
 .RE
 .SS "Metalink Download"
 .sp

+ 91 - 1
doc/aria2c.1.html

@@ -685,6 +685,45 @@ downloading a file like BitTorrent.</p></div>
   The format of PROXY is [<a href="http://][USER:PASSWORD@]HOST[:PORT">http://][USER:PASSWORD@]HOST[:PORT</a>]
 </p>
 </dd>
+</dl></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<div class="title">Note</div>
+</td>
+<td class="content">If user and password are embedded in proxy URI and they are also
+specified by <strong>--{http,https,ftp,all}-proxy-{user,passwd}</strong> options,
+those appeared later have precedence. For example, you have
+http-proxy-user="myname", http-proxy-passwd="mypass" in aria2.conf and
+you specify --http-proxy="http://proxy" in command-line, then you get
+HTTP proxy "http://proxy" with user "myname" and password
+"mypass". Another example: if you specified in command-line
+--http-proxy="http://user:pass@proxy" --http-proxy-user="myname"
+--http-proxy-passwd="mypass", then you will get HTTP proxy
+"http://proxy" with user "myname" and password "mypass".  One more
+example: if you specified in command-line --http-proxy-user="myname"
+--http-proxy-passwd="mypass" --http-proxy="http://user:pass@proxy",
+then you get HTTP proxy "http://proxy" with user "user" and password
+"pass".</td>
+</tr></table>
+</div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
+<strong>--all-proxy-passwd</strong>=PASSWD
+</dt>
+<dd>
+<p>
+  Set password for <strong>--all-proxy</strong> option.
+</p>
+</dd>
+<dt class="hdlist1">
+<strong>--all-proxy-user</strong>=USER
+</dt>
+<dd>
+<p>
+  Set user for <strong>--all-proxy</strong> option.
+</p>
+</dd>
 <dt class="hdlist1">
 <strong>--connect-timeout</strong>=SEC
 </dt>
@@ -970,6 +1009,21 @@ aria2c -o myfile.zip "http://mirror1/file.zip" "http://mirror2/file.zip"</td>
 </p>
 </dd>
 <dt class="hdlist1">
+<strong>--http-proxy-passwd</strong>=PASSWD
+</dt>
+<dd>
+<p>
+  Set password for <strong>--http-proxy</strong> option.
+</p>
+</dd>
+</dl></div>
+<div class="paragraph"><p><strong>--http-proxy-user</strong>=USER:</p></div>
+<div class="literalblock">
+<div class="content">
+<pre><tt>Set user for *--http-proxy* option.</tt></pre>
+</div></div>
+<div class="dlist"><dl>
+<dt class="hdlist1">
 <strong>--https-proxy</strong>=PROXY
 </dt>
 <dd>
@@ -980,6 +1034,22 @@ aria2c -o myfile.zip "http://mirror1/file.zip" "http://mirror2/file.zip"</td>
 </p>
 </dd>
 <dt class="hdlist1">
+<strong>--https-proxy-passwd</strong>=PASSWD
+</dt>
+<dd>
+<p>
+  Set password for <strong>--https-proxy</strong> option.
+</p>
+</dd>
+<dt class="hdlist1">
+<strong>--https-proxy-user</strong>=USER
+</dt>
+<dd>
+<p>
+  Set user for <strong>--https-proxy</strong> option.
+</p>
+</dd>
+<dt class="hdlist1">
 <strong>--private-key</strong>=FILE
 </dt>
 <dd>
@@ -1120,6 +1190,22 @@ aria2c -o myfile.zip "http://mirror1/file.zip" "http://mirror2/file.zip"</td>
 </p>
 </dd>
 <dt class="hdlist1">
+<strong>--ftp-proxy-passwd</strong>=PASSWD
+</dt>
+<dd>
+<p>
+  Set password for <strong>--ftp-proxy</strong> option.
+</p>
+</dd>
+<dt class="hdlist1">
+<strong>--ftp-proxy-user</strong>=USER
+</dt>
+<dd>
+<p>
+  Set user for <strong>--ftp-proxy</strong> option.
+</p>
+</dd>
+<dt class="hdlist1">
 <strong>--ftp-type</strong>=TYPE
 </dt>
 <dd>
@@ -3504,6 +3590,10 @@ You can specify proxy in the environment variables. See <strong>ENVIRONMENT</str
 <div class="content">
 <pre><tt>aria2c --http-proxy="http://username:password@proxy:8080" "http://host/file"</tt></pre>
 </div></div>
+<div class="listingblock">
+<div class="content">
+<pre><tt>aria2c --http-proxy="http://proxy:8080" --http-proxy-user="username" --http-proxy-passwd="password" "http://host/file"</tt></pre>
+</div></div>
 <h3 id="_metalink_download">Metalink Download</h3><div style="clear:left"></div>
 <h4 id="_download_files_with_remote_metalink">Download files with remote Metalink</h4>
 <div class="listingblock">
@@ -3824,7 +3914,7 @@ files in the program, then also delete it here.</p></div>
 <div id="footnotes"><hr /></div>
 <div id="footer">
 <div id="footer-text">
-Last updated 2010-03-09 00:04:25 JST
+Last updated 2010-03-11 23:51:12 JST
 </div>
 </div>
 </body>

+ 54 - 1
doc/aria2c.1.txt

@@ -3,7 +3,7 @@ ARIA2C(1)
 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
 :man source: Aria2
 :man manual: Aria2 Manual
-:man version: 1.9.0a
+:man version: 1.9.0
 
 NAME
 ----
@@ -84,6 +84,31 @@ HTTP/FTP Options
   *--https-proxy* and *--ftp-proxy* options.  This affects all URLs.
   The format of PROXY is [\http://][USER:PASSWORD@]HOST[:PORT]
 
+[NOTE]
+
+If user and password are embedded in proxy URI and they are also
+specified by *--{http,https,ftp,all}-proxy-{user,passwd}* options,
+those appeared later have precedence. For example, you have
+http-proxy-user="myname", http-proxy-passwd="mypass" in aria2.conf and
+you specify --http-proxy="http://proxy" in command-line, then you get
+HTTP proxy "http://proxy" with user "myname" and password
+"mypass". Another example: if you specified in command-line
+--http-proxy="http://user:pass@proxy" --http-proxy-user="myname"
+--http-proxy-passwd="mypass", then you will get HTTP proxy
+"http://proxy" with user "myname" and password "mypass".  One more
+example: if you specified in command-line --http-proxy-user="myname"
+--http-proxy-passwd="mypass" --http-proxy="http://user:pass@proxy",
+then you get HTTP proxy "http://proxy" with user "user" and password
+"pass".
+
+*--all-proxy-passwd*=PASSWD::
+
+  Set password for *--all-proxy* option.
+
+*--all-proxy-user*=USER::
+
+  Set user for *--all-proxy* option.
+
 *--connect-timeout*=SEC::
   Set the connect timeout in seconds to establish connection to
   HTTP/FTP/proxy server. After the connection is established, this
@@ -239,12 +264,28 @@ HTTP Specific Options
   use "".  See also *--all-proxy* option.  This affects all URLs.  The
   format of PROXY is [\http://][USER:PASSWORD@]HOST[:PORT]
 
+*--http-proxy-passwd*=PASSWD::
+
+  Set password for *--http-proxy* option.
+
+*--http-proxy-user*=USER:
+
+  Set user for *--http-proxy* option.
+
 *--https-proxy*=PROXY::
 
   Use this proxy server for HTTPS. To erase previously defined proxy,
   use "". See also *--all-proxy* option.  This affects all URLs.  The
   format of PROXY is [\http://][USER:PASSWORD@]HOST[:PORT]
 
+*--https-proxy-passwd*=PASSWD::
+
+  Set password for *--https-proxy* option.
+
+*--https-proxy-user*=USER::
+
+  Set user for *--https-proxy* option.
+
 *--private-key*=FILE::
   Use the private key in FILE.
   The private key must be decrypted and in PEM format.
@@ -315,6 +356,14 @@ FTP Specific Options
   use "".  See also *--all-proxy* option.  This affects all URLs.  The
   format of PROXY is [\http://][USER:PASSWORD@]HOST[:PORT]
 
+*--ftp-proxy-passwd*=PASSWD::
+
+  Set password for *--ftp-proxy* option.
+
+*--ftp-proxy-user*=USER::
+
+  Set user for *--ftp-proxy* option.
+
 *--ftp-type*=TYPE::
   Set FTP transfer type. TYPE is either 'binary' or 'ascii'.
   Default: 'binary'
@@ -1754,6 +1803,10 @@ Proxy with authorization
 aria2c --http-proxy="http://username:password@proxy:8080" "http://host/file"
 ----------------------------------------------------------------------------
 
+----------------------------------------------------------------------------
+aria2c --http-proxy="http://proxy:8080" --http-proxy-user="username" --http-proxy-passwd="password" "http://host/file"
+----------------------------------------------------------------------------
+
 Metalink Download
 ~~~~~~~~~~~~~~~~~
 Download files with remote Metalink

+ 70 - 0
src/OptionHandlerFactory.cc

@@ -871,6 +871,22 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
     op->addTag(TAG_HTTP);
     handlers.push_back(op);
   }
+  {
+    SharedHandle<OptionHandler> op(new HttpProxyPasswdOptionHandler
+                                   (PREF_HTTP_PROXY_PASSWD,
+                                    TEXT_HTTP_PROXY_PASSWD,
+                                    NO_DEFAULT_VALUE));
+    op->addTag(TAG_HTTP);
+    handlers.push_back(op);
+  }
+  {
+    SharedHandle<OptionHandler> op(new HttpProxyUserOptionHandler
+                                   (PREF_HTTP_PROXY_USER,
+                                    TEXT_HTTP_PROXY_USER,
+                                    NO_DEFAULT_VALUE));
+    op->addTag(TAG_HTTP);
+    handlers.push_back(op);
+  }
   {
     SharedHandle<OptionHandler> op(new HttpProxyOptionHandler
                                    (PREF_HTTPS_PROXY,
@@ -880,6 +896,24 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
     op->addTag(TAG_HTTPS);
     handlers.push_back(op);
   }
+  {
+    SharedHandle<OptionHandler> op(new HttpProxyPasswdOptionHandler
+                                   (PREF_HTTPS_PROXY_PASSWD,
+                                    TEXT_HTTPS_PROXY_PASSWD,
+                                    NO_DEFAULT_VALUE));
+    op->addTag(TAG_HTTP);
+    op->addTag(TAG_HTTPS);
+    handlers.push_back(op);
+  }
+  {
+    SharedHandle<OptionHandler> op(new HttpProxyUserOptionHandler
+                                   (PREF_HTTPS_PROXY_USER,
+                                    TEXT_HTTPS_PROXY_USER,
+                                    NO_DEFAULT_VALUE));
+    op->addTag(TAG_HTTP);
+    op->addTag(TAG_HTTPS);
+    handlers.push_back(op);
+  }
   {
     SharedHandle<OptionHandler> op(new HttpProxyOptionHandler
                                    (PREF_FTP_PROXY,
@@ -888,6 +922,22 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
     op->addTag(TAG_FTP);
     handlers.push_back(op);
   }
+  {
+    SharedHandle<OptionHandler> op(new HttpProxyPasswdOptionHandler
+                                   (PREF_FTP_PROXY_PASSWD,
+                                    TEXT_FTP_PROXY_PASSWD,
+                                    NO_DEFAULT_VALUE));
+    op->addTag(TAG_FTP);
+    handlers.push_back(op);
+  }
+  {
+    SharedHandle<OptionHandler> op(new HttpProxyUserOptionHandler
+                                   (PREF_FTP_PROXY_USER,
+                                    TEXT_FTP_PROXY_USER,
+                                    NO_DEFAULT_VALUE));
+    op->addTag(TAG_FTP);
+    handlers.push_back(op);
+  }
   {
     SharedHandle<OptionHandler> op(new HttpProxyOptionHandler
                                    (PREF_ALL_PROXY,
@@ -898,6 +948,26 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers()
     op->addTag(TAG_HTTPS);
     handlers.push_back(op);
   }
+  {
+    SharedHandle<OptionHandler> op(new HttpProxyPasswdOptionHandler
+                                   (PREF_ALL_PROXY_PASSWD,
+                                    TEXT_ALL_PROXY_PASSWD,
+                                    NO_DEFAULT_VALUE));
+    op->addTag(TAG_FTP);
+    op->addTag(TAG_HTTP);
+    op->addTag(TAG_HTTPS);
+    handlers.push_back(op);
+  }
+  {
+    SharedHandle<OptionHandler> op(new HttpProxyUserOptionHandler
+                                   (PREF_ALL_PROXY_USER,
+                                    TEXT_ALL_PROXY_USER,
+                                    NO_DEFAULT_VALUE));
+    op->addTag(TAG_FTP);
+    op->addTag(TAG_HTTP);
+    op->addTag(TAG_HTTPS);
+    handlers.push_back(op);
+  }
   {
     SharedHandle<OptionHandler> op(new DefaultOptionHandler
                                    (PREF_NO_PROXY,

+ 116 - 4
src/OptionHandlerImpl.h

@@ -37,6 +37,7 @@
 
 #include "OptionHandler.h"
 
+#include <cassert>
 #include <cstdio>
 #include <utility>
 #include <algorithm>
@@ -543,7 +544,96 @@ public:
   }
 };
 
+class HttpProxyUserOptionHandler:public NameMatchOptionHandler {
+public:
+  HttpProxyUserOptionHandler(const std::string& optName,
+                             const std::string& description,
+                             const std::string& defaultValue,
+                             char shortName = 0):
+    NameMatchOptionHandler(optName, description, defaultValue,
+                           OptionHandler::REQ_ARG, shortName)
+  {}
+
+  virtual void parseArg(Option& option, const std::string& optarg)
+  {
+    if(util::endsWith(_optName, "-user")) {
+      const std::string proxyPref = _optName.substr(0, _optName.size()-5);
+      const std::string& olduri = option.get(proxyPref);
+      if(!olduri.empty()) {
+        Request req;
+        bool b = req.setUri(olduri);
+        assert(b);
+        std::string uri = "http://";
+        if(!optarg.empty()) {
+          uri += util::percentEncode(optarg);
+        }
+        if(req.hasPassword()) {
+          uri += A2STR::COLON_C;
+          uri += util::percentEncode(req.getPassword());
+        }
+        if(uri.size() > 7) {
+          uri += "@";
+        }
+        strappend(uri, req.getHost(),A2STR::COLON_C,util::uitos(req.getPort()));
+        option.put(proxyPref, uri);
+      }
+    }
+    option.put(_optName, optarg);
+  }
+
+  virtual std::string createPossibleValuesString() const
+  {
+    return "";
+  }
+};
+
+class HttpProxyPasswdOptionHandler:public NameMatchOptionHandler {
+public:
+  HttpProxyPasswdOptionHandler(const std::string& optName,
+                               const std::string& description,
+                               const std::string& defaultValue,
+                               char shortName = 0):
+    NameMatchOptionHandler(optName, description, defaultValue,
+                           OptionHandler::REQ_ARG, shortName)
+  {}
+
+  virtual void parseArg(Option& option, const std::string& optarg)
+  {
+    if(util::endsWith(_optName, "-passwd")) {
+      const std::string proxyPref = _optName.substr(0, _optName.size()-7);
+      const std::string& olduri = option.get(proxyPref);
+      if(!olduri.empty()) {
+        Request req;
+        bool b = req.setUri(olduri);
+        assert(b);
+        std::string uri = "http://";
+        if(!req.getUsername().empty()) {
+          uri += util::percentEncode(req.getUsername());
+        }
+        uri += A2STR::COLON_C;
+        if(!optarg.empty()) {
+          uri += util::percentEncode(optarg);
+        }
+        if(uri.size() > 7) {
+          uri += "@";
+        }
+        strappend(uri, req.getHost(), A2STR::COLON_C,util::itos(req.getPort()));
+        option.put(proxyPref, uri);
+      }
+    }
+    option.put(_optName, optarg);
+  }
+
+  virtual std::string createPossibleValuesString() const
+  {
+    return "";
+  }
+};
+
 class HttpProxyOptionHandler : public NameMatchOptionHandler {
+private:
+  std::string _proxyUserPref;
+  std::string _proxyPasswdPref;
 public:
   HttpProxyOptionHandler(const std::string& optName,
                          const std::string& description,
@@ -551,7 +641,9 @@ public:
                          char shortName = 0)
     :
     NameMatchOptionHandler(optName, description, defaultValue,
-                           OptionHandler::REQ_ARG, shortName)
+                           OptionHandler::REQ_ARG, shortName),
+    _proxyUserPref(_optName+"-user"),
+    _proxyPasswdPref(_optName+"-passwd")
   {}
 
   virtual ~HttpProxyOptionHandler() {}
@@ -568,11 +660,31 @@ public:
       } else {
         uri = "http://"+optarg;
       }
-      if(req.setUri(uri)) {
-        option.put(_optName, uri);
-      } else {
+      if(!req.setUri(uri)) {
         throw DL_ABORT_EX(_("unrecognized proxy format"));
       }
+      uri = "http://";
+      if(req.getUsername().empty()) {
+        if(option.defined(_proxyUserPref)) {
+          uri += util::percentEncode(option.get(_proxyUserPref));
+        }
+      } else {
+        uri += util::percentEncode(req.getUsername());
+      }
+      if(!req.hasPassword()) {
+        if(option.defined(_proxyPasswdPref)) {
+          uri += A2STR::COLON_C;
+          uri += util::percentEncode(option.get(_proxyPasswdPref));
+        }
+      } else {
+        uri += A2STR::COLON_C;
+        uri += util::percentEncode(req.getPassword());
+      }
+      if(uri.size() > 7) {
+        uri += "@";
+      }
+      strappend(uri, req.getHost(), A2STR::COLON_C, util::uitos(req.getPort()));
+      option.put(_optName, uri);
     }
   }
 

+ 8 - 0
src/prefs.cc

@@ -240,6 +240,14 @@ const std::string PREF_NO_PROXY("no-proxy");
 const std::string PREF_PROXY_METHOD("proxy-method");
 const std::string V_GET("get");
 const std::string V_TUNNEL("tunnel");
+const std::string PREF_HTTP_PROXY_USER("http-proxy-user");
+const std::string PREF_HTTP_PROXY_PASSWD("http-proxy-passwd");
+const std::string PREF_HTTPS_PROXY_USER("https-proxy-user");
+const std::string PREF_HTTPS_PROXY_PASSWD("https-proxy-passwd");
+const std::string PREF_FTP_PROXY_USER("ftp-proxy-user");
+const std::string PREF_FTP_PROXY_PASSWD("ftp-proxy-passwd");
+const std::string PREF_ALL_PROXY_USER("all-proxy-user");
+const std::string PREF_ALL_PROXY_PASSWD("all-proxy-passwd");
 
 /**
  * BitTorrent related preferences

+ 8 - 0
src/prefs.h

@@ -244,6 +244,14 @@ extern const std::string PREF_NO_PROXY;
 extern const std::string PREF_PROXY_METHOD;
 extern const std::string V_GET;
 extern const std::string V_TUNNEL;
+extern const std::string PREF_HTTP_PROXY_USER;
+extern const std::string PREF_HTTP_PROXY_PASSWD;
+extern const std::string PREF_HTTPS_PROXY_USER;
+extern const std::string PREF_HTTPS_PROXY_PASSWD;
+extern const std::string PREF_FTP_PROXY_USER;
+extern const std::string PREF_FTP_PROXY_PASSWD;
+extern const std::string PREF_ALL_PROXY_USER;
+extern const std::string PREF_ALL_PROXY_PASSWD;
 
 /**
  * BitTorrent related preferences

+ 16 - 0
src/usage_text.h

@@ -618,3 +618,19 @@
 #define TEXT_REUSE_URI                          \
   _(" --reuse-uri[=true|false]     Reuse already used URIs if no unused URIs are\n" \
     "                              left.")
+#define TEXT_ALL_PROXY_USER                                             \
+  _(" --all-proxy-user=USER        Set user for --all-proxy option.")
+#define TEXT_ALL_PROXY_PASSWD                                           \
+  _(" --all-proxy-passwd=PASSWD    Set password for --all-proxy option.")
+#define TEXT_HTTP_PROXY_USER                                            \
+  _(" --http-proxy-user=USER       Set user for --http-proxy option.")
+#define TEXT_HTTP_PROXY_PASSWD                                          \
+  _(" --http-proxy-passwd=PASSWD   Set password for --http-proxy option.")
+#define TEXT_HTTPS_PROXY_USER                                           \
+  _(" --https-proxy-user=USER      Set user for --https-proxy option.")
+#define TEXT_HTTPS_PROXY_PASSWD                                         \
+  _(" --https-proxy-passwd=PASSWD  Set password for --https-proxy option.")
+#define TEXT_FTP_PROXY_USER                                             \
+  _(" --ftp-proxy-user=USER        Set user for --ftp-proxy option.")
+#define TEXT_FTP_PROXY_PASSWD                                           \
+  _(" --ftp-proxy-passwd=PASSWD    Set password for --ftp-proxy option.")

+ 94 - 0
test/OptionHandlerTest.cc

@@ -26,6 +26,8 @@ class OptionHandlerTest:public CppUnit::TestFixture {
   CPPUNIT_TEST(testFloatNumberOptionHandler_max);
   CPPUNIT_TEST(testFloatNumberOptionHandler_min_max);
   CPPUNIT_TEST(testHttpProxyOptionHandler);
+  CPPUNIT_TEST(testHttpProxyUserOptionHandler);
+  CPPUNIT_TEST(testHttpProxyPasswdOptionHandler);
   CPPUNIT_TEST_SUITE_END();
   
 public:
@@ -45,6 +47,8 @@ public:
   void testFloatNumberOptionHandler_max();
   void testFloatNumberOptionHandler_min_max();
   void testHttpProxyOptionHandler();
+  void testHttpProxyUserOptionHandler();
+  void testHttpProxyPasswdOptionHandler();
 };
 
 
@@ -323,6 +327,96 @@ void OptionHandlerTest::testHttpProxyOptionHandler()
   } catch(Exception& e) {}
   CPPUNIT_ASSERT_EQUAL(std::string("[http://][USER:PASSWORD@]HOST[:PORT]"),
                        handler.createPossibleValuesString());
+
+  handler.parse(option, "http://user%40:passwd%40@proxy:8080");
+  CPPUNIT_ASSERT_EQUAL(std::string("http://user%40:passwd%40@proxy:8080"),
+                       option.get(PREF_HTTP_PROXY));
+
+  option.put(PREF_HTTP_PROXY_USER, "proxy@user");
+  handler.parse(option, "http://proxy:8080");
+  CPPUNIT_ASSERT_EQUAL(std::string("http://proxy%40user@proxy:8080"),
+                       option.get(PREF_HTTP_PROXY));
+
+  option.put(PREF_HTTP_PROXY_PASSWD, "proxy@passwd");
+  handler.parse(option, "http://proxy:8080");
+  CPPUNIT_ASSERT_EQUAL
+    (std::string("http://proxy%40user:proxy%40passwd@proxy:8080"),
+     option.get(PREF_HTTP_PROXY));
+
+  handler.parse(option, "http://user:passwd@proxy:8080");
+  CPPUNIT_ASSERT_EQUAL(std::string("http://user:passwd@proxy:8080"),
+                       option.get(PREF_HTTP_PROXY));
+
+  option.put(PREF_HTTP_PROXY_USER, "");
+  handler.parse(option, "http://proxy:8080");
+  CPPUNIT_ASSERT_EQUAL(std::string("http://:proxy%40passwd@proxy:8080"),
+                       option.get(PREF_HTTP_PROXY));
+
+  option.put(PREF_HTTP_PROXY_PASSWD, "");
+  handler.parse(option, "http://proxy:8080");
+  CPPUNIT_ASSERT_EQUAL(std::string("http://:@proxy:8080"),
+                       option.get(PREF_HTTP_PROXY));
+}
+
+void OptionHandlerTest::testHttpProxyUserOptionHandler()
+{
+  HttpProxyUserOptionHandler handler(PREF_HTTP_PROXY_USER, "", "");
+  Option option;
+  handler.parse(option, "proxyuser");
+  CPPUNIT_ASSERT_EQUAL(std::string("proxyuser"),
+                       option.get(PREF_HTTP_PROXY_USER));
+
+  option.put(PREF_HTTP_PROXY, "http://proxy:8080");
+  handler.parse(option, "proxy@user");
+  CPPUNIT_ASSERT_EQUAL(std::string("proxy@user"),
+                       option.get(PREF_HTTP_PROXY_USER));
+  CPPUNIT_ASSERT_EQUAL(std::string("http://proxy%40user@proxy:8080"),
+                       option.get(PREF_HTTP_PROXY));
+
+  option.put(PREF_HTTP_PROXY, "http://user@proxy:8080");
+  handler.parse(option, "proxyuser");
+  CPPUNIT_ASSERT_EQUAL(std::string("http://proxyuser@proxy:8080"),
+                       option.get(PREF_HTTP_PROXY));
+
+  option.put(PREF_HTTP_PROXY, "http://user:passwd%40@proxy:8080");
+  handler.parse(option, "proxyuser");
+  CPPUNIT_ASSERT_EQUAL(std::string("http://proxyuser:passwd%40@proxy:8080"),
+                       option.get(PREF_HTTP_PROXY));
+
+  handler.parse(option, "");
+  CPPUNIT_ASSERT_EQUAL(std::string("http://:passwd%40@proxy:8080"),
+                       option.get(PREF_HTTP_PROXY));
+}
+
+void OptionHandlerTest::testHttpProxyPasswdOptionHandler()
+{
+  HttpProxyPasswdOptionHandler handler(PREF_HTTP_PROXY_PASSWD, "", "");
+  Option option;
+  handler.parse(option, "proxypasswd");
+  CPPUNIT_ASSERT_EQUAL(std::string("proxypasswd"),
+                       option.get(PREF_HTTP_PROXY_PASSWD));
+
+  option.put(PREF_HTTP_PROXY, "http://proxy:8080");
+  handler.parse(option, "proxy@passwd");
+  CPPUNIT_ASSERT_EQUAL(std::string("proxy@passwd"),
+                       option.get(PREF_HTTP_PROXY_PASSWD));
+  CPPUNIT_ASSERT_EQUAL(std::string("http://:proxy%40passwd@proxy:8080"),
+                       option.get(PREF_HTTP_PROXY));
+
+  option.put(PREF_HTTP_PROXY, "http://:pass@proxy:8080");
+  handler.parse(option, "proxypasswd");
+  CPPUNIT_ASSERT_EQUAL(std::string("http://:proxypasswd@proxy:8080"),
+                       option.get(PREF_HTTP_PROXY));
+
+  option.put(PREF_HTTP_PROXY, "http://user%40:pass@proxy:8080");
+  handler.parse(option, "proxypasswd");
+  CPPUNIT_ASSERT_EQUAL(std::string("http://user%40:proxypasswd@proxy:8080"),
+                       option.get(PREF_HTTP_PROXY));
+
+  handler.parse(option, "");
+  CPPUNIT_ASSERT_EQUAL(std::string("http://user%40:@proxy:8080"),
+                       option.get(PREF_HTTP_PROXY));
+  
 }
 
 } // namespace aria2