OptionHandlerImpl.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  1. /* <!-- copyright */
  2. /*
  3. * aria2 - The high speed download utility
  4. *
  5. * Copyright (C) 2006 Tatsuhiro Tsujikawa
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. * In addition, as a special exception, the copyright holders give
  22. * permission to link the code of portions of this program with the
  23. * OpenSSL library under certain conditions as described in each
  24. * individual source file, and distribute linked combinations
  25. * including the two.
  26. * You must obey the GNU General Public License in all respects
  27. * for all of the code used other than OpenSSL. If you modify
  28. * file(s) with this exception, you may extend this exception to your
  29. * version of the file(s), but you are not obligated to do so. If you
  30. * do not wish to do so, delete this exception statement from your
  31. * version. If you delete this exception statement from all source
  32. * files in the program, then also delete it here.
  33. */
  34. /* copyright --> */
  35. #ifndef _D_OPTION_HANDLER_IMPL_H_
  36. #define _D_OPTION_HANDLER_IMPL_H_
  37. #include "OptionHandler.h"
  38. #include <cstdio>
  39. #include <utility>
  40. #include <algorithm>
  41. #include <numeric>
  42. #include <sstream>
  43. #include <iterator>
  44. #include "NameMatchOptionHandler.h"
  45. #include "Util.h"
  46. #include "DlAbortEx.h"
  47. #include "prefs.h"
  48. #include "Option.h"
  49. #include "StringFormat.h"
  50. #include "A2STR.h"
  51. #include "Request.h"
  52. #include "a2functional.h"
  53. #include "message.h"
  54. #include "File.h"
  55. namespace aria2 {
  56. class NullOptionHandler : public OptionHandler {
  57. private:
  58. int _id;
  59. public:
  60. virtual ~NullOptionHandler() {}
  61. virtual bool canHandle(const std::string& optName) { return true; }
  62. virtual void parse(Option& option, const std::string& arg) {}
  63. virtual bool hasTag(const std::string& tag) const { return false; }
  64. virtual void addTag(const std::string& tag) {}
  65. virtual std::string toTagString() const { return A2STR::NIL; }
  66. virtual const std::string& getName() const { return A2STR::NIL; }
  67. virtual const std::string& getDescription() const { return A2STR::NIL; }
  68. virtual const std::string& getDefaultValue() const { return A2STR::NIL; }
  69. virtual std::string createPossibleValuesString() const { return A2STR::NIL; }
  70. virtual bool isHidden() const { return true; }
  71. virtual void hide() {}
  72. virtual OptionHandler::ARG_TYPE getArgType() const
  73. {
  74. return OptionHandler::NO_ARG;
  75. }
  76. virtual int getOptionID() const
  77. {
  78. return _id;
  79. }
  80. virtual void setOptionID(int id)
  81. {
  82. _id = id;
  83. }
  84. virtual char getShortName() const
  85. {
  86. return 0;
  87. }
  88. };
  89. class BooleanOptionHandler : public NameMatchOptionHandler {
  90. public:
  91. BooleanOptionHandler(const std::string& optName,
  92. const std::string& description = NO_DESCRIPTION,
  93. const std::string& defaultValue = NO_DEFAULT_VALUE,
  94. OptionHandler::ARG_TYPE argType = OptionHandler::REQ_ARG,
  95. char shortName = 0):
  96. NameMatchOptionHandler(optName, description, defaultValue,
  97. argType, shortName) {}
  98. virtual ~BooleanOptionHandler() {}
  99. virtual void parseArg(Option& option, const std::string& optarg)
  100. {
  101. if(optarg == "true" ||
  102. ((_argType == OptionHandler::OPT_ARG ||
  103. _argType == OptionHandler::NO_ARG)
  104. && optarg.empty())) {
  105. option.put(_optName, V_TRUE);
  106. } else if(optarg == "false") {
  107. option.put(_optName, V_FALSE);
  108. } else {
  109. std::string msg = _optName;
  110. strappend(msg, " ", _("must be either 'true' or 'false'."));
  111. throw DL_ABORT_EX(msg);
  112. }
  113. }
  114. virtual std::string createPossibleValuesString() const
  115. {
  116. return "true,false";
  117. }
  118. };
  119. class IntegerRangeOptionHandler : public NameMatchOptionHandler {
  120. private:
  121. int32_t _min;
  122. int32_t _max;
  123. public:
  124. IntegerRangeOptionHandler(const std::string& optName,
  125. const std::string& description,
  126. const std::string& defaultValue,
  127. int32_t min, int32_t max,
  128. char shortName = 0):
  129. NameMatchOptionHandler(optName, description, defaultValue,
  130. OptionHandler::REQ_ARG, shortName),
  131. _min(min), _max(max) {}
  132. virtual ~IntegerRangeOptionHandler() {}
  133. virtual void parseArg(Option& option, const std::string& optarg)
  134. {
  135. IntSequence seq = util::parseIntRange(optarg);
  136. while(seq.hasNext()) {
  137. int32_t v = seq.next();
  138. if(v < _min || _max < v) {
  139. std::string msg = _optName;
  140. strappend(msg, " ", _("must be between %s and %s."));
  141. throw DL_ABORT_EX
  142. (StringFormat(msg.c_str(), util::itos(_min).c_str(),
  143. util::itos(_max).c_str()).str());
  144. }
  145. option.put(_optName, optarg);
  146. }
  147. }
  148. virtual std::string createPossibleValuesString() const
  149. {
  150. return util::itos(_min)+"-"+util::itos(_max);
  151. }
  152. };
  153. class NumberOptionHandler : public NameMatchOptionHandler {
  154. private:
  155. int64_t _min;
  156. int64_t _max;
  157. public:
  158. NumberOptionHandler(const std::string& optName,
  159. const std::string& description = NO_DESCRIPTION,
  160. const std::string& defaultValue = NO_DEFAULT_VALUE,
  161. int64_t min = -1,
  162. int64_t max = -1,
  163. char shortName = 0):
  164. NameMatchOptionHandler(optName, description, defaultValue,
  165. OptionHandler::REQ_ARG, shortName),
  166. _min(min), _max(max) {}
  167. virtual ~NumberOptionHandler() {}
  168. virtual void parseArg(Option& option, const std::string& optarg)
  169. {
  170. int64_t num = util::parseLLInt(optarg);
  171. parseArg(option, num);
  172. }
  173. void parseArg(Option& option, int64_t number)
  174. {
  175. if((_min == -1 || _min <= number) && (_max == -1 || number <= _max)) {
  176. option.put(_optName, util::itos(number));
  177. } else {
  178. std::string msg = _optName;
  179. msg += " ";
  180. if(_min == -1 && _max != -1) {
  181. msg += StringFormat(_("must be smaller than or equal to %s."),
  182. util::itos(_max).c_str()).str();
  183. } else if(_min != -1 && _max != -1) {
  184. msg += StringFormat(_("must be between %s and %s."),
  185. util::itos(_min).c_str(), util::itos(_max).c_str()).str();
  186. } else if(_min != -1 && _max == -1) {
  187. msg += StringFormat(_("must be greater than or equal to %s."),
  188. util::itos(_min).c_str()).str();
  189. } else {
  190. msg += _("must be a number.");
  191. }
  192. throw DL_ABORT_EX(msg);
  193. }
  194. }
  195. virtual std::string createPossibleValuesString() const
  196. {
  197. std::string values;
  198. if(_min == -1) {
  199. values += "*";
  200. } else {
  201. values += util::itos(_min);
  202. }
  203. values += "-";
  204. if(_max == -1) {
  205. values += "*";
  206. } else {
  207. values += util::itos(_max);
  208. }
  209. return values;
  210. }
  211. };
  212. class UnitNumberOptionHandler : public NumberOptionHandler {
  213. public:
  214. UnitNumberOptionHandler(const std::string& optName,
  215. const std::string& description = NO_DESCRIPTION,
  216. const std::string& defaultValue = NO_DEFAULT_VALUE,
  217. int64_t min = -1,
  218. int64_t max = -1,
  219. char shortName = 0):
  220. NumberOptionHandler(optName, description, defaultValue, min, max,
  221. shortName) {}
  222. virtual ~UnitNumberOptionHandler() {}
  223. virtual void parseArg(Option& option, const std::string& optarg)
  224. {
  225. int64_t num = util::getRealSize(optarg);
  226. NumberOptionHandler::parseArg(option, num);
  227. }
  228. };
  229. class FloatNumberOptionHandler : public NameMatchOptionHandler {
  230. private:
  231. double _min;
  232. double _max;
  233. public:
  234. FloatNumberOptionHandler(const std::string& optName,
  235. const std::string& description = NO_DESCRIPTION,
  236. const std::string& defaultValue = NO_DEFAULT_VALUE,
  237. double min = -1, double max = -1,
  238. char shortName = 0):
  239. NameMatchOptionHandler(optName, description, defaultValue,
  240. OptionHandler::REQ_ARG, shortName),
  241. _min(min), _max(max) {}
  242. virtual ~FloatNumberOptionHandler() {}
  243. virtual void parseArg(Option& option, const std::string& optarg)
  244. {
  245. double number = strtod(optarg.c_str(), 0);
  246. if((_min < 0 || _min <= number) && (_max < 0 || number <= _max)) {
  247. option.put(_optName, optarg);
  248. } else {
  249. std::string msg = _optName;
  250. msg += " ";
  251. if(_min < 0 && _max >= 0) {
  252. msg += StringFormat(_("must be smaller than or equal to %.1f."),
  253. _max).str();
  254. } else if(_min >= 0 && _max >= 0) {
  255. msg += StringFormat(_("must be between %.1f and %.1f."),
  256. _min, _max).str();
  257. } else if(_min >= 0 && _max < 0) {
  258. msg += StringFormat(_("must be greater than or equal to %.1f."),
  259. _min).str();
  260. } else {
  261. msg += _("must be a number.");
  262. }
  263. throw DL_ABORT_EX(msg);
  264. }
  265. }
  266. virtual std::string createPossibleValuesString() const
  267. {
  268. std::string valuesString;
  269. if(_min < 0) {
  270. valuesString += "*";
  271. } else {
  272. char buf[11];
  273. snprintf(buf, sizeof(buf), "%.1f", _min);
  274. valuesString += buf;
  275. }
  276. valuesString += "-";
  277. if(_max < 0) {
  278. valuesString += "*";
  279. } else {
  280. char buf[11];
  281. snprintf(buf, sizeof(buf), "%.1f", _max);
  282. valuesString += buf;
  283. }
  284. return valuesString;
  285. }
  286. };
  287. class DefaultOptionHandler : public NameMatchOptionHandler {
  288. private:
  289. std::string _possibleValuesString;
  290. public:
  291. DefaultOptionHandler(const std::string& optName,
  292. const std::string& description = NO_DESCRIPTION,
  293. const std::string& defaultValue = NO_DEFAULT_VALUE,
  294. const std::string& possibleValuesString = A2STR::NIL,
  295. OptionHandler::ARG_TYPE argType = OptionHandler::REQ_ARG,
  296. char shortName = 0):
  297. NameMatchOptionHandler(optName, description, defaultValue, argType,
  298. shortName),
  299. _possibleValuesString(possibleValuesString) {}
  300. virtual ~DefaultOptionHandler() {}
  301. virtual void parseArg(Option& option, const std::string& optarg)
  302. {
  303. option.put(_optName, optarg);
  304. }
  305. virtual std::string createPossibleValuesString() const
  306. {
  307. return _possibleValuesString;
  308. }
  309. };
  310. class CumulativeOptionHandler : public NameMatchOptionHandler {
  311. private:
  312. std::string _delim;
  313. std::string _possibleValuesString;
  314. public:
  315. CumulativeOptionHandler(const std::string& optName,
  316. const std::string& description,
  317. const std::string& defaultValue,
  318. const std::string& delim,
  319. const std::string& possibleValuesString = A2STR::NIL,
  320. OptionHandler::ARG_TYPE argType =
  321. OptionHandler::REQ_ARG,
  322. char shortName = 0):
  323. NameMatchOptionHandler(optName, description, defaultValue, argType,
  324. shortName),
  325. _delim(delim),
  326. _possibleValuesString(possibleValuesString) {}
  327. virtual ~CumulativeOptionHandler() {}
  328. virtual void parseArg(Option& option, const std::string& optarg)
  329. {
  330. std::string value = option.get(_optName);
  331. strappend(value, optarg, _delim);
  332. option.put(_optName, value);
  333. }
  334. virtual std::string createPossibleValuesString() const
  335. {
  336. return _possibleValuesString;
  337. }
  338. };
  339. class IndexOutOptionHandler : public NameMatchOptionHandler {
  340. private:
  341. public:
  342. IndexOutOptionHandler(const std::string& optName,
  343. const std::string& description,
  344. char shortName = 0):
  345. NameMatchOptionHandler(optName, description, NO_DEFAULT_VALUE,
  346. OptionHandler::REQ_ARG, shortName) {}
  347. virtual ~IndexOutOptionHandler() {}
  348. virtual void parseArg(Option& option, const std::string& optarg)
  349. {
  350. // See optarg is in the fomrat of "INDEX=PATH"
  351. util::parseIndexPath(optarg);
  352. std::string value = option.get(_optName);
  353. strappend(value, optarg, "\n");
  354. option.put(_optName, value);
  355. }
  356. virtual std::string createPossibleValuesString() const
  357. {
  358. return "INDEX=PATH";
  359. }
  360. };
  361. class ParameterOptionHandler : public NameMatchOptionHandler {
  362. private:
  363. std::deque<std::string> _validParamValues;
  364. public:
  365. ParameterOptionHandler(const std::string& optName,
  366. const std::string& description,
  367. const std::string& defaultValue,
  368. const std::deque<std::string>& validParamValues,
  369. char shortName = 0):
  370. NameMatchOptionHandler(optName, description, defaultValue,
  371. OptionHandler::REQ_ARG, shortName),
  372. _validParamValues(validParamValues) {}
  373. ParameterOptionHandler(const std::string& optName,
  374. const std::string& description,
  375. const std::string& defaultValue,
  376. const std::string& validParamValue,
  377. char shortName = 0):
  378. NameMatchOptionHandler(optName, description, defaultValue,
  379. OptionHandler::REQ_ARG, shortName)
  380. {
  381. _validParamValues.push_back(validParamValue);
  382. }
  383. ParameterOptionHandler(const std::string& optName,
  384. const std::string& description,
  385. const std::string& defaultValue,
  386. const std::string& validParamValue1,
  387. const std::string& validParamValue2,
  388. char shortName = 0):
  389. NameMatchOptionHandler(optName, description, defaultValue,
  390. OptionHandler::REQ_ARG, shortName)
  391. {
  392. _validParamValues.push_back(validParamValue1);
  393. _validParamValues.push_back(validParamValue2);
  394. }
  395. ParameterOptionHandler(const std::string& optName,
  396. const std::string& description,
  397. const std::string& defaultValue,
  398. const std::string& validParamValue1,
  399. const std::string& validParamValue2,
  400. const std::string& validParamValue3,
  401. char shortName = 0):
  402. NameMatchOptionHandler(optName, description, defaultValue,
  403. OptionHandler::REQ_ARG, shortName)
  404. {
  405. _validParamValues.push_back(validParamValue1);
  406. _validParamValues.push_back(validParamValue2);
  407. _validParamValues.push_back(validParamValue3);
  408. }
  409. virtual ~ParameterOptionHandler() {}
  410. virtual void parseArg(Option& option, const std::string& optarg)
  411. {
  412. std::deque<std::string>::const_iterator itr =
  413. std::find(_validParamValues.begin(), _validParamValues.end(), optarg);
  414. if(itr == _validParamValues.end()) {
  415. std::string msg = _optName;
  416. strappend(msg, " ", _("must be one of the following:"));
  417. if(_validParamValues.size() == 0) {
  418. msg += "''";
  419. } else {
  420. for(std::deque<std::string>::const_iterator itr = _validParamValues.begin();
  421. itr != _validParamValues.end(); ++itr) {
  422. strappend(msg, "'", *itr, "' ");
  423. }
  424. }
  425. throw DL_ABORT_EX(msg);
  426. } else {
  427. option.put(_optName, optarg);
  428. }
  429. }
  430. virtual std::string createPossibleValuesString() const
  431. {
  432. std::stringstream s;
  433. std::copy(_validParamValues.begin(), _validParamValues.end(),
  434. std::ostream_iterator<std::string>(s, ","));
  435. return util::trim(s.str(), ", ");
  436. }
  437. };
  438. class HostPortOptionHandler : public NameMatchOptionHandler {
  439. private:
  440. std::string _hostOptionName;
  441. std::string _portOptionName;
  442. public:
  443. HostPortOptionHandler(const std::string& optName,
  444. const std::string& description,
  445. const std::string& defaultValue,
  446. const std::string& hostOptionName,
  447. const std::string& portOptionName,
  448. char shortName = 0):
  449. NameMatchOptionHandler(optName, description, defaultValue,
  450. OptionHandler::REQ_ARG, shortName),
  451. _hostOptionName(hostOptionName),
  452. _portOptionName(portOptionName) {}
  453. virtual ~HostPortOptionHandler() {}
  454. virtual void parseArg(Option& option, const std::string& optarg)
  455. {
  456. std::pair<std::string, std::string> proxy = util::split(optarg, ":");
  457. int32_t port = util::parseInt(proxy.second);
  458. if(proxy.first.empty() || proxy.second.empty() ||
  459. port <= 0 || 65535 < port) {
  460. throw DL_ABORT_EX(_("unrecognized proxy format"));
  461. }
  462. option.put(_optName, optarg);
  463. setHostAndPort(option, proxy.first, port);
  464. }
  465. void setHostAndPort(Option& option, const std::string& hostname, uint16_t port)
  466. {
  467. option.put(_hostOptionName, hostname);
  468. option.put(_portOptionName, util::uitos(port));
  469. }
  470. virtual std::string createPossibleValuesString() const
  471. {
  472. return "HOST:PORT";
  473. }
  474. };
  475. class HttpProxyOptionHandler : public NameMatchOptionHandler {
  476. public:
  477. HttpProxyOptionHandler(const std::string& optName,
  478. const std::string& description,
  479. const std::string& defaultValue,
  480. char shortName = 0)
  481. :
  482. NameMatchOptionHandler(optName, description, defaultValue,
  483. OptionHandler::REQ_ARG, shortName)
  484. {}
  485. virtual ~HttpProxyOptionHandler() {}
  486. virtual void parseArg(Option& option, const std::string& optarg)
  487. {
  488. Request req;
  489. std::string url;
  490. if(util::startsWith(optarg, "http://")) {
  491. url = optarg;
  492. } else {
  493. url = "http://"+optarg;
  494. }
  495. if(req.setUrl(url)) {
  496. option.put(_optName, url);
  497. } else {
  498. throw DL_ABORT_EX(_("unrecognized proxy format"));
  499. }
  500. }
  501. virtual std::string createPossibleValuesString() const
  502. {
  503. return "[http://][USER:PASSWORD@]HOST[:PORT]";
  504. }
  505. };
  506. class LocalFilePathOptionHandler : public NameMatchOptionHandler {
  507. public:
  508. LocalFilePathOptionHandler
  509. (const std::string& optName,
  510. const std::string& description = NO_DESCRIPTION,
  511. const std::string& defaultValue = NO_DEFAULT_VALUE,
  512. char shortName = 0):
  513. NameMatchOptionHandler(optName, description, defaultValue,
  514. OptionHandler::REQ_ARG,
  515. shortName) {}
  516. virtual void parseArg(Option& option, const std::string& optarg)
  517. {
  518. File f(optarg);
  519. if(!f.exists() || f.isDir()) {
  520. throw DL_ABORT_EX
  521. (StringFormat(MSG_NOT_FILE, optarg.c_str()).str());
  522. }
  523. option.put(_optName, optarg);
  524. }
  525. virtual std::string createPossibleValuesString() const
  526. {
  527. return "/path/to/file";
  528. }
  529. };
  530. } // namespace aria2
  531. #endif // _D_OPTION_HANDLER_IMPL_H_