diff --git a/src/OptionHandlerFactory.cc b/src/OptionHandlerFactory.cc index 8f2b5e40..e42437a7 100644 --- a/src/OptionHandlerFactory.cc +++ b/src/OptionHandlerFactory.cc @@ -672,6 +672,16 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() handlers.push_back(op); } // HTTP/FTP options +#ifdef ENABLE_MESSAGE_DIGEST + { + SharedHandle op(new ChecksumOptionHandler + (PREF_CHECKSUM, + TEXT_CHECKSUM)); + op->addTag(TAG_FTP); + op->addTag(TAG_HTTP); + handlers.push_back(op); + } +#endif // ENABLE_MESSAGE_DIGEST { SharedHandle op(new NumberOptionHandler (PREF_CONNECT_TIMEOUT, diff --git a/src/OptionHandlerImpl.cc b/src/OptionHandlerImpl.cc index c8967f06..e94570b5 100644 --- a/src/OptionHandlerImpl.cc +++ b/src/OptionHandlerImpl.cc @@ -56,6 +56,9 @@ #include "FileEntry.h" #include "a2io.h" #include "LogFactory.h" +#ifdef ENABLE_MESSAGE_DIGEST +# include "MessageDigest.h" +#endif // ENABLE_MESSAGE_DIGEST namespace aria2 { @@ -408,6 +411,33 @@ std::string IndexOutOptionHandler::createPossibleValuesString() const return "INDEX=PATH"; } +ChecksumOptionHandler::ChecksumOptionHandler +(const std::string& optName, + const std::string& description, + char shortName) + : NameMatchOptionHandler(optName, description, NO_DEFAULT_VALUE, + OptionHandler::REQ_ARG, shortName) +{} + +ChecksumOptionHandler::~ChecksumOptionHandler() {} + +void ChecksumOptionHandler::parseArg(Option& option, const std::string& optarg) +{ + std::pair p; + util::divide(p, optarg, '='); + util::lowercase(p.first); + util::lowercase(p.second); + if(!MessageDigest::isValidHash(p.first, p.second)) { + throw DL_ABORT_EX(_("Unrecognized checksum")); + } + option.put(optName_, optarg); +} + +std::string ChecksumOptionHandler::createPossibleValuesString() const +{ + return "HASH_TYPE=HEX_DIGEST"; +} + ParameterOptionHandler::ParameterOptionHandler (const std::string& optName, const std::string& description, diff --git a/src/OptionHandlerImpl.h b/src/OptionHandlerImpl.h index fd1f2da9..cc842f7b 100644 --- a/src/OptionHandlerImpl.h +++ b/src/OptionHandlerImpl.h @@ -185,6 +185,17 @@ public: virtual std::string createPossibleValuesString() const; }; +class ChecksumOptionHandler : public NameMatchOptionHandler { +private: +public: + ChecksumOptionHandler(const std::string& optName, + const std::string& description, + char shortName = 0); + virtual ~ChecksumOptionHandler(); + virtual void parseArg(Option& option, const std::string& optarg); + virtual std::string createPossibleValuesString() const; +}; + class ParameterOptionHandler : public NameMatchOptionHandler { private: std::vector validParamValues_; diff --git a/src/download_helper.cc b/src/download_helper.cc index 749660d5..1c523809 100644 --- a/src/download_helper.cc +++ b/src/download_helper.cc @@ -169,7 +169,8 @@ const std::set& listRequestOptions() PREF_METALINK_BASE_URI, PREF_PAUSE, PREF_STREAM_PIECE_SELECTOR, - PREF_HASH_CHECK_ONLY + PREF_HASH_CHECK_ONLY, + PREF_CHECKSUM }; static std::set requestOptions (vbegin(REQUEST_OPTIONS), vend(REQUEST_OPTIONS)); @@ -229,6 +230,16 @@ SharedHandle createRequestGroup dctx->getFirstFileEntry()->setUris(uris); dctx->getFirstFileEntry()->setMaxConnectionPerServer (option->getAsInt(PREF_MAX_CONNECTION_PER_SERVER)); +#ifdef ENABLE_MESSAGE_DIGEST + const std::string& checksum = option->get(PREF_CHECKSUM); + if(!checksum.empty()) { + std::pair p; + util::divide(p, checksum, '='); + util::lowercase(p.first); + util::lowercase(p.second); + dctx->setDigest(p.first, p.second); + } +#endif // ENABLE_MESSAGE_DIGEST rg->setDownloadContext(dctx); rg->setPauseRequested(option->getAsBool(PREF_PAUSE)); removeOneshotOption(rg->getOption()); diff --git a/src/main.cc b/src/main.cc index b6d3544b..2c6fcd24 100644 --- a/src/main.cc +++ b/src/main.cc @@ -267,6 +267,7 @@ error_code::Value main(int argc, char* argv[]) op->remove(PREF_INDEX_OUT); op->remove(PREF_SELECT_FILE); op->remove(PREF_PAUSE); + op->remove(PREF_CHECKSUM); if(!op->getAsBool(PREF_ENABLE_RPC) && requestGroups.empty()) { global::cout()->printf("%s\n", MSG_NO_FILES_TO_DOWNLOAD); } else { diff --git a/src/prefs.cc b/src/prefs.cc index a451a5c1..92be4a48 100644 --- a/src/prefs.cc +++ b/src/prefs.cc @@ -223,6 +223,8 @@ const std::string PREF_PAUSE("pause"); const std::string PREF_DOWNLOAD_RESULT("download-result"); // value: true | false const std::string PREF_HASH_CHECK_ONLY("hash-check-only"); +// values: hashType=digest +const std::string PREF_CHECKSUM("checksum"); /** * FTP related preferences diff --git a/src/prefs.h b/src/prefs.h index 3385ce47..2fbe3872 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -240,6 +240,8 @@ extern const std::string V_ASCII; extern const std::string PREF_FTP_PASV; // values: true | false extern const std::string PREF_FTP_REUSE_CONNECTION; +// values: hashType=digest +extern const std::string PREF_CHECKSUM; /** * HTTP related preferences diff --git a/src/usage_text.h b/src/usage_text.h index 829af0fe..a88d62d7 100644 --- a/src/usage_text.h +++ b/src/usage_text.h @@ -822,3 +822,12 @@ _(" --hash-check-only[=true|false] If true is given, after hash check using\n" \ " --check-integrity option, abort download whether\n" \ " or not download is complete.") +#define TEXT_CHECKSUM \ + _(" --checksum=TYPE=DIGEST Set checksum. TYPE is hash type. The supported\n" \ + " hash type is listed in \"Hash Algorithms\" in\n" \ + " \"aria2c -v\". DIGEST is hex digest.\n" \ + " For example, setting sha-1 digest looks like\n" \ + " this:\n" \ + " sha-1=0192ba11326fe2298c8cb4de616f4d4140213838\n" \ + " This option applies only to HTTP(S)/FTP\n" \ + " downloads.")