/* */ #include "OptionHandlerImpl.h" #include #include #include #include #include #include #include #include #include "util.h" #include "DlAbortEx.h" #include "prefs.h" #include "Option.h" #include "fmt.h" #include "A2STR.h" #include "Request.h" #include "a2functional.h" #include "message.h" #include "File.h" #include "FileEntry.h" #include "a2io.h" #include "LogFactory.h" #include "uri.h" #ifdef ENABLE_MESSAGE_DIGEST # include "MessageDigest.h" #endif // ENABLE_MESSAGE_DIGEST namespace aria2 { BooleanOptionHandler::BooleanOptionHandler (const Pref* pref, const std::string& description, const std::string& defaultValue, OptionHandler::ARG_TYPE argType, char shortName) : AbstractOptionHandler(pref, description, defaultValue, argType, shortName) {} BooleanOptionHandler::~BooleanOptionHandler() {} void BooleanOptionHandler::parseArg(Option& option, const std::string& optarg) { if(optarg == "true" || ((argType_ == OptionHandler::OPT_ARG || argType_ == OptionHandler::NO_ARG) && optarg.empty())) { option.put(pref_, A2_V_TRUE); } else if(optarg == "false") { option.put(pref_, A2_V_FALSE); } else { std::string msg = pref_->k; strappend(msg, " ", _("must be either 'true' or 'false'.")); throw DL_ABORT_EX(msg); } } std::string BooleanOptionHandler::createPossibleValuesString() const { return "true, false"; } IntegerRangeOptionHandler::IntegerRangeOptionHandler (const Pref* pref, const std::string& description, const std::string& defaultValue, int32_t min, int32_t max, char shortName) : AbstractOptionHandler(pref, description, defaultValue, OptionHandler::REQ_ARG, shortName), min_(min), max_(max) {} IntegerRangeOptionHandler::~IntegerRangeOptionHandler() {} void IntegerRangeOptionHandler::parseArg (Option& option, const std::string& optarg) { IntSequence seq = util::parseIntRange(optarg); while(seq.hasNext()) { int32_t v = seq.next(); if(v < min_ || max_ < v) { std::string msg = pref_->k; strappend(msg, " ", _("must be between %s and %s.")); throw DL_ABORT_EX (fmt(msg.c_str(), util::itos(min_).c_str(), util::itos(max_).c_str())); } option.put(pref_, optarg); } } std::string IntegerRangeOptionHandler::createPossibleValuesString() const { return util::itos(min_)+"-"+util::itos(max_); } NumberOptionHandler::NumberOptionHandler (const Pref* pref, const std::string& description, const std::string& defaultValue, int64_t min, int64_t max, char shortName) : AbstractOptionHandler(pref, description, defaultValue, OptionHandler::REQ_ARG, shortName), min_(min), max_(max) {} NumberOptionHandler::~NumberOptionHandler() {} void NumberOptionHandler::parseArg(Option& option, const std::string& optarg) { int64_t num = util::parseLLInt(optarg); parseArg(option, num); } void NumberOptionHandler::parseArg(Option& option, int64_t number) { if((min_ == -1 || min_ <= number) && (max_ == -1 || number <= max_)) { option.put(pref_, util::itos(number)); } else { std::string msg = pref_->k; msg += " "; if(min_ == -1 && max_ != -1) { msg += fmt(_("must be smaller than or equal to %s."), util::itos(max_).c_str()); } else if(min_ != -1 && max_ != -1) { msg += fmt(_("must be between %s and %s."), util::itos(min_).c_str(), util::itos(max_).c_str()); } else if(min_ != -1 && max_ == -1) { msg += fmt(_("must be greater than or equal to %s."), util::itos(min_).c_str()); } else { msg += _("must be a number."); } throw DL_ABORT_EX(msg); } } std::string NumberOptionHandler::createPossibleValuesString() const { std::string values; if(min_ == -1) { values += "*"; } else { values += util::itos(min_); } values += "-"; if(max_ == -1) { values += "*"; } else { values += util::itos(max_); } return values; } UnitNumberOptionHandler::UnitNumberOptionHandler (const Pref* pref, const std::string& description, const std::string& defaultValue, int64_t min, int64_t max, char shortName) : NumberOptionHandler(pref, description, defaultValue, min, max, shortName) {} UnitNumberOptionHandler::~UnitNumberOptionHandler() {} void UnitNumberOptionHandler::parseArg (Option& option, const std::string& optarg) { int64_t num = util::getRealSize(optarg); NumberOptionHandler::parseArg(option, num); } FloatNumberOptionHandler::FloatNumberOptionHandler (const Pref* pref, const std::string& description, const std::string& defaultValue, double min, double max, char shortName) : AbstractOptionHandler(pref, description, defaultValue, OptionHandler::REQ_ARG, shortName), min_(min), max_(max) {} FloatNumberOptionHandler::~FloatNumberOptionHandler() {} void FloatNumberOptionHandler::parseArg (Option& option, const std::string& optarg) { double number = strtod(optarg.c_str(), 0); if((min_ < 0 || min_ <= number) && (max_ < 0 || number <= max_)) { option.put(pref_, optarg); } else { std::string msg = pref_->k; msg += " "; if(min_ < 0 && max_ >= 0) { msg += fmt(_("must be smaller than or equal to %.1f."), max_); } else if(min_ >= 0 && max_ >= 0) { msg += fmt(_("must be between %.1f and %.1f."), min_, max_); } else if(min_ >= 0 && max_ < 0) { msg += fmt(_("must be greater than or equal to %.1f."), min_); } else { msg += _("must be a number."); } throw DL_ABORT_EX(msg); } } std::string FloatNumberOptionHandler::createPossibleValuesString() const { std::string valuesString; if(min_ < 0) { valuesString += "*"; } else { char buf[11]; snprintf(buf, sizeof(buf), "%.1f", min_); valuesString += buf; } valuesString += "-"; if(max_ < 0) { valuesString += "*"; } else { char buf[11]; snprintf(buf, sizeof(buf), "%.1f", max_); valuesString += buf; } return valuesString; } DefaultOptionHandler::DefaultOptionHandler (const Pref* pref, const std::string& description, const std::string& defaultValue, const std::string& possibleValuesString, OptionHandler::ARG_TYPE argType, char shortName) : AbstractOptionHandler(pref, description, defaultValue, argType, shortName), possibleValuesString_(possibleValuesString) {} DefaultOptionHandler::~DefaultOptionHandler() {} void DefaultOptionHandler::parseArg(Option& option, const std::string& optarg) { option.put(pref_, optarg); } std::string DefaultOptionHandler::createPossibleValuesString() const { return possibleValuesString_; } CumulativeOptionHandler::CumulativeOptionHandler (const Pref* pref, const std::string& description, const std::string& defaultValue, const std::string& delim, const std::string& possibleValuesString, OptionHandler::ARG_TYPE argType, char shortName) : AbstractOptionHandler(pref, description, defaultValue, argType, shortName), delim_(delim), possibleValuesString_(possibleValuesString) {} CumulativeOptionHandler::~CumulativeOptionHandler() {} void CumulativeOptionHandler::parseArg (Option& option, const std::string& optarg) { std::string value = option.get(pref_); strappend(value, optarg, delim_); option.put(pref_, value); } std::string CumulativeOptionHandler::createPossibleValuesString() const { return possibleValuesString_; } IndexOutOptionHandler::IndexOutOptionHandler (const Pref* pref, const std::string& description, char shortName) : AbstractOptionHandler(pref, description, NO_DEFAULT_VALUE, OptionHandler::REQ_ARG, shortName) {} IndexOutOptionHandler::~IndexOutOptionHandler() {} void IndexOutOptionHandler::parseArg(Option& option, const std::string& optarg) { // See optarg is in the fomrat of "INDEX=PATH" util::parseIndexPath(optarg); std::string value = option.get(pref_); strappend(value, optarg, "\n"); option.put(pref_, value); } std::string IndexOutOptionHandler::createPossibleValuesString() const { return "INDEX=PATH"; } #ifdef ENABLE_MESSAGE_DIGEST ChecksumOptionHandler::ChecksumOptionHandler (const Pref* pref, const std::string& description, char shortName) : AbstractOptionHandler(pref, 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(pref_, optarg); } std::string ChecksumOptionHandler::createPossibleValuesString() const { return "HASH_TYPE=HEX_DIGEST"; } #endif // ENABLE_MESSAGE_DIGEST ParameterOptionHandler::ParameterOptionHandler (const Pref* pref, const std::string& description, const std::string& defaultValue, const std::vector& validParamValues, char shortName) : AbstractOptionHandler(pref, description, defaultValue, OptionHandler::REQ_ARG, shortName), validParamValues_(validParamValues) {} ParameterOptionHandler::ParameterOptionHandler (const Pref* pref, const std::string& description, const std::string& defaultValue, const std::string& validParamValue, char shortName) : AbstractOptionHandler(pref, description, defaultValue, OptionHandler::REQ_ARG, shortName) { validParamValues_.push_back(validParamValue); } ParameterOptionHandler::ParameterOptionHandler (const Pref* pref, const std::string& description, const std::string& defaultValue, const std::string& validParamValue1, const std::string& validParamValue2, char shortName) : AbstractOptionHandler(pref, description, defaultValue, OptionHandler::REQ_ARG, shortName) { validParamValues_.push_back(validParamValue1); validParamValues_.push_back(validParamValue2); } ParameterOptionHandler::ParameterOptionHandler (const Pref* pref, const std::string& description, const std::string& defaultValue, const std::string& validParamValue1, const std::string& validParamValue2, const std::string& validParamValue3, char shortName) : AbstractOptionHandler(pref, description, defaultValue, OptionHandler::REQ_ARG, shortName) { validParamValues_.push_back(validParamValue1); validParamValues_.push_back(validParamValue2); validParamValues_.push_back(validParamValue3); } ParameterOptionHandler::~ParameterOptionHandler() {} void ParameterOptionHandler::parseArg(Option& option, const std::string& optarg) { std::vector::const_iterator itr = std::find(validParamValues_.begin(), validParamValues_.end(), optarg); if(itr == validParamValues_.end()) { std::string msg = pref_->k; strappend(msg, " ", _("must be one of the following:")); if(validParamValues_.size() == 0) { msg += "''"; } else { for(std::vector::const_iterator itr = validParamValues_.begin(), eoi = validParamValues_.end(); itr != eoi; ++itr) { strappend(msg, "'", *itr, "' "); } } throw DL_ABORT_EX(msg); } else { option.put(pref_, optarg); } } std::string ParameterOptionHandler::createPossibleValuesString() const { std::stringstream s; std::copy(validParamValues_.begin(), validParamValues_.end(), std::ostream_iterator(s, ", ")); return util::strip(s.str(), ", "); } HostPortOptionHandler::HostPortOptionHandler (const Pref* pref, const std::string& description, const std::string& defaultValue, const Pref* hostOptionName, const Pref* portOptionName, char shortName) : AbstractOptionHandler(pref, description, defaultValue, OptionHandler::REQ_ARG, shortName), hostOptionName_(hostOptionName), portOptionName_(portOptionName) {} HostPortOptionHandler::~HostPortOptionHandler() {} void HostPortOptionHandler::parseArg(Option& option, const std::string& optarg) { std::string uri = "http://"; uri += optarg; Request req; if(!req.setUri(uri)) { throw DL_ABORT_EX(_("Unrecognized format")); } option.put(pref_, optarg); setHostAndPort(option, req.getHost(), req.getPort()); } void HostPortOptionHandler::setHostAndPort (Option& option, const std::string& hostname, uint16_t port) { option.put(hostOptionName_, hostname); option.put(portOptionName_, util::uitos(port)); } std::string HostPortOptionHandler::createPossibleValuesString() const { return "HOST:PORT"; } HttpProxyUserOptionHandler::HttpProxyUserOptionHandler (const Pref* pref, const std::string& description, const std::string& defaultValue, char shortName) : AbstractOptionHandler(pref, description, defaultValue, OptionHandler::REQ_ARG, shortName) {} void HttpProxyUserOptionHandler::parseArg (Option& option, const std::string& optarg) { if(util::endsWith(pref_->k, "-user")) { const Pref* proxyPref = option::k2p(pref_->k.substr(0, pref_->k.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(pref_, optarg); } std::string HttpProxyUserOptionHandler::createPossibleValuesString() const { return ""; } HttpProxyPasswdOptionHandler::HttpProxyPasswdOptionHandler (const Pref* pref, const std::string& description, const std::string& defaultValue, char shortName) : AbstractOptionHandler(pref, description, defaultValue, OptionHandler::REQ_ARG, shortName) {} void HttpProxyPasswdOptionHandler::parseArg (Option& option, const std::string& optarg) { if(util::endsWith(pref_->k, "-passwd")) { const Pref* proxyPref = option::k2p(pref_->k.substr(0, pref_->k.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(pref_, optarg); } std::string HttpProxyPasswdOptionHandler::createPossibleValuesString() const { return ""; } HttpProxyOptionHandler::HttpProxyOptionHandler (const Pref* pref, const std::string& description, const std::string& defaultValue, char shortName) : AbstractOptionHandler(pref, description, defaultValue, OptionHandler::REQ_ARG, shortName), proxyUserPref_(option::k2p(pref->k+"-user")), proxyPasswdPref_(option::k2p(pref->k+"-passwd")) {} HttpProxyOptionHandler::~HttpProxyOptionHandler() {} void HttpProxyOptionHandler::parseArg(Option& option, const std::string& optarg) { if(optarg.empty()) { option.put(pref_, optarg); } else { Request req; std::string uri; if(util::startsWith(optarg, "http://") || util::startsWith(optarg, "https://") || util::startsWith(optarg, "ftp://")) { uri = optarg; } else { uri = "http://"; uri += optarg; } uri::UriStruct us; if(!uri::parse(us, uri)) { throw DL_ABORT_EX(_("unrecognized proxy format")); } us.protocol = "http"; if(us.username.empty()) { if(option.defined(proxyUserPref_)) { us.username = option.get(proxyUserPref_); } } if(!us.hasPassword) { if(option.defined(proxyPasswdPref_)) { us.password = option.get(proxyPasswdPref_); us.hasPassword = true; } } option.put(pref_, uri::construct(us)); } } std::string HttpProxyOptionHandler::createPossibleValuesString() const { return "[http://][USER:PASSWORD@]HOST[:PORT]"; } LocalFilePathOptionHandler::LocalFilePathOptionHandler (const Pref* pref, const std::string& description, const std::string& defaultValue, bool acceptStdin, char shortName) : AbstractOptionHandler(pref, description, defaultValue, OptionHandler::REQ_ARG, shortName), acceptStdin_(acceptStdin) {} void LocalFilePathOptionHandler::parseArg (Option& option, const std::string& optarg) { if(acceptStdin_ && optarg == "-") { 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())); } option.put(pref_, optarg); } } std::string LocalFilePathOptionHandler::createPossibleValuesString() const { if(acceptStdin_) { return PATH_TO_FILE_STDIN; } else { return PATH_TO_FILE; } } PrioritizePieceOptionHandler::PrioritizePieceOptionHandler (const Pref* pref, const std::string& description, const std::string& defaultValue, char shortName) : AbstractOptionHandler(pref, description, defaultValue, OptionHandler::REQ_ARG, shortName) {} void PrioritizePieceOptionHandler::parseArg (Option& option, const std::string& optarg) { // Parse optarg against empty FileEntry list to detect syntax // error. std::vector result; util::parsePrioritizePieceRange (result, optarg, std::vector >(), 1024); option.put(pref_, optarg); } std::string PrioritizePieceOptionHandler::createPossibleValuesString() const { return "head[=SIZE], tail[=SIZE]"; } DeprecatedOptionHandler::DeprecatedOptionHandler (const SharedHandle& depOptHandler, const SharedHandle& repOptHandler) : depOptHandler_(depOptHandler), repOptHandler_(repOptHandler) {} void DeprecatedOptionHandler::parse(Option& option, const std::string& arg) { if(repOptHandler_) { A2_LOG_WARN(fmt(_("--%s option is deprecated. Use --%s option instead."), depOptHandler_->getName().c_str(), repOptHandler_->getName().c_str())); repOptHandler_->parse(option, arg); } else { A2_LOG_WARN(fmt(_("--%s option is deprecated."), depOptHandler_->getName().c_str())); } } std::string DeprecatedOptionHandler::createPossibleValuesString() const { return depOptHandler_->createPossibleValuesString(); } bool DeprecatedOptionHandler::hasTag(const std::string& tag) const { return depOptHandler_->hasTag(tag); } void DeprecatedOptionHandler::addTag(const std::string& tag) { depOptHandler_->addTag(tag); } std::string DeprecatedOptionHandler::toTagString() const { return depOptHandler_->toTagString(); } const std::string& DeprecatedOptionHandler::getName() const { return depOptHandler_->getName(); } const std::string& DeprecatedOptionHandler::getDescription() const { return depOptHandler_->getDescription(); } const std::string& DeprecatedOptionHandler::getDefaultValue() const { return depOptHandler_->getDefaultValue(); } bool DeprecatedOptionHandler::isHidden() const { return depOptHandler_->isHidden(); } void DeprecatedOptionHandler::hide() { depOptHandler_->hide(); } const Pref* DeprecatedOptionHandler::getPref() const { return depOptHandler_->getPref(); } OptionHandler::ARG_TYPE DeprecatedOptionHandler::getArgType() const { return depOptHandler_->getArgType(); } char DeprecatedOptionHandler::getShortName() const { return depOptHandler_->getShortName(); } bool DeprecatedOptionHandler::getEraseAfterParse() const { return depOptHandler_->getEraseAfterParse(); } void DeprecatedOptionHandler::setEraseAfterParse(bool eraseAfterParse) { depOptHandler_->setEraseAfterParse(eraseAfterParse); } bool DeprecatedOptionHandler::getInitialOption() const { return depOptHandler_->getInitialOption(); } void DeprecatedOptionHandler::setInitialOption(bool f) { depOptHandler_->setInitialOption(f); } bool DeprecatedOptionHandler::getChangeOption() const { return depOptHandler_->getChangeOption(); } void DeprecatedOptionHandler::setChangeOption(bool f) { depOptHandler_->setChangeOption(f); } bool DeprecatedOptionHandler::getChangeGlobalOption() const { return depOptHandler_->getChangeGlobalOption(); } void DeprecatedOptionHandler::setChangeGlobalOption(bool f) { depOptHandler_->setChangeGlobalOption(f); } bool DeprecatedOptionHandler::getCumulative() const { return depOptHandler_->getCumulative(); } void DeprecatedOptionHandler::setCumulative(bool f) { depOptHandler_->setCumulative(f); } } // namespace aria2