OptionHandlerImpl.h 20 KB

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