Quellcode durchsuchen

Merge branch 'user-home-variable-expansion'

Tatsuhiro Tsujikawa vor 9 Jahren
Ursprung
Commit
380e5aa451
4 geänderte Dateien mit 127 neuen und 64 gelöschten Zeilen
  1. 37 0
      doc/manual-src/en/aria2c.rst
  2. 70 57
      src/OptionHandlerFactory.cc
  3. 15 6
      src/OptionHandlerImpl.cc
  4. 5 1
      src/OptionHandlerImpl.h

+ 37 - 0
doc/manual-src/en/aria2c.rst

@@ -1958,6 +1958,43 @@ lines beginning ``#`` are treated as comments::
   bits of the configuration file (e.g., ``chmod 600 aria2.conf``), so
   that other user cannot see the contents of the file.
 
+The environment variables, such as ``${HOME}``, are expanded by shell.
+This means that those variables used in configuration file are not
+expanded.  However, it is useful to ``${HOME}`` to refer user's home
+directory in configuration file to specify file paths.  Therefore,
+aria2 expands ``${HOME}`` found in the following option values to
+user's home directory:
+
+* :option:`ca-certificate <--ca-certificate>`
+* :option:`certificate <--certificate>`
+* :option:`dht-file-path <--dht-file-path>`
+* :option:`dht-file-path6 <--dht-file-path6>`
+* :option:`dir <--dir>`
+* :option:`input-file <--input-file>`
+* :option:`load-cookies <--load-cookies>`
+* :option:`log <--log>`
+* :option:`metalink-file <--metalink-file>`
+* :option:`netrc-path <--netrc-path>`
+* :option:`on-bt-download-complete <--on-bt-download-complete>`
+* :option:`on-download-complete <--on-download-complete>`
+* :option:`on-download-error <--on-download-error>`
+* :option:`on-download-start <--on-download-start>`
+* :option:`on-download-stop <--on-download-stop>`
+* :option:`on-download-pause <--on-download-pause>`
+* :option:`out <--out>`
+* :option:`private-key <--private-key>`
+* :option:`rpc-certificate <--rpc-certificate>`
+* :option:`rpc-private-key <--rpc-private-key>`
+* :option:`save-cookies <--save-cookies>`
+* :option:`save-session <--save-session>`
+* :option:`server-stat-if <--server-stat-if>`
+* :option:`server-stat-of <--server-stat-of>`
+* :option:`torrent-file <--torrent-file>`
+
+Note that this expansion occurs even if the above options are used in
+the command-line.  This means that expansion may occur 2 times: first,
+shell and then aria2c.
+
 dht.dat
 ~~~~~~~~
 

+ 70 - 57
src/OptionHandlerFactory.cc

@@ -200,9 +200,10 @@ std::vector<OptionHandler*> OptionHandlerFactory::createOptionHandlers()
     handlers.push_back(op);
   }
   {
-    OptionHandler* op(
-        new DefaultOptionHandler(PREF_DIR, TEXT_DIR, File::getCurrentDir(),
-                                 PATH_TO_DIR, OptionHandler::REQ_ARG, 'd'));
+    OptionHandler* op(new LocalFilePathOptionHandler(
+        PREF_DIR, TEXT_DIR, File::getCurrentDir(), /* acceptStdin = */ false,
+        'd',
+        /* mustExist = */ false, PATH_TO_DIR));
     op->addTag(TAG_BASIC);
     op->addTag(TAG_FILE);
     op->setInitialOption(true);
@@ -390,9 +391,9 @@ std::vector<OptionHandler*> OptionHandlerFactory::createOptionHandlers()
     handlers.push_back(op);
   }
   {
-    OptionHandler* op(new DefaultOptionHandler(
-        PREF_INPUT_FILE, TEXT_INPUT_FILE, NO_DEFAULT_VALUE, PATH_TO_FILE_STDIN,
-        OptionHandler::REQ_ARG, 'i'));
+    OptionHandler* op(new LocalFilePathOptionHandler(
+        PREF_INPUT_FILE, TEXT_INPUT_FILE, NO_DEFAULT_VALUE,
+        /* acceptStdin = */ true, 'i', /* mustExist = */ false));
     op->addTag(TAG_BASIC);
     handlers.push_back(op);
   }
