diff --git a/src/XmlRpcRequestParserStateImpl.cc b/src/XmlRpcRequestParserStateImpl.cc index 7cf1c5ac..2d406e8e 100644 --- a/src/XmlRpcRequestParserStateImpl.cc +++ b/src/XmlRpcRequestParserStateImpl.cc @@ -168,7 +168,20 @@ void ValueXmlRpcRequestParserState::beginElement stm->pushUnknownElementState(); } } - + +void ValueXmlRpcRequestParserState::endElement +(XmlRpcRequestParserStateMachine* stm, + const std::string& name, + const std::string& characters) +{ + // XML-RPC specification says that if no data type tag is used, the + // data must be treated as string. To prevent from overwriting + // current frame value, we first check it is still null. + if(!stm->getCurrentFrameValue() && !characters.empty()) { + stm->setCurrentFrameValue(String::g(characters)); + } +} + // IntXmlRpcRequestParserState void IntXmlRpcRequestParserState::beginElement @@ -321,6 +334,7 @@ void ArrayValueXmlRpcRequestParserState::endElement const std::string& name, const std::string& characters) { + ValueXmlRpcRequestParserState::endElement(stm, name, characters); stm->popArrayFrame(); } diff --git a/src/XmlRpcRequestParserStateImpl.h b/src/XmlRpcRequestParserStateImpl.h index c73aeb3a..40a1534e 100644 --- a/src/XmlRpcRequestParserStateImpl.h +++ b/src/XmlRpcRequestParserStateImpl.h @@ -121,12 +121,12 @@ class ValueXmlRpcRequestParserState:public XmlRpcRequestParserState { virtual void beginElement(XmlRpcRequestParserStateMachine* stm, const std::string& name, const std::map& attrs); - +protected: virtual void endElement(XmlRpcRequestParserStateMachine* stm, const std::string& name, - const std::string& characters) {} + const std::string& characters); - virtual bool needsCharactersBuffering() const { return false; } + virtual bool needsCharactersBuffering() const { return true; } }; class IntXmlRpcRequestParserState:public XmlRpcRequestParserState { diff --git a/test/XmlRpcRequestProcessorTest.cc b/test/XmlRpcRequestProcessorTest.cc index c0f724e7..33c87984 100644 --- a/test/XmlRpcRequestProcessorTest.cc +++ b/test/XmlRpcRequestProcessorTest.cc @@ -14,6 +14,7 @@ class XmlRpcRequestProcessorTest:public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(XmlRpcRequestProcessorTest); CPPUNIT_TEST(testParseMemory); CPPUNIT_TEST(testParseMemory_shouldFail); + CPPUNIT_TEST(testParseMemory_withoutStringTag); CPPUNIT_TEST_SUITE_END(); public: void setUp() {} @@ -22,6 +23,7 @@ public: void testParseMemory(); void testParseMemory_shouldFail(); + void testParseMemory_withoutStringTag(); }; @@ -114,6 +116,58 @@ void XmlRpcRequestProcessorTest::testParseMemory_shouldFail() } } +void XmlRpcRequestProcessorTest::testParseMemory_withoutStringTag() +{ + XmlRpcRequestProcessor proc; + RpcRequest req = + proc.parseMemory("" + "" + " aria2.addUri" + " " + " " + " http://aria2.sourceforge.net" + " " + " " + " http://aria2.sourceforge.net" + " " + " " + " " + " " + " " + " hello" + " world" + " " + " " + " " + " " + " " + " " + " " + " " + " apple" + " banana" + " lemonpeanuts" + " " + " " + " " + " " + " " + ""); + + CPPUNIT_ASSERT_EQUAL((size_t)4, req.params->size()); + CPPUNIT_ASSERT_EQUAL(std::string("http://aria2.sourceforge.net"), + asString(req.params->get(0))->s()); + CPPUNIT_ASSERT_EQUAL(std::string("http://aria2.sourceforge.net"), + asString(req.params->get(1))->s()); + const Dict* dict = asDict(req.params->get(2)); + CPPUNIT_ASSERT_EQUAL(std::string("world"), + asString(dict->get("hello"))->s()); + const List* list = asList(req.params->get(3)); + CPPUNIT_ASSERT_EQUAL(std::string("apple"), asString(list->get(0))->s()); + CPPUNIT_ASSERT_EQUAL(std::string("banana"), asString(list->get(1))->s()); + CPPUNIT_ASSERT_EQUAL(std::string("lemon"), asString(list->get(2))->s()); +} + } // namespace rpc } // namespace aria2