mirror of https://github.com/aria2/aria2
Merge pull request #1905 from aria2/bt-bencode-allow-empty-dict-name
Allow empty dist name in bencode which is needed for hybrid torrentpull/1907/head
commit
998f203288
|
@ -42,9 +42,14 @@
|
||||||
|
|
||||||
namespace aria2 {
|
namespace aria2 {
|
||||||
|
|
||||||
template <typename Parser, typename ParserStateMachine> class GenericParser {
|
template <typename Parser, typename ParserStateMachine,
|
||||||
|
bool allowEmptyName = false>
|
||||||
|
class GenericParser {
|
||||||
public:
|
public:
|
||||||
GenericParser() : parser_{&psm_} {}
|
GenericParser() : parser_{&psm_}
|
||||||
|
{
|
||||||
|
psm_.setAllowEmptyMemberName(allowEmptyName);
|
||||||
|
}
|
||||||
|
|
||||||
~GenericParser() = default;
|
~GenericParser() = default;
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ namespace aria2 {
|
||||||
|
|
||||||
namespace bittorrent {
|
namespace bittorrent {
|
||||||
|
|
||||||
typedef GenericParser<BencodeParser, ValueBaseStructParserStateMachine>
|
typedef GenericParser<BencodeParser, ValueBaseStructParserStateMachine, true>
|
||||||
ValueBaseBencodeParser;
|
ValueBaseBencodeParser;
|
||||||
|
|
||||||
} // namespace bittorrent
|
} // namespace bittorrent
|
||||||
|
|
|
@ -213,4 +213,9 @@ void ValueBaseStructParserStateMachine::pushNullState()
|
||||||
stateStack_.push(nullState);
|
stateStack_.push(nullState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ValueBaseStructParserStateMachine::setAllowEmptyMemberName(bool b)
|
||||||
|
{
|
||||||
|
ctrl_->setAllowEmptyMemberName(b);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
|
@ -106,6 +106,8 @@ public:
|
||||||
void pushBoolState();
|
void pushBoolState();
|
||||||
void pushNullState();
|
void pushNullState();
|
||||||
|
|
||||||
|
void setAllowEmptyMemberName(bool b);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<rpc::XmlRpcRequestParserController> ctrl_;
|
std::unique_ptr<rpc::XmlRpcRequestParserController> ctrl_;
|
||||||
std::stack<ValueBaseStructParserState*> stateStack_;
|
std::stack<ValueBaseStructParserState*> stateStack_;
|
||||||
|
|
|
@ -54,7 +54,7 @@ void XmlRpcRequestParserController::popStructFrame()
|
||||||
Dict* dict = downcast<Dict>(parentFrame.value_);
|
Dict* dict = downcast<Dict>(parentFrame.value_);
|
||||||
assert(dict);
|
assert(dict);
|
||||||
frameStack_.pop();
|
frameStack_.pop();
|
||||||
if (currentFrame_.validMember()) {
|
if (currentFrame_.validMember(allowEmptyMemberName_)) {
|
||||||
dict->put(std::move(currentFrame_.name_), std::move(currentFrame_.value_));
|
dict->put(std::move(currentFrame_.name_), std::move(currentFrame_.value_));
|
||||||
}
|
}
|
||||||
currentFrame_ = std::move(parentFrame);
|
currentFrame_ = std::move(parentFrame);
|
||||||
|
@ -110,6 +110,11 @@ void XmlRpcRequestParserController::setMethodName(std::string methodName)
|
||||||
methodName_ = std::move(methodName);
|
methodName_ = std::move(methodName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void XmlRpcRequestParserController::setAllowEmptyMemberName(bool b)
|
||||||
|
{
|
||||||
|
allowEmptyMemberName_ = b;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace rpc
|
} // namespace rpc
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
|
@ -52,7 +52,10 @@ private:
|
||||||
std::unique_ptr<ValueBase> value_;
|
std::unique_ptr<ValueBase> value_;
|
||||||
std::string name_;
|
std::string name_;
|
||||||
|
|
||||||
bool validMember() const { return value_ && !name_.empty(); }
|
bool validMember(bool allowEmptyMemberName) const
|
||||||
|
{
|
||||||
|
return value_ && (allowEmptyMemberName || !name_.empty());
|
||||||
|
}
|
||||||
|
|
||||||
void reset()
|
void reset()
|
||||||
{
|
{
|
||||||
|
@ -67,7 +70,11 @@ private:
|
||||||
|
|
||||||
std::string methodName_;
|
std::string methodName_;
|
||||||
|
|
||||||
|
bool allowEmptyMemberName_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
XmlRpcRequestParserController() : allowEmptyMemberName_(false) {}
|
||||||
|
|
||||||
void pushFrame();
|
void pushFrame();
|
||||||
|
|
||||||
// Pops StateFrame p from frameStack_ and set p[currentFrame_.name_]
|
// Pops StateFrame p from frameStack_ and set p[currentFrame_.name_]
|
||||||
|
@ -90,6 +97,8 @@ public:
|
||||||
|
|
||||||
const std::string& getMethodName() const { return methodName_; }
|
const std::string& getMethodName() const { return methodName_; }
|
||||||
|
|
||||||
|
void setAllowEmptyMemberName(bool b);
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -208,6 +208,16 @@ void ValueBaseBencodeParserTest::testParseUpdate()
|
||||||
// Get trailing garbage position
|
// Get trailing garbage position
|
||||||
CPPUNIT_ASSERT_EQUAL((ssize_t)7, error);
|
CPPUNIT_ASSERT_EQUAL((ssize_t)7, error);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
// dict, empty member name
|
||||||
|
std::string src = "d0:i123ee";
|
||||||
|
std::shared_ptr<ValueBase> d =
|
||||||
|
parser.parseFinal(src.c_str(), src.size(), error);
|
||||||
|
Dict* dict = downcast<Dict>(d);
|
||||||
|
CPPUNIT_ASSERT(dict);
|
||||||
|
CPPUNIT_ASSERT(dict->get(""));
|
||||||
|
CPPUNIT_ASSERT_EQUAL((int64_t)123, downcast<Integer>(dict->get(""))->i());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace aria2
|
} // namespace aria2
|
||||||
|
|
Loading…
Reference in New Issue