1 /* <!-- copyright */
2 /*
3  * aria2 - The high speed download utility
4  *
5  * Copyright (C) 2010 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 #include "OptionHandlerImpl.h"
36 
37 #include <cassert>
38 #include <cstdio>
39 #include <cstring>
40 #include <utility>
41 #include <algorithm>
42 #include <numeric>
43 #include <sstream>
44 #include <iterator>
45 #include <vector>
46 #include <stdexcept>
47 
48 #include "util.h"
49 #include "DlAbortEx.h"
50 #include "prefs.h"
51 #include "Option.h"
52 #include "fmt.h"
53 #include "A2STR.h"
54 #include "Request.h"
55 #include "a2functional.h"
56 #include "message.h"
57 #include "File.h"
58 #include "FileEntry.h"
59 #include "a2io.h"
60 #include "LogFactory.h"
61 #include "uri.h"
62 #include "SegList.h"
63 #include "array_fun.h"
64 #include "help_tags.h"
65 #include "MessageDigest.h"
66 
67 namespace aria2 {
68 
BooleanOptionHandler(PrefPtr pref,const char * description,const std::string & defaultValue,OptionHandler::ARG_TYPE argType,char shortName)69 BooleanOptionHandler::BooleanOptionHandler(PrefPtr pref,
70                                            const char* description,
71                                            const std::string& defaultValue,
72                                            OptionHandler::ARG_TYPE argType,
73                                            char shortName)
74     : AbstractOptionHandler(pref, description, defaultValue, argType, shortName)
75 {
76 }
77 
78 BooleanOptionHandler::~BooleanOptionHandler() = default;
79 
parseArg(Option & option,const std::string & optarg) const80 void BooleanOptionHandler::parseArg(Option& option,
81                                     const std::string& optarg) const
82 {
83   if (optarg == "true" || ((argType_ == OptionHandler::OPT_ARG ||
84                             argType_ == OptionHandler::NO_ARG) &&
85                            optarg.empty())) {
86     option.put(pref_, A2_V_TRUE);
87   }
88   else if (optarg == "false") {
89     option.put(pref_, A2_V_FALSE);
90   }
91   else {
92     std::string msg = pref_->k;
93     msg += " ";
94     msg += _("must be either 'true' or 'false'.");
95     throw DL_ABORT_EX(msg);
96   }
97 }
98 
createPossibleValuesString() const99 std::string BooleanOptionHandler::createPossibleValuesString() const
100 {
101   return "true, false";
102 }
103 
IntegerRangeOptionHandler(PrefPtr pref,const char * description,const std::string & defaultValue,int32_t min,int32_t max,char shortName)104 IntegerRangeOptionHandler::IntegerRangeOptionHandler(
105     PrefPtr pref, const char* description, const std::string& defaultValue,
106     int32_t min, int32_t max, char shortName)
107     : AbstractOptionHandler(pref, description, defaultValue,
108                             OptionHandler::REQ_ARG, shortName),
109       min_(min),
110       max_(max)
111 {
112 }
113 
114 IntegerRangeOptionHandler::~IntegerRangeOptionHandler() = default;
115 
parseArg(Option & option,const std::string & optarg) const116 void IntegerRangeOptionHandler::parseArg(Option& option,
117                                          const std::string& optarg) const
118 {
119   auto sgl = util::parseIntSegments(optarg);
120   sgl.normalize();
121   while (sgl.hasNext()) {
122     int v = sgl.next();
123     if (v < min_ || max_ < v) {
124       std::string msg = pref_->k;
125       msg += " ";
126       msg += _("must be between %d and %d.");
127       throw DL_ABORT_EX(fmt(msg.c_str(), min_, max_));
128     }
129     option.put(pref_, optarg);
130   }
131 }
132 
createPossibleValuesString() const133 std::string IntegerRangeOptionHandler::createPossibleValuesString() const
134 {
135   return fmt("%d-%d", min_, max_);
136 }
137 
NumberOptionHandler(PrefPtr pref,const char * description,const std::string & defaultValue,int64_t min,int64_t max,char shortName)138 NumberOptionHandler::NumberOptionHandler(PrefPtr pref, const char* description,
139                                          const std::string& defaultValue,
140                                          int64_t min, int64_t max,
141                                          char shortName)
142     : AbstractOptionHandler(pref, description, defaultValue,
143                             OptionHandler::REQ_ARG, shortName),
144       min_(min),
145       max_(max)
146 {
147 }
148 
149 NumberOptionHandler::~NumberOptionHandler() = default;
150 
parseArg(Option & option,const std::string & optarg) const151 void NumberOptionHandler::parseArg(Option& option,
152                                    const std::string& optarg) const
153 {
154   int64_t number;
155   if (util::parseLLIntNoThrow(number, optarg)) {
156     parseArg(option, number);
157   }
158   else {
159     throw DL_ABORT_EX(fmt("Bad number %s", optarg.c_str()));
160   }
161 }
162 
parseArg(Option & option,int64_t number) const163 void NumberOptionHandler::parseArg(Option& option, int64_t number) const
164 {
165   if ((min_ == -1 || min_ <= number) && (max_ == -1 || number <= max_)) {
166     option.put(pref_, util::itos(number));
167     return;
168   }
169 
170   std::string msg = pref_->k;
171   msg += " ";
172   if (min_ == -1 && max_ != -1) {
173     msg += fmt(_("must be smaller than or equal to %" PRId64 "."), max_);
174   }
175   else if (min_ != -1 && max_ != -1) {
176     msg += fmt(_("must be between %" PRId64 " and %" PRId64 "."), min_, max_);
177   }
178   else if (min_ != -1 && max_ == -1) {
179     msg += fmt(_("must be greater than or equal to %" PRId64 "."), min_);
180   }
181   else {
182     msg += _("must be a number.");
183   }
184   throw DL_ABORT_EX(msg);
185 }
186 
createPossibleValuesString() const187 std::string NumberOptionHandler::createPossibleValuesString() const
188 {
189   std::string values;
190   if (min_ == -1) {
191     values += "*";
192   }
193   else {
194     values += util::itos(min_);
195   }
196   values += "-";
197   if (max_ == -1) {
198     values += "*";
199   }
200   else {
201     values += util::itos(max_);
202   }
203   return values;
204 }
205 
UnitNumberOptionHandler(PrefPtr pref,const char * description,const std::string & defaultValue,int64_t min,int64_t max,char shortName)206 UnitNumberOptionHandler::UnitNumberOptionHandler(
207     PrefPtr pref, const char* description, const std::string& defaultValue,
208     int64_t min, int64_t max, char shortName)
209     : NumberOptionHandler(pref, description, defaultValue, min, max, shortName)
210 {
211 }
212 
213 UnitNumberOptionHandler::~UnitNumberOptionHandler() = default;
214 
parseArg(Option & option,const std::string & optarg) const215 void UnitNumberOptionHandler::parseArg(Option& option,
216                                        const std::string& optarg) const
217 {
218   int64_t num = util::getRealSize(optarg);
219   NumberOptionHandler::parseArg(option, num);
220 }
221 
FloatNumberOptionHandler(PrefPtr pref,const char * description,const std::string & defaultValue,double min,double max,char shortName)222 FloatNumberOptionHandler::FloatNumberOptionHandler(
223     PrefPtr pref, const char* description, const std::string& defaultValue,
224     double min, double max, char shortName)
225     : AbstractOptionHandler(pref, description, defaultValue,
226                             OptionHandler::REQ_ARG, shortName),
227       min_(min),
228       max_(max)
229 {
230 }
231 
232 FloatNumberOptionHandler::~FloatNumberOptionHandler() = default;
233 
parseArg(Option & option,const std::string & optarg) const234 void FloatNumberOptionHandler::parseArg(Option& option,
235                                         const std::string& optarg) const
236 {
237   double number = strtod(optarg.c_str(), nullptr);
238   if ((min_ < 0 || min_ <= number) && (max_ < 0 || number <= max_)) {
239     option.put(pref_, optarg);
240   }
241   else {
242     std::string msg = pref_->k;
243     msg += " ";
244     if (min_ < 0 && max_ >= 0) {
245       msg += fmt(_("must be smaller than or equal to %.1f."), max_);
246     }
247     else if (min_ >= 0 && max_ >= 0) {
248       msg += fmt(_("must be between %.1f and %.1f."), min_, max_);
249     }
250     else if (min_ >= 0 && max_ < 0) {
251       msg += fmt(_("must be greater than or equal to %.1f."), min_);
252     }
253     else {
254       msg += _("must be a number.");
255     }
256     throw DL_ABORT_EX(msg);
257   }
258 }
259 
createPossibleValuesString() const260 std::string FloatNumberOptionHandler::createPossibleValuesString() const
261 {
262   std::string valuesString;
263   if (min_ < 0) {
264     valuesString += "*";
265   }
266   else {
267     valuesString += fmt("%.1f", min_);
268   }
269   valuesString += "-";
270   if (max_ < 0) {
271     valuesString += "*";
272   }
273   else {
274     valuesString += fmt("%.1f", max_);
275   }
276   return valuesString;
277 }
278 
DefaultOptionHandler(PrefPtr pref,const char * description,const std::string & defaultValue,const std::string & possibleValuesString,OptionHandler::ARG_TYPE argType,char shortName)279 DefaultOptionHandler::DefaultOptionHandler(
280     PrefPtr pref, const char* description, const std::string& defaultValue,
281     const std::string& possibleValuesString, OptionHandler::ARG_TYPE argType,
282     char shortName)
283     : AbstractOptionHandler(pref, description, defaultValue, argType,
284                             shortName),
285       possibleValuesString_(possibleValuesString),
286       allowEmpty_(true)
287 {
288 }
289 
290 DefaultOptionHandler::~DefaultOptionHandler() = default;
291 
parseArg(Option & option,const std::string & optarg) const292 void DefaultOptionHandler::parseArg(Option& option,
293                                     const std::string& optarg) const
294 {
295   if (!allowEmpty_ && optarg.empty()) {
296     throw DL_ABORT_EX("Empty string is not allowed");
297   }
298   option.put(pref_, optarg);
299 }
300 
createPossibleValuesString() const301 std::string DefaultOptionHandler::createPossibleValuesString() const
302 {
303   return possibleValuesString_;
304 }
305 
setAllowEmpty(bool allow)306 void DefaultOptionHandler::setAllowEmpty(bool allow) { allowEmpty_ = allow; }
307 
CumulativeOptionHandler(PrefPtr pref,const char * description,const std::string & defaultValue,const std::string & delim,const std::string & possibleValuesString,OptionHandler::ARG_TYPE argType,char shortName)308 CumulativeOptionHandler::CumulativeOptionHandler(
309     PrefPtr pref, const char* description, const std::string& defaultValue,
310     const std::string& delim, const std::string& possibleValuesString,
311     OptionHandler::ARG_TYPE argType, char shortName)
312     : AbstractOptionHandler(pref, description, defaultValue, argType,
313                             shortName),
314       delim_(delim),
315       possibleValuesString_(possibleValuesString)
316 {
317 }
318 
319 CumulativeOptionHandler::~CumulativeOptionHandler() = default;
320 
parseArg(Option & option,const std::string & optarg) const321 void CumulativeOptionHandler::parseArg(Option& option,
322                                        const std::string& optarg) const
323 {
324   std::string value = option.get(pref_);
325   value += optarg;
326   value += delim_;
327   option.put(pref_, value);
328 }
329 
createPossibleValuesString() const330 std::string CumulativeOptionHandler::createPossibleValuesString() const
331 {
332   return possibleValuesString_;
333 }
334 
IndexOutOptionHandler(PrefPtr pref,const char * description,char shortName)335 IndexOutOptionHandler::IndexOutOptionHandler(PrefPtr pref,
336                                              const char* description,
337                                              char shortName)
338     : AbstractOptionHandler(pref, description, NO_DEFAULT_VALUE,
339                             OptionHandler::REQ_ARG, shortName)
340 {
341 }
342 
343 IndexOutOptionHandler::~IndexOutOptionHandler() = default;
344 
parseArg(Option & option,const std::string & optarg) const345 void IndexOutOptionHandler::parseArg(Option& option,
346                                      const std::string& optarg) const
347 {
348   // See optarg is in the format of "INDEX=PATH"
349   util::parseIndexPath(optarg);
350   std::string value = option.get(pref_);
351   value += optarg;
352   value += "\n";
353   option.put(pref_, value);
354 }
355 
createPossibleValuesString() const356 std::string IndexOutOptionHandler::createPossibleValuesString() const
357 {
358   return "INDEX=PATH";
359 }
360 
ChecksumOptionHandler(PrefPtr pref,const char * description,char shortName)361 ChecksumOptionHandler::ChecksumOptionHandler(PrefPtr pref,
362                                              const char* description,
363                                              char shortName)
364     : AbstractOptionHandler(pref, description, NO_DEFAULT_VALUE,
365                             OptionHandler::REQ_ARG, shortName)
366 {
367 }
368 
ChecksumOptionHandler(PrefPtr pref,const char * description,std::vector<std::string> acceptableTypes,char shortName)369 ChecksumOptionHandler::ChecksumOptionHandler(
370     PrefPtr pref, const char* description,
371     std::vector<std::string> acceptableTypes, char shortName)
372     : AbstractOptionHandler(pref, description, NO_DEFAULT_VALUE,
373                             OptionHandler::REQ_ARG, shortName),
374       acceptableTypes_(std::move(acceptableTypes))
375 {
376 }
377 
378 ChecksumOptionHandler::~ChecksumOptionHandler() = default;
379 
parseArg(Option & option,const std::string & optarg) const380 void ChecksumOptionHandler::parseArg(Option& option,
381                                      const std::string& optarg) const
382 {
383   auto p = util::divide(std::begin(optarg), std::end(optarg), '=');
384   std::string hashType(p.first.first, p.first.second);
385   if (!acceptableTypes_.empty() &&
386       std::find(std::begin(acceptableTypes_), std::end(acceptableTypes_),
387                 hashType) == std::end(acceptableTypes_)) {
388     throw DL_ABORT_EX(
389         fmt("Checksum type %s is not acceptable", hashType.c_str()));
390   }
391   std::string hexDigest(p.second.first, p.second.second);
392   util::lowercase(hashType);
393   util::lowercase(hexDigest);
394   if (!MessageDigest::isValidHash(hashType, hexDigest)) {
395     throw DL_ABORT_EX(_("Unrecognized checksum"));
396   }
397   option.put(pref_, optarg);
398 }
399 
createPossibleValuesString() const400 std::string ChecksumOptionHandler::createPossibleValuesString() const
401 {
402   return "HASH_TYPE=HEX_DIGEST";
403 }
404 
ParameterOptionHandler(PrefPtr pref,const char * description,const std::string & defaultValue,std::vector<std::string> validParamValues,char shortName)405 ParameterOptionHandler::ParameterOptionHandler(
406     PrefPtr pref, const char* description, const std::string& defaultValue,
407     std::vector<std::string> validParamValues, char shortName)
408     : AbstractOptionHandler(pref, description, defaultValue,
409                             OptionHandler::REQ_ARG, shortName),
410       validParamValues_(std::move(validParamValues))
411 {
412 }
413 
414 ParameterOptionHandler::~ParameterOptionHandler() = default;
415 
parseArg(Option & option,const std::string & optarg) const416 void ParameterOptionHandler::parseArg(Option& option,
417                                       const std::string& optarg) const
418 {
419   auto itr =
420       std::find(validParamValues_.begin(), validParamValues_.end(), optarg);
421   if (itr == validParamValues_.end()) {
422     std::string msg = pref_->k;
423     msg += " ";
424     msg += _("must be one of the following:");
425     if (validParamValues_.size() == 0) {
426       msg += "''";
427     }
428     else {
429       for (const auto& p : validParamValues_) {
430         msg += "'";
431         msg += p;
432         msg += "' ";
433       }
434     }
435     throw DL_ABORT_EX(msg);
436   }
437   else {
438     option.put(pref_, optarg);
439   }
440 }
441 
createPossibleValuesString() const442 std::string ParameterOptionHandler::createPossibleValuesString() const
443 {
444   std::stringstream s;
445   std::copy(validParamValues_.begin(), validParamValues_.end(),
446             std::ostream_iterator<std::string>(s, ", "));
447   return util::strip(s.str(), ", ");
448 }
449 
HostPortOptionHandler(PrefPtr pref,const char * description,const std::string & defaultValue,PrefPtr hostOptionName,PrefPtr portOptionName,char shortName)450 HostPortOptionHandler::HostPortOptionHandler(
451     PrefPtr pref, const char* description, const std::string& defaultValue,
452     PrefPtr hostOptionName, PrefPtr portOptionName, char shortName)
453     : AbstractOptionHandler(pref, description, defaultValue,
454                             OptionHandler::REQ_ARG, shortName),
455       hostOptionName_(hostOptionName),
456       portOptionName_(portOptionName)
457 {
458 }
459 
460 HostPortOptionHandler::~HostPortOptionHandler() = default;
461 
parseArg(Option & option,const std::string & optarg) const462 void HostPortOptionHandler::parseArg(Option& option,
463                                      const std::string& optarg) const
464 {
465   std::string uri = "http://";
466   uri += optarg;
467   Request req;
468   if (!req.setUri(uri)) {
469     throw DL_ABORT_EX(_("Unrecognized format"));
470   }
471   option.put(pref_, optarg);
472   setHostAndPort(option, req.getHost(), req.getPort());
473 }
474 
setHostAndPort(Option & option,const std::string & hostname,uint16_t port) const475 void HostPortOptionHandler::setHostAndPort(Option& option,
476                                            const std::string& hostname,
477                                            uint16_t port) const
478 {
479   option.put(hostOptionName_, hostname);
480   option.put(portOptionName_, util::uitos(port));
481 }
482 
createPossibleValuesString() const483 std::string HostPortOptionHandler::createPossibleValuesString() const
484 {
485   return "HOST:PORT";
486 }
487 
HttpProxyOptionHandler(PrefPtr pref,const char * description,const std::string & defaultValue,char shortName)488 HttpProxyOptionHandler::HttpProxyOptionHandler(PrefPtr pref,
489                                                const char* description,
490                                                const std::string& defaultValue,
491                                                char shortName)
492     : AbstractOptionHandler(pref, description, defaultValue,
493                             OptionHandler::REQ_ARG, shortName),
494       proxyUserPref_(option::k2p(std::string(pref->k) + "-user")),
495       proxyPasswdPref_(option::k2p(std::string(pref->k) + "-passwd"))
496 {
497 }
498 
499 HttpProxyOptionHandler::~HttpProxyOptionHandler() = default;
500 
parseArg(Option & option,const std::string & optarg) const501 void HttpProxyOptionHandler::parseArg(Option& option,
502                                       const std::string& optarg) const
503 {
504   if (optarg.empty()) {
505     option.put(pref_, optarg);
506   }
507   else {
508     std::string uri;
509     if (util::startsWith(optarg, "http://") ||
510         util::startsWith(optarg, "https://") ||
511         util::startsWith(optarg, "ftp://")) {
512       uri = optarg;
513     }
514     else {
515       uri = "http://";
516       uri += optarg;
517     }
518     uri::UriStruct us;
519     if (!uri::parse(us, uri)) {
520       throw DL_ABORT_EX(_("unrecognized proxy format"));
521     }
522     us.protocol = "http";
523     option.put(pref_, uri::construct(us));
524   }
525 }
526 
createPossibleValuesString() const527 std::string HttpProxyOptionHandler::createPossibleValuesString() const
528 {
529   return "[http://][USER:PASSWORD@]HOST[:PORT]";
530 }
531 
LocalFilePathOptionHandler(PrefPtr pref,const char * description,const std::string & defaultValue,bool acceptStdin,char shortName,bool mustExist,const std::string & possibleValuesString)532 LocalFilePathOptionHandler::LocalFilePathOptionHandler(
533     PrefPtr pref, const char* description, const std::string& defaultValue,
534     bool acceptStdin, char shortName, bool mustExist,
535     const std::string& possibleValuesString)
536     : AbstractOptionHandler(pref, description, defaultValue,
537                             OptionHandler::REQ_ARG, shortName),
538       possibleValuesString_(possibleValuesString),
539       acceptStdin_(acceptStdin),
540       mustExist_(mustExist)
541 {
542 }
543 
parseArg(Option & option,const std::string & optarg) const544 void LocalFilePathOptionHandler::parseArg(Option& option,
545                                           const std::string& optarg) const
546 {
547   if (acceptStdin_ && optarg == "-") {
548     option.put(pref_, DEV_STDIN);
549   }
550   else {
551     auto path = util::replace(optarg, "${HOME}", util::getHomeDir());
552     if (mustExist_) {
553       File f(path);
554       std::string err;
555       if (!f.exists(err)) {
556         throw DL_ABORT_EX(err);
557       }
558       if (f.isDir()) {
559         throw DL_ABORT_EX(fmt(MSG_NOT_FILE, optarg.c_str()));
560       }
561     }
562     option.put(pref_, path);
563   }
564 }
565 
createPossibleValuesString() const566 std::string LocalFilePathOptionHandler::createPossibleValuesString() const
567 {
568   if (!possibleValuesString_.empty()) {
569     return possibleValuesString_;
570   }
571   if (acceptStdin_) {
572     return PATH_TO_FILE_STDIN;
573   }
574   else {
575     return PATH_TO_FILE;
576   }
577 }
578 
PrioritizePieceOptionHandler(PrefPtr pref,const char * description,const std::string & defaultValue,char shortName)579 PrioritizePieceOptionHandler::PrioritizePieceOptionHandler(
580     PrefPtr pref, const char* description, const std::string& defaultValue,
581     char shortName)
582     : AbstractOptionHandler(pref, description, defaultValue,
583                             OptionHandler::REQ_ARG, shortName)
584 {
585 }
586 
parseArg(Option & option,const std::string & optarg) const587 void PrioritizePieceOptionHandler::parseArg(Option& option,
588                                             const std::string& optarg) const
589 {
590   // Parse optarg against empty FileEntry list to detect syntax
591   // error.
592   std::vector<size_t> result;
593   util::parsePrioritizePieceRange(
594       result, optarg, std::vector<std::shared_ptr<FileEntry>>(), 1024);
595   option.put(pref_, optarg);
596 }
597 
createPossibleValuesString() const598 std::string PrioritizePieceOptionHandler::createPossibleValuesString() const
599 {
600   return "head[=SIZE], tail[=SIZE]";
601 }
602 
603 OptimizeConcurrentDownloadsOptionHandler::
OptimizeConcurrentDownloadsOptionHandler(PrefPtr pref,const char * description,const std::string & defaultValue,char shortName)604     OptimizeConcurrentDownloadsOptionHandler(PrefPtr pref,
605                                              const char* description,
606                                              const std::string& defaultValue,
607                                              char shortName)
608     : AbstractOptionHandler(pref, description, defaultValue,
609                             OptionHandler::OPT_ARG, shortName)
610 {
611 }
612 
parseArg(Option & option,const std::string & optarg) const613 void OptimizeConcurrentDownloadsOptionHandler::parseArg(
614     Option& option, const std::string& optarg) const
615 {
616   if (optarg == "true" || optarg.empty()) {
617     option.put(pref_, A2_V_TRUE);
618   }
619   else if (optarg == "false") {
620     option.put(pref_, A2_V_FALSE);
621   }
622   else {
623     auto p = util::divide(std::begin(optarg), std::end(optarg), ':');
624 
625     std::string coeff_b(p.second.first, p.second.second);
626     if (coeff_b.empty()) {
627       std::string msg = pref_->k;
628       msg += " ";
629       msg += _("must be either 'true', 'false' or a pair numeric coefficients "
630                "A and B under the form 'A:B'.");
631       throw DL_ABORT_EX(msg);
632     }
633 
634     std::string coeff_a(p.first.first, p.first.second);
635 
636     PrefPtr pref = PREF_OPTIMIZE_CONCURRENT_DOWNLOADS_COEFFA;
637     std::string* sptr = &coeff_a;
638     for (;;) {
639       char* end;
640       errno = 0;
641       strtod(sptr->c_str(), &end);
642       if (errno != 0 || sptr->c_str() + sptr->size() != end) {
643         throw DL_ABORT_EX(fmt("Bad number '%s'", sptr->c_str()));
644       }
645       option.put(pref, *sptr);
646 
647       if (pref == PREF_OPTIMIZE_CONCURRENT_DOWNLOADS_COEFFB) {
648         break;
649       }
650       pref = PREF_OPTIMIZE_CONCURRENT_DOWNLOADS_COEFFB;
651       sptr = &coeff_b;
652     }
653     option.put(pref_, A2_V_TRUE);
654   }
655 }
656 
657 std::string
createPossibleValuesString() const658 OptimizeConcurrentDownloadsOptionHandler::createPossibleValuesString() const
659 {
660   return "true, false, A:B";
661 }
662 
DeprecatedOptionHandler(OptionHandler * depOptHandler,const OptionHandler * repOptHandler,bool stillWork,std::string additionalMessage)663 DeprecatedOptionHandler::DeprecatedOptionHandler(
664     OptionHandler* depOptHandler, const OptionHandler* repOptHandler,
665     bool stillWork, std::string additionalMessage)
666     : depOptHandler_(depOptHandler),
667       repOptHandler_(repOptHandler),
668       stillWork_(stillWork),
669       additionalMessage_(std::move(additionalMessage))
670 {
671   depOptHandler_->addTag(TAG_DEPRECATED);
672 }
673 
~DeprecatedOptionHandler()674 DeprecatedOptionHandler::~DeprecatedOptionHandler()
675 {
676   delete depOptHandler_;
677   // We don't delete repOptHandler_.
678 }
679 
parse(Option & option,const std::string & arg) const680 void DeprecatedOptionHandler::parse(Option& option,
681                                     const std::string& arg) const
682 {
683   if (repOptHandler_) {
684     A2_LOG_WARN(fmt(_("--%s option is deprecated. Use --%s option instead. %s"),
685                     depOptHandler_->getName(), repOptHandler_->getName(),
686                     additionalMessage_.c_str()));
687     repOptHandler_->parse(option, arg);
688   }
689   else if (stillWork_) {
690     A2_LOG_WARN(fmt(_("--%s option will be deprecated in the future release. "
691                       "%s"),
692                     depOptHandler_->getName(), additionalMessage_.c_str()));
693     depOptHandler_->parse(option, arg);
694   }
695   else {
696     A2_LOG_WARN(fmt(_("--%s option is deprecated. %s"),
697                     depOptHandler_->getName(), additionalMessage_.c_str()));
698   }
699 }
700 
createPossibleValuesString() const701 std::string DeprecatedOptionHandler::createPossibleValuesString() const
702 {
703   return depOptHandler_->createPossibleValuesString();
704 }
705 
hasTag(uint32_t tag) const706 bool DeprecatedOptionHandler::hasTag(uint32_t tag) const
707 {
708   return depOptHandler_->hasTag(tag);
709 }
710 
addTag(uint32_t tag)711 void DeprecatedOptionHandler::addTag(uint32_t tag)
712 {
713   depOptHandler_->addTag(tag);
714 }
715 
toTagString() const716 std::string DeprecatedOptionHandler::toTagString() const
717 {
718   return depOptHandler_->toTagString();
719 }
720 
getName() const721 const char* DeprecatedOptionHandler::getName() const
722 {
723   return depOptHandler_->getName();
724 }
725 
getDescription() const726 const char* DeprecatedOptionHandler::getDescription() const
727 {
728   return depOptHandler_->getDescription();
729 }
730 
getDefaultValue() const731 const std::string& DeprecatedOptionHandler::getDefaultValue() const
732 {
733   return depOptHandler_->getDefaultValue();
734 }
735 
isHidden() const736 bool DeprecatedOptionHandler::isHidden() const
737 {
738   return depOptHandler_->isHidden();
739 }
740 
hide()741 void DeprecatedOptionHandler::hide() { depOptHandler_->hide(); }
742 
getPref() const743 PrefPtr DeprecatedOptionHandler::getPref() const
744 {
745   return depOptHandler_->getPref();
746 }
747 
getArgType() const748 OptionHandler::ARG_TYPE DeprecatedOptionHandler::getArgType() const
749 {
750   return depOptHandler_->getArgType();
751 }
752 
getShortName() const753 char DeprecatedOptionHandler::getShortName() const
754 {
755   return depOptHandler_->getShortName();
756 }
757 
getEraseAfterParse() const758 bool DeprecatedOptionHandler::getEraseAfterParse() const
759 {
760   return depOptHandler_->getEraseAfterParse();
761 }
762 
setEraseAfterParse(bool eraseAfterParse)763 void DeprecatedOptionHandler::setEraseAfterParse(bool eraseAfterParse)
764 {
765   depOptHandler_->setEraseAfterParse(eraseAfterParse);
766 }
767 
getInitialOption() const768 bool DeprecatedOptionHandler::getInitialOption() const
769 {
770   return depOptHandler_->getInitialOption();
771 }
772 
setInitialOption(bool f)773 void DeprecatedOptionHandler::setInitialOption(bool f)
774 {
775   depOptHandler_->setInitialOption(f);
776 }
777 
getChangeOption() const778 bool DeprecatedOptionHandler::getChangeOption() const
779 {
780   return depOptHandler_->getChangeOption();
781 }
782 
setChangeOption(bool f)783 void DeprecatedOptionHandler::setChangeOption(bool f)
784 {
785   depOptHandler_->setChangeOption(f);
786 }
787 
getChangeOptionForReserved() const788 bool DeprecatedOptionHandler::getChangeOptionForReserved() const
789 {
790   return depOptHandler_->getChangeOptionForReserved();
791 }
792 
setChangeOptionForReserved(bool f)793 void DeprecatedOptionHandler::setChangeOptionForReserved(bool f)
794 {
795   depOptHandler_->setChangeOptionForReserved(f);
796 }
797 
getChangeGlobalOption() const798 bool DeprecatedOptionHandler::getChangeGlobalOption() const
799 {
800   return depOptHandler_->getChangeGlobalOption();
801 }
802 
setChangeGlobalOption(bool f)803 void DeprecatedOptionHandler::setChangeGlobalOption(bool f)
804 {
805   depOptHandler_->setChangeGlobalOption(f);
806 }
807 
getCumulative() const808 bool DeprecatedOptionHandler::getCumulative() const
809 {
810   return depOptHandler_->getCumulative();
811 }
812 
setCumulative(bool f)813 void DeprecatedOptionHandler::setCumulative(bool f)
814 {
815   depOptHandler_->setCumulative(f);
816 }
817 
818 } // namespace aria2
819