OptionHandlerImpl.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646
  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. #include "FileEntry.h"
  56. #include "a2io.h"
  57. namespace aria2 {
  58. class NullOptionHandler : public OptionHandler {
  59. private:
  60. int _id;
  61. public:
  62. virtual ~NullOptionHandler() {}
  63. virtual bool canHandle(const std::string& optName) { return true; }
  64. virtual void parse(Option& option, const std::string& arg) {}
  65. virtual bool hasTag(const std::string& tag) const { return false; }
  66. virtual void addTag(const std::string& tag) {}
  67. virtual std::string toTagString() const { return A2STR::NIL; }
  68. virtual const std::string& getName() const { return A2STR::NIL; }
  69. virtual const std::string& getDescription() const { return A2STR::NIL; }
  70. virtual const std::string& getDefaultValue() const { return A2STR::NIL; }
  71. virtual std::string createPossibleValuesString() const { return A2STR::NIL; }
  72. virtual bool isHidden() const { return true; }
  73. virtual void hide() {}
  74. virtual OptionHandler::ARG_TYPE getArgType() const
  75. {
  76. return OptionHandler::NO_ARG;
  77. }
  78. virtual int getOptionID() const
  79. {
  80. return _id;
  81. }
  82. virtual void setOptionID(int id)
  83. {
  84. _id = id;
  85. }
  86. virtual char getShortName() const
  87. {
  88. return 0;
  89. }
  90. };
  91. class BooleanOptionHandler : public NameMatchOptionHandler {
  92. public:
  93. BooleanOptionHandler(const std::string& optName,
  94. const std::string& description = NO_DESCRIPTION,
  95. const std::string& defaultValue = NO_DEFAULT_VALUE,
  96. OptionHandler::ARG_TYPE argType = OptionHandler::REQ_ARG,
  97. char shortName = 0):
  98. NameMatchOptionHandler(optName, description, defaultValue,
  99. argType, shortName) {}
  100. virtual ~BooleanOptionHandler() {}
  101. virtual void parseArg(Option& option, const std::string& optarg)
  102. {
  103. if(optarg == "true" ||
  104. ((_argType == OptionHandler::OPT_ARG ||
  105. _argType == OptionHandler::NO_ARG)
  106. && optarg.empty())) {
  107. option.put(_optName, V_TRUE);
  108. } else if(optarg == "false") {
  109. option.put(_optName, V_FALSE);
  110. } else {
  111. std::string msg = _optName;
  112. strappend(msg, " ", _("must be either 'true' or 'false'."));
  113. throw DL_ABORT_EX(msg);
  114. }
  115. }
  116. virtual std::string createPossibleValuesString() const
  117. {
  118. return "true,false";
  119. }
  120. };
  121. class IntegerRangeOptionHandler : public NameMatchOptionHandler {
  122. private:
  123. int32_t _min;
  124. int32_t _max;
  125. public:
  126. IntegerRangeOptionHandler(const std::string& optName,
  127. const std::string& description,
  128. const std::string& defaultValue,
  129. int32_t min, int32_t max,
  130. char shortName = 0):
  131. NameMatchOptionHandler(optName, description, defaultValue,
  132. OptionHandler::REQ_ARG, shortName),
  133. _min(min), _max(max) {}
  134. virtual ~IntegerRangeOptionHandler() {}
  135. virtual void parseArg(Option& option, const std::string& optarg)
  136. {
  137. IntSequence seq = util::parseIntRange(optarg);
  138. while(seq.hasNext()) {
  139. int32_t v = seq.next();
  140. if(v < _min || _max < v) {
  141. std::string msg = _optName;
  142. strappend(msg, " ", _("must be between %s and %s."));
  143. throw DL_ABORT_EX
  144. (StringFormat(msg.c_str(), util::itos(_min).c_str(),
  145. util::itos(_max).c_str()).str());
  146. }
  147. option.put(_optName, optarg);
  148. }
  149. }
  150. virtual std::string createPossibleValuesString() const
  151. {
  152. return util::itos(_min)+"-"+util::itos(_max);
  153. }
  154. };
  155. class NumberOptionHandler : public NameMatchOptionHandler {
  156. private:
  157. int64_t _min;
  158. int64_t _max;
  159. public:
  160. NumberOptionHandler(const std::string& optName,
  161. const std::string& description = NO_DESCRIPTION,
  162. const std::string& defaultValue = NO_DEFAULT_VALUE,
  163. int64_t min = -1,
  164. int64_t max = -1,
  165. char shortName = 0):
  166. NameMatchOptionHandler(optName, description, defaultValue,
  167. OptionHandler::REQ_ARG, shortName),
  168. _min(min), _max(max) {}
  169. virtual ~NumberOptionHandler() {}
  170. virtual void parseArg(Option& option, const std::string& optarg)
  171. {
  172. int64_t num = util::parseLLInt(optarg);
  173. parseArg(option, num);
  174. }
  175. void parseArg(Option& option, int64_t number)
  176. {
  177. if((_min == -1 || _min <= number) && (_max == -1 || number <= _max)) {
  178. option.put(_optName, util::itos(number));
  179. } else {
  180. std::string msg = _optName;
  181. msg += " ";
  182. if(_min == -1 && _max != -1) {
  183. msg += StringFormat(_("must be smaller than or equal to %s."),
  184. util::itos(_max).c_str()).str();
  185. } else if(_min != -1 && _max != -1) {
  186. msg += StringFormat(_("must be between %s and %s."),
  187. util::itos(_min).c_str(), util::itos(_max).c_str()).str();
  188. } else if(_min != -1 && _max == -1) {
  189. msg += StringFormat(_("must be greater than or equal to %s."),
  190. util::itos(_min).c_str()).str();
  191. } else {
  192. msg += _("must be a number.");
  193. }
  194. throw DL_ABORT_EX(msg);
  195. }
  196. }
  197. virtual std::string createPossibleValuesString() const
  198. {
  199. std::string values;
  200. if(_min == -1) {
  201. values += "*";
  202. } else {
  203. values += util::itos(_min);
  204. }
  205. values += "-";
  206. if(_max == -1) {
  207. values += "*";
  208. } else {
  209. values += util::itos(_max);
  210. }
  211. return values;
  212. }
  213. };
  214. class UnitNumberOptionHandler : public NumberOptionHandler {
  215. public:
  216. UnitNumberOptionHandler(const std::string& optName,
  217. const std::string& description = NO_DESCRIPTION,
  218. const std::string& defaultValue = NO_DEFAULT_VALUE,
  219. int64_t min = -1,
  220. int64_t max = -1,
  221. char shortName = 0):
  222. NumberOptionHandler(optName, description, defaultValue, min, max,
  223. shortName) {}
  224. virtual ~UnitNumberOptionHandler() {}
  225. virtual void parseArg(Option& option, const std::string& optarg)
  226. {
  227. int64_t num = util::getRealSize(optarg);
  228. NumberOptionHandler::parseArg(option, num);
  229. }
  230. };
  231. class FloatNumberOptionHandler : public NameMatchOptionHandler {
  232. private:
  233. double _min;
  234. double _max;
  235. public:
  236. FloatNumberOptionHandler(const std::string& optName,
  237. const std::string& description = NO_DESCRIPTION,
  238. const std::string& defaultValue = NO_DEFAULT_VALUE,
  239. double min = -1, double max = -1,
  240. char shortName = 0):
  241. NameMatchOptionHandler(optName, description, defaultValue,
  242. OptionHandler::REQ_ARG, shortName),
  243. _min(min), _max(max) {}
  244. virtual ~FloatNumberOptionHandler() {}
  245. virtual void parseArg(Option& option, const std::string& optarg)
  246. {
  247. double number = strtod(optarg.c_str(), 0);
  248. if((_min < 0 || _min <= number) && (_max < 0 || number <= _max)) {
  249. option.put(_optName, optarg);
  250. } else {
  251. std::string msg = _optName;
  252. msg += " ";
  253. if(_min < 0 && _max >= 0) {
  254. msg += StringFormat(_("must be smaller than or equal to %.1f."),
  255. _max).str();
  256. } else if(_min >= 0 && _max >= 0) {
  257. msg += StringFormat(_("must be between %.1f and %.1f."),
  258. _min, _max).str();
  259. } else if(_min >= 0 && _max < 0) {
  260. msg += StringFormat(_("must be greater than or equal to %.1f."),
  261. _min).str();
  262. } else {
  263. msg += _("must be a number.");
  264. }
  265. throw DL_ABORT_EX(msg);
  266. }
  267. }
  268. virtual std::string createPossibleValuesString() const
  269. {
  270. std::string valuesString;
  271. if(_min < 0) {
  272. valuesString += "*";
  273. } else {
  274. char buf[11];
  275. snprintf(buf, sizeof(buf), "%.1f", _min);
  276. valuesString += buf;
  277. }
  278. valuesString += "-";
  279. if(_max < 0) {
  280. valuesString += "*";
  281. } else {
  282. char buf[11];
  283. snprintf(buf, sizeof(buf), "%.1f", _max);
  284. valuesString += buf;
  285. }
  286. return valuesString;
  287. }
  288. };
  289. class DefaultOptionHandler : public NameMatchOptionHandler {
  290. private:
  291. std::string _possibleValuesString;
  292. public:
  293. DefaultOptionHandler(const std::string& optName,
  294. const std::string& description = NO_DESCRIPTION,
  295. const std::string& defaultValue = NO_DEFAULT_VALUE,
  296. const std::string& possibleValuesString = A2STR::NIL,
  297. OptionHandler::ARG_TYPE argType = OptionHandler::REQ_ARG,
  298. char shortName = 0):
  299. NameMatchOptionHandler(optName, description, defaultValue, argType,
  300. shortName),
  301. _possibleValuesString(possibleValuesString) {}
  302. virtual ~DefaultOptionHandler() {}
  303. virtual void parseArg(Option& option, const std::string& optarg)
  304. {
  305. option.put(_optName, optarg);
  306. }
  307. virtual std::string createPossibleValuesString() const
  308. {
  309. return _possibleValuesString;
  310. }
  311. };
  312. class CumulativeOptionHandler : public NameMatchOptionHandler {
  313. private:
  314. std::string _delim;
  315. std::string _possibleValuesString;
  316. public:
  317. CumulativeOptionHandler(const std::string& optName,
  318. const std::string& description,
  319. const std::string& defaultValue,
  320. const std::string& delim,
  321. const std::string& possibleValuesString = A2STR::NIL,
  322. OptionHandler::ARG_TYPE argType =
  323. OptionHandler::REQ_ARG,
  324. char shortName = 0):
  325. NameMatchOptionHandler(optName, description, defaultValue, argType,
  326. shortName),
  327. _delim(delim),
  328. _possibleValuesString(possibleValuesString) {}
  329. virtual ~CumulativeOptionHandler() {}
  330. virtual void parseArg(Option& option, const std::string& optarg)
  331. {
  332. std::string value = option.get(_optName);
  333. strappend(value, optarg, _delim);
  334. option.put(_optName, value);
  335. }
  336. virtual std::string createPossibleValuesString() const
  337. {
  338. return _possibleValuesString;
  339. }
  340. };
  341. class IndexOutOptionHandler : public NameMatchOptionHandler {
  342. private:
  343. public:
  344. IndexOutOptionHandler(const std::string& optName,
  345. const std::string& description,
  346. char shortName = 0):
  347. NameMatchOptionHandler(optName, description, NO_DEFAULT_VALUE,
  348. OptionHandler::REQ_ARG, shortName) {}
  349. virtual ~IndexOutOptionHandler() {}
  350. virtual void parseArg(Option& option, const std::string& optarg)
  351. {
  352. // See optarg is in the fomrat of "INDEX=PATH"
  353. util::parseIndexPath(optarg);
  354. std::string value = option.get(_optName);
  355. strappend(value, optarg, "\n");
  356. option.put(_optName, value);
  357. }
  358. virtual std::string createPossibleValuesString() const
  359. {
  360. return "INDEX=PATH";
  361. }
  362. };
  363. class ParameterOptionHandler : public NameMatchOptionHandler {
  364. private:
  365. std::deque<std::string> _validParamValues;
  366. public:
  367. ParameterOptionHandler(const std::string& optName,
  368. const std::string& description,
  369. const std::string& defaultValue,
  370. const std::deque<std::string>& validParamValues,
  371. char shortName = 0):
  372. NameMatchOptionHandler(optName, description, defaultValue,
  373. OptionHandler::REQ_ARG, shortName),
  374. _validParamValues(validParamValues) {}
  375. ParameterOptionHandler(const std::string& optName,
  376. const std::string& description,
  377. const std::string& defaultValue,
  378. const std::string& validParamValue,
  379. char shortName = 0):
  380. NameMatchOptionHandler(optName, description, defaultValue,
  381. OptionHandler::REQ_ARG, shortName)
  382. {
  383. _validParamValues.push_back(validParamValue);
  384. }
  385. ParameterOptionHandler(const std::string& optName,
  386. const std::string& description,
  387. const std::string& defaultValue,
  388. const std::string& validParamValue1,
  389. const std::string& validParamValue2,
  390. char shortName = 0):
  391. NameMatchOptionHandler(optName, description, defaultValue,
  392. OptionHandler::REQ_ARG, shortName)
  393. {
  394. _validParamValues.push_back(validParamValue1);
  395. _validParamValues.push_back(validParamValue2);
  396. }
  397. ParameterOptionHandler(const std::string& optName,
  398. const std::string& description,
  399. const std::string& defaultValue,
  400. const std::string& validParamValue1,
  401. const std::string& validParamValue2,
  402. const std::string& validParamValue3,
  403. char shortName = 0):
  404. NameMatchOptionHandler(optName, description, defaultValue,
  405. OptionHandler::REQ_ARG, shortName)
  406. {
  407. _validParamValues.push_back(validParamValue1);
  408. _validParamValues.push_back(validParamValue2);
  409. _validParamValues.push_back(validParamValue3);
  410. }
  411. virtual ~ParameterOptionHandler() {}
  412. virtual void parseArg(Option& option, const std::string& optarg)
  413. {
  414. std::deque<std::string>::const_iterator itr =
  415. std::find(_validParamValues.begin(), _validParamValues.end(), optarg);
  416. if(itr == _validParamValues.end()) {
  417. std::string msg = _optName;
  418. strappend(msg, " ", _("must be one of the following:"));
  419. if(_validParamValues.size() == 0) {
  420. msg += "''";
  421. } else {
  422. for(std::deque<std::string>::const_iterator itr = _validParamValues.begin();
  423. itr != _validParamValues.end(); ++itr) {
  424. strappend(msg, "'", *itr, "' ");
  425. }
  426. }
  427. throw DL_ABORT_EX(msg);
  428. } else {
  429. option.put(_optName, optarg);
  430. }
  431. }
  432. virtual std::string createPossibleValuesString() const
  433. {
  434. std::stringstream s;
  435. std::copy(_validParamValues.begin(), _validParamValues.end(),
  436. std::ostream_iterator<std::string>(s, ","));
  437. return util::trim(s.str(), ", ");
  438. }
  439. };
  440. class HostPortOptionHandler : public NameMatchOptionHandler {
  441. private:
  442. std::string _hostOptionName;
  443. std::string _portOptionName;
  444. public:
  445. HostPortOptionHandler(const std::string& optName,
  446. const std::string& description,
  447. const std::string& defaultValue,
  448. const std::string& hostOptionName,
  449. const std::string& portOptionName,
  450. char shortName = 0):
  451. NameMatchOptionHandler(optName, description, defaultValue,
  452. OptionHandler::REQ_ARG, shortName),
  453. _hostOptionName(hostOptionName),
  454. _portOptionName(portOptionName) {}
  455. virtual ~HostPortOptionHandler() {}
  456. virtual void parseArg(Option& option, const std::string& optarg)
  457. {
  458. std::pair<std::string, std::string> proxy = util::split(optarg, ":");
  459. int32_t port = util::parseInt(proxy.second);
  460. if(proxy.first.empty() || proxy.second.empty() ||
  461. port <= 0 || 65535 < port) {
  462. throw DL_ABORT_EX(_("unrecognized proxy format"));
  463. }
  464. option.put(_optName, optarg);
  465. setHostAndPort(option, proxy.first, port);
  466. }
  467. void setHostAndPort(Option& option, const std::string& hostname, uint16_t port)
  468. {
  469. option.put(_hostOptionName, hostname);
  470. option.put(_portOptionName, util::uitos(port));
  471. }
  472. virtual std::string createPossibleValuesString() const
  473. {
  474. return "HOST:PORT";
  475. }
  476. };
  477. class HttpProxyOptionHandler : public NameMatchOptionHandler {
  478. public:
  479. HttpProxyOptionHandler(const std::string& optName,
  480. const std::string& description,
  481. const std::string& defaultValue,
  482. char shortName = 0)
  483. :
  484. NameMatchOptionHandler(optName, description, defaultValue,
  485. OptionHandler::REQ_ARG, shortName)
  486. {}
  487. virtual ~HttpProxyOptionHandler() {}
  488. virtual void parseArg(Option& option, const std::string& optarg)
  489. {
  490. if(optarg.empty()) {
  491. option.put(_optName, optarg);
  492. } else {
  493. Request req;
  494. std::string url;
  495. if(util::startsWith(optarg, "http://")) {
  496. url = optarg;
  497. } else {
  498. url = "http://"+optarg;
  499. }
  500. if(req.setUrl(url)) {
  501. option.put(_optName, url);
  502. } else {
  503. throw DL_ABORT_EX(_("unrecognized proxy format"));
  504. }
  505. }
  506. }
  507. virtual std::string createPossibleValuesString() const
  508. {
  509. return "[http://][USER:PASSWORD@]HOST[:PORT]";
  510. }
  511. };
  512. class LocalFilePathOptionHandler : public NameMatchOptionHandler {
  513. private:
  514. bool _acceptStdin;
  515. public:
  516. LocalFilePathOptionHandler
  517. (const std::string& optName,
  518. const std::string& description = NO_DESCRIPTION,
  519. const std::string& defaultValue = NO_DEFAULT_VALUE,
  520. bool acceptStdin = false,
  521. char shortName = 0):
  522. NameMatchOptionHandler(optName, description, defaultValue,
  523. OptionHandler::REQ_ARG,
  524. shortName),
  525. _acceptStdin(acceptStdin) {}
  526. virtual void parseArg(Option& option, const std::string& optarg)
  527. {
  528. if(_acceptStdin && optarg == "-") {
  529. option.put(_optName, DEV_STDIN);
  530. } else {
  531. File f(optarg);
  532. if(!f.exists() || f.isDir()) {
  533. throw DL_ABORT_EX
  534. (StringFormat(MSG_NOT_FILE, optarg.c_str()).str());
  535. }
  536. option.put(_optName, optarg);
  537. }
  538. }
  539. virtual std::string createPossibleValuesString() const
  540. {
  541. return "/path/to/file";
  542. }
  543. };
  544. class PrioritizePieceOptionHandler:public NameMatchOptionHandler {
  545. public:
  546. PrioritizePieceOptionHandler
  547. (const std::string& optName,
  548. const std::string& description = NO_DESCRIPTION,
  549. const std::string& defaultValue = NO_DEFAULT_VALUE,
  550. char shortName = 0):
  551. NameMatchOptionHandler(optName, description, defaultValue,
  552. OptionHandler::REQ_ARG, shortName) {}
  553. virtual void parseArg(Option& option, const std::string& optarg)
  554. {
  555. // Parse optarg against empty FileEntry list to detect syntax
  556. // error.
  557. std::vector<size_t> result;
  558. util::parsePrioritizePieceRange
  559. (result, optarg, std::vector<SharedHandle<FileEntry> >(), 1024);
  560. option.put(_optName, optarg);
  561. }
  562. virtual std::string createPossibleValuesString() const
  563. {
  564. return "head[=SIZE],tail[=SIZE]";
  565. }
  566. };
  567. } // namespace aria2
  568. #endif // _D_OPTION_HANDLER_IMPL_H_