@@ -413,9 +414,9 @@ std::vector<OptionHandler*> OptionHandlerFactory::createOptionHandlers()
     handlers.push_back(op);
   }
   {
-    OptionHandler* op(new DefaultOptionHandler(
-        PREF_LOG, TEXT_LOG, NO_DEFAULT_VALUE, PATH_TO_FILE_STDOUT,
-        OptionHandler::REQ_ARG, 'l'));
+    OptionHandler* op(new LocalFilePathOptionHandler(
+        PREF_LOG, TEXT_LOG, NO_DEFAULT_VALUE, /* acceptStdin = */ false, 'l',
+        /* mustExist = */ false, PATH_TO_FILE_STDOUT));
     op->addTag(TAG_BASIC);
     op->setChangeGlobalOption(true);
     handlers.push_back(op);
@@ -542,41 +543,46 @@ std::vector<OptionHandler*> OptionHandlerFactory::createOptionHandlers()
     handlers.push_back(op);
   }
   {
-    OptionHandler* op(new DefaultOptionHandler(
+    OptionHandler* op(new LocalFilePathOptionHandler(
         PREF_ON_DOWNLOAD_COMPLETE, TEXT_ON_DOWNLOAD_COMPLETE, NO_DEFAULT_VALUE,
+        /* acceptStdin = */ false, 0, /* mustExist = */ false,
         PATH_TO_COMMAND));
     op->addTag(TAG_ADVANCED);
     op->addTag(TAG_HOOK);
     handlers.push_back(op);
   }
   {
-    OptionHandler* op(
-        new DefaultOptionHandler(PREF_ON_DOWNLOAD_ERROR, TEXT_ON_DOWNLOAD_ERROR,
-                                 NO_DEFAULT_VALUE, PATH_TO_COMMAND));
+    OptionHandler* op(new LocalFilePathOptionHandler(
+        PREF_ON_DOWNLOAD_ERROR, TEXT_ON_DOWNLOAD_ERROR, NO_DEFAULT_VALUE,
+        /* acceptStdin = */ false, 0, /* mustExist = */ false,
+        PATH_TO_COMMAND));
     op->addTag(TAG_ADVANCED);
     op->addTag(TAG_HOOK);
     handlers.push_back(op);
   }
   {
-    OptionHandler* op(
-        new DefaultOptionHandler(PREF_ON_DOWNLOAD_PAUSE, TEXT_ON_DOWNLOAD_PAUSE,
-                                 NO_DEFAULT_VALUE, PATH_TO_COMMAND));
+    OptionHandler* op(new LocalFilePathOptionHandler(
+        PREF_ON_DOWNLOAD_PAUSE, TEXT_ON_DOWNLOAD_PAUSE, NO_DEFAULT_VALUE,
+        /* acceptStdin = */ false, 0, /* mustExist = */ false,
+        PATH_TO_COMMAND));
     op->addTag(TAG_ADVANCED);
     op->addTag(TAG_HOOK);
     handlers.push_back(op);
   }
   {
-    OptionHandler* op(
-        new DefaultOptionHandler(PREF_ON_DOWNLOAD_START, TEXT_ON_DOWNLOAD_START,
-                                 NO_DEFAULT_VALUE, PATH_TO_COMMAND));
+    OptionHandler* op(new LocalFilePathOptionHandler(
+        PREF_ON_DOWNLOAD_START, TEXT_ON_DOWNLOAD_START, NO_DEFAULT_VALUE,
+        /* acceptStdin = */ false, 0, /* mustExist = */ false,
+        PATH_TO_COMMAND));
     op->addTag(TAG_ADVANCED);
     op->addTag(TAG_HOOK);
     handlers.push_back(op);
   }
   {
-    OptionHandler* op(
-        new DefaultOptionHandler(PREF_ON_DOWNLOAD_STOP, TEXT_ON_DOWNLOAD_STOP,
-                                 NO_DEFAULT_VALUE, PATH_TO_COMMAND));
+    OptionHandler* op(new LocalFilePathOptionHandler(
+        PREF_ON_DOWNLOAD_STOP, TEXT_ON_DOWNLOAD_STOP, NO_DEFAULT_VALUE,
+        /* acceptStdin = */ false, 0, /* mustExist = */ false,
+        PATH_TO_COMMAND));
     op->addTag(TAG_ADVANCED);
     op->addTag(TAG_HOOK);
     handlers.push_back(op);
@@ -645,8 +651,9 @@ std::vector<OptionHandler*> OptionHandlerFactory::createOptionHandlers()
     handlers.push_back(op);
   }
   {
-    OptionHandler* op(new DefaultOptionHandler(
-        PREF_SAVE_SESSION, TEXT_SAVE_SESSION, NO_DEFAULT_VALUE, PATH_TO_FILE));
+    OptionHandler* op(new LocalFilePathOptionHandler(
+        PREF_SAVE_SESSION, TEXT_SAVE_SESSION, NO_DEFAULT_VALUE,
+        /* acceptStdin = */ false, 0, /* mustExist = */ false));
     op->addTag(TAG_ADVANCED);
     op->setChangeGlobalOption(true);
     handlers.push_back(op);
@@ -741,8 +748,9 @@ std::vector<OptionHandler*> OptionHandlerFactory::createOptionHandlers()
   {
     OptionHandler* op(
 #ifdef HAVE_APPLETLS
-        new DefaultOptionHandler(PREF_RPC_CERTIFICATE, TEXT_RPC_CERTIFICATE,
-                                 NO_DEFAULT_VALUE)
+        new LocalFilePathOptionHandler(
+            PREF_RPC_CERTIFICATE, TEXT_RPC_CERTIFICATE, NO_DEFAULT_VALUE,
+            /* acceptStdin = */ false, 0, /* mustExist = */ false)
 #else  // HAVE_APPLETLS
         new LocalFilePathOptionHandler(
             PREF_RPC_CERTIFICATE, TEXT_RPC_CERTIFICATE, NO_DEFAULT_VALUE, false)
@@ -884,9 +892,9 @@ std::vector<OptionHandler*> OptionHandlerFactory::createOptionHandlers()
     handlers.push_back(op);
   }
   {
-    OptionHandler* op(new DefaultOptionHandler(PREF_OUT, TEXT_OUT,
-                                               NO_DEFAULT_VALUE, PATH_TO_FILE,
-                                               OptionHandler::REQ_ARG, 'o'));
+    OptionHandler* op(new LocalFilePathOptionHandler(
+        PREF_OUT, TEXT_OUT, NO_DEFAULT_VALUE,
+        /* acceptStdin = */ false, 'o', /* mustExist = */ false));
     op->addTag(TAG_BASIC);
     op->addTag(TAG_FTP);
     op->addTag(TAG_HTTP);
@@ -937,17 +945,17 @@ std::vector<OptionHandler*> OptionHandlerFactory::createOptionHandlers()
     handlers.push_back(op);
   }
   {
-    OptionHandler* op(new DefaultOptionHandler(PREF_SERVER_STAT_IF,
-                                               TEXT_SERVER_STAT_IF,
-                                               NO_DEFAULT_VALUE, PATH_TO_FILE));
+    OptionHandler* op(new LocalFilePathOptionHandler(
+        PREF_SERVER_STAT_IF, TEXT_SERVER_STAT_IF, NO_DEFAULT_VALUE,
+        /* acceptStdin = */ false, 0, /* mustExist = */ false));
     op->addTag(TAG_FTP);
     op->addTag(TAG_HTTP);
     handlers.push_back(op);
   }
   {
-    OptionHandler* op(new DefaultOptionHandler(PREF_SERVER_STAT_OF,
-                                               TEXT_SERVER_STAT_OF,
-                                               NO_DEFAULT_VALUE, PATH_TO_FILE));
+    OptionHandler* op(new LocalFilePathOptionHandler(
+        PREF_SERVER_STAT_OF, TEXT_SERVER_STAT_OF, NO_DEFAULT_VALUE,
+        /* acceptStdin = */ false, 0, /* mustExist = */ false));
     op->addTag(TAG_FTP);
     op->addTag(TAG_HTTP);
     op->setChangeGlobalOption(true);
@@ -1012,14 +1020,14 @@ std::vector<OptionHandler*> OptionHandlerFactory::createOptionHandlers()
   }
   // HTTP Specific Options
   {
-    OptionHandler* op(new DefaultOptionHandler(PREF_CA_CERTIFICATE,
-                                               TEXT_CA_CERTIFICATE,
+    OptionHandler* op(new LocalFilePathOptionHandler(
+        PREF_CA_CERTIFICATE, TEXT_CA_CERTIFICATE,
 #ifdef CA_BUNDLE
-                                               CA_BUNDLE,
+        CA_BUNDLE,
 #else
-                                               "",
+        "",
 #endif
-                                               PATH_TO_FILE));
+        /* acceptStdin = */ false, 0, /* mustExist = */ false));
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTPS);
     handlers.push_back(op);
@@ -1128,8 +1136,9 @@ std::vector<OptionHandler*> OptionHandlerFactory::createOptionHandlers()
     handlers.push_back(op);
   }
   {
-    OptionHandler* op(new DefaultOptionHandler(
-        PREF_LOAD_COOKIES, TEXT_LOAD_COOKIES, NO_DEFAULT_VALUE, PATH_TO_FILE));
+    OptionHandler* op(new LocalFilePathOptionHandler(
+        PREF_LOAD_COOKIES, TEXT_LOAD_COOKIES, NO_DEFAULT_VALUE,
+        /* acceptStdin = */ false, 0, /* mustExist = */ false));
     op->addTag(TAG_BASIC);
     op->addTag(TAG_HTTP);
     op->addTag(TAG_COOKIE);
@@ -1151,8 +1160,9 @@ std::vector<OptionHandler*> OptionHandlerFactory::createOptionHandlers()
     handlers.push_back(op);
   }
   {
-    OptionHandler* op(new DefaultOptionHandler(
-        PREF_PRIVATE_KEY, TEXT_PRIVATE_KEY, NO_DEFAULT_VALUE, PATH_TO_FILE));
+    OptionHandler* op(new LocalFilePathOptionHandler(
+        PREF_PRIVATE_KEY, TEXT_PRIVATE_KEY, NO_DEFAULT_VALUE,
+        /* acceptStdin = */ false, 0, /* mustExist = */ false));
     op->addTag(TAG_HTTP);
     op->addTag(TAG_HTTPS);
     handlers.push_back(op);
@@ -1166,8 +1176,9 @@ std::vector<OptionHandler*> OptionHandlerFactory::createOptionHandlers()
     handlers.push_back(op);
   }
   {
-    OptionHandler* op(new DefaultOptionHandler(
-        PREF_SAVE_COOKIES, TEXT_SAVE_COOKIES, NO_DEFAULT_VALUE, PATH_TO_FILE));
+    OptionHandler* op(new LocalFilePathOptionHandler(
+        PREF_SAVE_COOKIES, TEXT_SAVE_COOKIES, NO_DEFAULT_VALUE,
+        /* acceptStdin = */ false, 0, /* mustExist = */ false));
     op->addTag(TAG_HTTP);
     op->addTag(TAG_COOKIE);
     op->setChangeGlobalOption(true);
@@ -1252,9 +1263,9 @@ std::vector<OptionHandler*> OptionHandlerFactory::createOptionHandlers()
     handlers.push_back(op);
   }
   {
-    OptionHandler* op(new DefaultOptionHandler(PREF_NETRC_PATH, TEXT_NETRC_PATH,
-                                               util::getHomeDir() + "/.netrc",
-                                               PATH_TO_FILE));
+    OptionHandler* op(new LocalFilePathOptionHandler(
+        PREF_NETRC_PATH, TEXT_NETRC_PATH, util::getHomeDir() + "/.netrc",
+        /* acceptStdin = */ false, 0, /* mustExist = */ false));
     handlers.push_back(op);
   }
   // Proxy options
@@ -1682,16 +1693,16 @@ std::vector<OptionHandler*> OptionHandlerFactory::createOptionHandlers()
     handlers.push_back(op);
   }
   {
-    OptionHandler* op(
-        new DefaultOptionHandler(PREF_DHT_FILE_PATH, TEXT_DHT_FILE_PATH,
-                                 util::getDHTFile(false), PATH_TO_FILE));
+    OptionHandler* op(new LocalFilePathOptionHandler(
+        PREF_DHT_FILE_PATH, TEXT_DHT_FILE_PATH, util::getDHTFile(false),
+        /* acceptStdin = */ false, 0, /* mustExist = */ false));
     op->addTag(TAG_BITTORRENT);
     handlers.push_back(op);
   }
   {
-    OptionHandler* op(
-        new DefaultOptionHandler(PREF_DHT_FILE_PATH6, TEXT_DHT_FILE_PATH6,
-                                 util::getDHTFile(true), PATH_TO_FILE));
+    OptionHandler* op(new LocalFilePathOptionHandler(
+        PREF_DHT_FILE_PATH6, TEXT_DHT_FILE_PATH6, util::getDHTFile(true),
+        /* acceptStdin = */ false, 0, /* mustExist = */ false));
     op->addTag(TAG_BITTORRENT);
     handlers.push_back(op);
   }
@@ -1795,9 +1806,11 @@ std::vector<OptionHandler*> OptionHandlerFactory::createOptionHandlers()
     handlers.push_back(op);
   }
   {
-    OptionHandler* op(new DefaultOptionHandler(
+    OptionHandler* op(new LocalFilePathOptionHandler(
         PREF_ON_BT_DOWNLOAD_COMPLETE, TEXT_ON_BT_DOWNLOAD_COMPLETE,
-        NO_DEFAULT_VALUE, PATH_TO_COMMAND));
+        NO_DEFAULT_VALUE,
+        /* acceptStdin = */ false, 0, /* mustExist = */ false,
+        PATH_TO_COMMAND));
     op->addTag(TAG_ADVANCED);
     op->addTag(TAG_HOOK);
     handlers.push_back(op);

+ 15 - 6
src/OptionHandlerImpl.cc

@@ -531,10 +531,13 @@ std::string HttpProxyOptionHandler::createPossibleValuesString() const
 
 LocalFilePathOptionHandler::LocalFilePathOptionHandler(
     PrefPtr pref, const char* description, const std::string& defaultValue,
-    bool acceptStdin, char shortName)
+    bool acceptStdin, char shortName, bool mustExist,
+    const std::string& possibleValuesString)
     : AbstractOptionHandler(pref, description, defaultValue,
                             OptionHandler::REQ_ARG, shortName),
-      acceptStdin_(acceptStdin)
+      possibleValuesString_(possibleValuesString),
+      acceptStdin_(acceptStdin),
+      mustExist_(mustExist)
 {
 }
 
@@ -545,16 +548,22 @@ void LocalFilePathOptionHandler::parseArg(Option& option,
     option.put(pref_, DEV_STDIN);
   }
   else {
-    File f(optarg);
-    if (!f.exists() || f.isDir()) {
-      throw DL_ABORT_EX(fmt(MSG_NOT_FILE, optarg.c_str()));
+    auto path = util::replace(optarg, "${HOME}", util::getHomeDir());
+    if (mustExist_) {
+      File f(path);
+      if (!f.exists() || f.isDir()) {
+        throw DL_ABORT_EX(fmt(MSG_NOT_FILE, optarg.c_str()));
+      }
     }
-    option.put(pref_, optarg);
+    option.put(pref_, path);
   }
 }
 
 std::string LocalFilePathOptionHandler::createPossibleValuesString() const
 {
+  if (!possibleValuesString_.empty()) {
+    return possibleValuesString_;
+  }
   if (acceptStdin_) {
     return PATH_TO_FILE_STDIN;
   }

+ 5 - 1
src/OptionHandlerImpl.h

@@ -232,13 +232,17 @@ public:
 
 class LocalFilePathOptionHandler : public AbstractOptionHandler {
 private:
+  std::string possibleValuesString_;
   bool acceptStdin_;
+  bool mustExist_;
 
 public:
   LocalFilePathOptionHandler(PrefPtr pref,
                              const char* description = NO_DESCRIPTION,
                              const std::string& defaultValue = NO_DEFAULT_VALUE,
-                             bool acceptStdin = false, char shortName = 0);
+                             bool acceptStdin = false, char shortName = 0,
+                             bool mustExist = true,
+                             const std::string& possibleValuesString = "");
   virtual void parseArg(Option& option,
                         const std::string& optarg) const CXX11_OVERRIDE;
   virtual std::string createPossibleValuesString() const CXX11_OVERRIDE;