From 9214e7250148135675db18c3d697f095454170c3 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Wed, 23 Nov 2016 22:30:39 +0900 Subject: [PATCH 1/2] Expand ${HOME} to user's home directory in several options The following options implement this substitution: * --ca-certificate * --certificate * --dht-file-path * --dht-file-path6 * --dir * --input-file * --load-cookies * --log * --metalink-file * --netrc-path * --on-bt-download-complete * --on-download-complete * --on-download-error * --on-download-start * --on-download-stop * --on-download_pause * --out * --private-key * --rpc-certificate * --rpc-private-key * --save-cookies * --save-session * --server-stat-if * --server-stat-of * --torrent-file --- src/OptionHandlerFactory.cc | 127 ++++++++++++++++++++---------------- src/OptionHandlerImpl.cc | 21 ++++-- src/OptionHandlerImpl.h | 6 +- 3 files changed, 90 insertions(+), 64 deletions(-) diff --git a/src/OptionHandlerFactory.cc b/src/OptionHandlerFactory.cc index 99b6ca35..fd963613 100644 --- a/src/OptionHandlerFactory.cc +++ b/src/OptionHandlerFactory.cc @@ -200,9 +200,10 @@ std::vector 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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); diff --git a/src/OptionHandlerImpl.cc b/src/OptionHandlerImpl.cc index 23e03876..6be23492 100644 --- a/src/OptionHandlerImpl.cc +++ b/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; } diff --git a/src/OptionHandlerImpl.h b/src/OptionHandlerImpl.h index f153a721..7846b226 100644 --- a/src/OptionHandlerImpl.h +++ b/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; From 63f47cbbc5d9b8e1dae09b06a6d2eda4fb0f2297 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Wed, 23 Nov 2016 22:52:27 +0900 Subject: [PATCH 2/2] Document about ${HOME} expansion --- doc/manual-src/en/aria2c.rst | 37 ++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/doc/manual-src/en/aria2c.rst b/doc/manual-src/en/aria2c.rst index 37d01a9b..4ffea4c7 100644 --- a/doc/manual-src/en/aria2c.rst +++ b/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 ~~~~~~~~