Use XmlParser for XML-RPC.

pull/2/head
Tatsuhiro Tsujikawa 2011-11-11 00:37:32 +09:00
parent 3b4a368554
commit 787bfd75da
17 changed files with 609 additions and 1017 deletions

View File

@ -1,134 +0,0 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2009 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#include "ExpatXmlRpcRequestProcessor.h"
#include <stack>
#include <expat.h>
#include "XmlRpcRequestParserStateMachine.h"
#include "util.h"
#include "DlAbortEx.h"
#include "message.h"
namespace aria2 {
namespace rpc {
namespace {
struct SessionData {
XmlRpcRequestParserStateMachine* stm_;
std::stack<std::string> charactersStack_;
SessionData(XmlRpcRequestParserStateMachine* stm):stm_(stm) {}
};
} // namespace
namespace {
void mlStartElement(void* userData, const char* name, const char** attrs)
{
SessionData* sd = reinterpret_cast<SessionData*>(userData);
std::map<std::string, std::string> attrmap;
if(attrs) {
const char** p = attrs;
while(*p != 0) {
std::string name = *p++;
if(*p == 0) {
break;
}
std::string value = util::strip(*p++);
attrmap[name] = value;
}
}
sd->stm_->beginElement(name, attrmap);
if(sd->stm_->needsCharactersBuffering()) {
sd->charactersStack_.push(std::string());
}
}
} // namespace
namespace {
void mlEndElement(void* userData, const char* name)
{
SessionData* sd = reinterpret_cast<SessionData*>(userData);
std::string characters;
if(sd->stm_->needsCharactersBuffering()) {
characters = util::strip(sd->charactersStack_.top());
sd->charactersStack_.pop();
}
sd->stm_->endElement(name, characters);
}
} // namespace
namespace {
void mlCharacters(void* userData, const char* ch, int len)
{
SessionData* sd = reinterpret_cast<SessionData*>(userData);
if(sd->stm_->needsCharactersBuffering()) {
sd->charactersStack_.top().append(&ch[0], &ch[len]);
}
}
} // namespace
RpcRequest
XmlRpcRequestProcessor::parseMemory(const std::string& xml)
{
stm_.reset(new XmlRpcRequestParserStateMachine());
SharedHandle<SessionData> sessionData(new SessionData(stm_.get()));
XML_Parser parser = XML_ParserCreate(0);
XML_SetUserData(parser, sessionData.get());
XML_SetElementHandler(parser, &mlStartElement, &mlEndElement);
XML_SetCharacterDataHandler(parser, &mlCharacters);
int r = XML_Parse(parser, xml.data(), xml.size(), 1);
XML_ParserFree(parser);
if(r == XML_STATUS_ERROR) {
throw DL_ABORT_EX(MSG_CANNOT_PARSE_XML_RPC_REQUEST);
}
if(!downcast<List>(stm_->getCurrentFrameValue())) {
throw DL_ABORT_EX("Bad XML-RPC parameter list");
}
return RpcRequest(stm_->getMethodName(),
static_pointer_cast<List>(stm_->getCurrentFrameValue()));
}
} // namespace rpc
} // namespace aria2

View File

@ -56,8 +56,8 @@
#include "RpcMethodFactory.h"
#include "RpcRequest.h"
#include "RpcResponse.h"
#include "rpc_helper.h"
#ifdef ENABLE_XML_RPC
# include "XmlRpcRequestProcessor.h"
# include "XmlRpcRequestParserStateMachine.h"
#endif // ENABLE_XML_RPC
@ -213,8 +213,8 @@ bool HttpServerBodyCommand::execute()
// Do something for requestpath and body
if(reqPath == "/rpc") {
#ifdef ENABLE_XML_RPC
rpc::RpcRequest req =
rpc::XmlRpcRequestProcessor().parseMemory(httpServer_->getBody());
std::string body = httpServer_->getBody();
rpc::RpcRequest req = rpc::xmlParseMemory(body.c_str(), body.size());
SharedHandle<rpc::RpcMethod> method =
rpc::RpcMethodFactory::create(req.methodName);
A2_LOG_INFO(fmt("Executing RPC method %s", req.methodName.c_str()));

View File

@ -222,7 +222,8 @@ SRCS = Socket.h\
SegList.h\
NullHandle.h\
a2iterator.h\
paramed_string.cc paramed_string.h
paramed_string.cc paramed_string.h\
rpc_helper.cc rpc_helper.h
if MINGW_BUILD
SRCS += WinConsoleFile.cc WinConsoleFile.h
@ -239,17 +240,8 @@ SRCS += XmlRpcRequestParserController.cc XmlRpcRequestParserController.h\
XmlRpcRequestParserStateMachine.cc XmlRpcRequestParserStateMachine.h\
XmlRpcRequestParserState.h\
XmlRpcRequestParserStateImpl.cc XmlRpcRequestParserStateImpl.h\
XmlRpcElements.cc XmlRpcElements.h\
XmlRpcRequestProcessor.h
if HAVE_LIBXML2
SRCS += Xml2XmlRpcRequestProcessor.cc Xml2XmlRpcRequestProcessor.h
endif # HAVE_LIBXML2
if HAVE_LIBEXPAT
SRCS += ExpatXmlRpcRequestProcessor.cc ExpatXmlRpcRequestProcessor.h
endif # HAVE_LIBEXPAT
endif # ENABLE_XML_RPC
if HAVE_SOME_FALLOCATE

View File

@ -1,172 +0,0 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2009 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#include "Xml2XmlRpcRequestProcessor.h"
#include <cstring>
#include <stack>
#include <libxml/parser.h>
#include "XmlRpcRequestParserStateMachine.h"
#include "util.h"
#include "DlAbortEx.h"
#include "message.h"
namespace aria2 {
namespace rpc {
namespace {
struct SessionData {
XmlRpcRequestParserStateMachine* stm_;
std::stack<std::string> charactersStack_;
SessionData(XmlRpcRequestParserStateMachine* stm):stm_(stm) {}
};
} // namespace
namespace {
void mlStartElement(void* userData, const xmlChar* name,
const xmlChar** attrs)
{
SessionData* sd = reinterpret_cast<SessionData*>(userData);
std::map<std::string, std::string> attrmap;
if(attrs) {
const char** p = reinterpret_cast<const char**>(attrs);
while(*p != 0) {
std::string name = *p;
++p;
if(*p == 0) {
break;
}
attrmap[name].assign(*p, *p+strlen(*p));
++p;
}
}
sd->stm_->beginElement(reinterpret_cast<const char*>(name), attrmap);
if(sd->stm_->needsCharactersBuffering()) {
sd->charactersStack_.push(A2STR::NIL);
}
}
} // namespace
namespace {
void mlEndElement(void* userData, const xmlChar* name)
{
SessionData* sd = reinterpret_cast<SessionData*>(userData);
if(sd->stm_->needsCharactersBuffering()) {
sd->stm_->endElement(reinterpret_cast<const char*>(name),
sd->charactersStack_.top());
sd->charactersStack_.pop();
} else {
sd->stm_->endElement(reinterpret_cast<const char*>(name), A2STR::NIL);
}
}
} // namespace
namespace {
void mlCharacters(void* userData, const xmlChar* ch, int len)
{
SessionData* sd = reinterpret_cast<SessionData*>(userData);
if(sd->stm_->needsCharactersBuffering()) {
sd->charactersStack_.top().append(&ch[0], &ch[len]);
}
}
} // namespace
namespace {
xmlSAXHandler mySAXHandler =
{
0, // internalSubsetSAXFunc
0, // isStandaloneSAXFunc
0, // hasInternalSubsetSAXFunc
0, // hasExternalSubsetSAXFunc
0, // resolveEntitySAXFunc
0, // getEntitySAXFunc
0, // entityDeclSAXFunc
0, // notationDeclSAXFunc
0, // attributeDeclSAXFunc
0, // elementDeclSAXFunc
0, // unparsedEntityDeclSAXFunc
0, // setDocumentLocatorSAXFunc
0, // startDocumentSAXFunc
0, // endDocumentSAXFunc
&mlStartElement, // startElementSAXFunc
&mlEndElement, // endElementSAXFunc
0, // referenceSAXFunc
&mlCharacters, // charactersSAXFunc
0, // ignorableWhitespaceSAXFunc
0, // processingInstructionSAXFunc
0, // commentSAXFunc
0, // warningSAXFunc
0, // errorSAXFunc
0, // fatalErrorSAXFunc
0, // getParameterEntitySAXFunc
0, // cdataBlockSAXFunc
0, // externalSubsetSAXFunc
0, // unsigned int initialized
0, // void * _private
0, // startElementNsSAX2Func
0, // endElementNsSAX2Func
0, // xmlStructuredErrorFunc
};
} // namespace
XmlRpcRequestProcessor::XmlRpcRequestProcessor() {}
XmlRpcRequestProcessor::~XmlRpcRequestProcessor() {}
RpcRequest
XmlRpcRequestProcessor::parseMemory(const std::string& xml)
{
stm_.reset(new XmlRpcRequestParserStateMachine());
SharedHandle<SessionData> sessionData(new SessionData(stm_.get()));
int r = xmlSAXUserParseMemory(&mySAXHandler, sessionData.get(),
xml.data(), xml.size());
if(r != 0) {
throw DL_ABORT_EX(MSG_CANNOT_PARSE_XML_RPC_REQUEST);
}
if(!downcast<List>(stm_->getCurrentFrameValue())) {
throw DL_ABORT_EX("Bad XML-RPC parameter list");
}
return RpcRequest(stm_->getMethodName(),
static_pointer_cast<List>(stm_->getCurrentFrameValue()));
}
} // namespace rpc
} // namespace aria2

View File

@ -1,66 +0,0 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2009 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#ifndef D_XML2_XML_RPC_REQUEST_PROCESSOR_H
#define D_XML2_XML_RPC_REQUEST_PROCESSOR_H
#include "common.h"
#include <string>
#include "SharedHandle.h"
#include "RpcRequest.h"
namespace aria2 {
namespace rpc {
class XmlRpcRequestParserStateMachine;
class XmlRpcRequestProcessor {
private:
SharedHandle<XmlRpcRequestParserStateMachine> stm_;
public:
XmlRpcRequestProcessor();
~XmlRpcRequestProcessor();
RpcRequest parseMemory(const std::string& xml);
};
} // namespace rpc
} // namespace aria2
#endif // D_XML2_XML_RPC_REQUEST_PROCESSOR_H

View File

@ -1,61 +0,0 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2009 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#include "XmlRpcElements.h"
namespace aria2 {
namespace rpc {
namespace elements {
const std::string METHOD_CALL("methodCall");
const std::string METHOD_NAME("methodName");
const std::string A2_PARAMS("params");
const std::string PARAM("param");
const std::string VALUE("value");
const std::string I4("i4");
const std::string INT("int");
const std::string BOOLEAN("boolean");
const std::string STRING("string");
const std::string DOUBLE("double");
const std::string DATE_TIME_ISO8601("dateTime.iso8601");
const std::string BASE64("base64");
const std::string STRUCT("struct");
const std::string MEMBER("member");
const std::string NAME("name");
const std::string ARRAY("array");
const std::string DATA("data");
} // namespace elements
} // namespace rpc
} // namespace aria2

View File

@ -1,68 +0,0 @@
/* <!-- copyright */
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2009 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you
* do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source
* files in the program, then also delete it here.
*/
/* copyright --> */
#ifndef D_XML_RPC_ELEMENTS_H
#define D_XML_RPC_ELEMENTS_H
#include "common.h"
#include <string>
namespace aria2 {
namespace rpc {
namespace elements {
extern const std::string METHOD_CALL;
extern const std::string METHOD_NAME;
extern const std::string A2_PARAMS;
extern const std::string PARAM;
extern const std::string VALUE;
extern const std::string I4;
extern const std::string INT;
extern const std::string BOOLEAN;
extern const std::string STRING;
extern const std::string DOUBLE;
extern const std::string DATE_TIME_ISO8601;
extern const std::string BASE64;
extern const std::string STRUCT;
extern const std::string MEMBER;
extern const std::string NAME;
extern const std::string ARRAY;
extern const std::string DATA;
} // namespace elements
} // namespace rpc
} // namespace aria2
#endif // D_XML_RPC_ELEMENTS_H

View File

@ -38,10 +38,12 @@
#include "common.h"
#include <string>
#include <map>
#include <vector>
namespace aria2 {
class XmlAttr;
namespace rpc {
class XmlRpcRequestParserStateMachine;
@ -50,11 +52,11 @@ class XmlRpcRequestParserState {
public:
virtual ~XmlRpcRequestParserState() {}
virtual void beginElement(XmlRpcRequestParserStateMachine* stm,
virtual void beginElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::map<std::string, std::string>& attrs)= 0;
const std::vector<XmlAttr>& attrs)= 0;
virtual void endElement(XmlRpcRequestParserStateMachine* stm,
virtual void endElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::string& characters) = 0;

View File

@ -33,11 +33,14 @@
*/
/* copyright --> */
#include "XmlRpcRequestParserStateImpl.h"
#include <cstring>
#include "XmlRpcRequestParserStateMachine.h"
#include "XmlRpcElements.h"
#include "RecoverableException.h"
#include "util.h"
#include "base64.h"
#include "ValueBase.h"
namespace aria2 {
@ -46,19 +49,19 @@ namespace rpc {
// InitialXmlRpcRequestParserState
void InitialXmlRpcRequestParserState::beginElement
(XmlRpcRequestParserStateMachine* stm,
(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::map<std::string, std::string>& attrs)
const std::vector<XmlAttr>& attrs)
{
if(name == elements::METHOD_CALL) {
stm->pushMethodCallState();
if(strcmp(name, "methodCall") == 0) {
psm->pushMethodCallState();
} else {
stm->pushUnknownElementState();
psm->pushUnknownElementState();
}
}
void InitialXmlRpcRequestParserState::endElement
(XmlRpcRequestParserStateMachine* stm,
(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::string& characters)
{}
@ -66,140 +69,140 @@ void InitialXmlRpcRequestParserState::endElement
// UnknownElementXmlRpcRequestParserState
void UnknownElementXmlRpcRequestParserState::beginElement
(XmlRpcRequestParserStateMachine* stm,
(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::map<std::string, std::string>& attrs)
const std::vector<XmlAttr>& attrs)
{
stm->pushUnknownElementState();
psm->pushUnknownElementState();
}
// MethodCallXmlRpcRequestParserState
void MethodCallXmlRpcRequestParserState::beginElement
(XmlRpcRequestParserStateMachine* stm,
(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::map<std::string, std::string>& attrs)
const std::vector<XmlAttr>& attrs)
{
if(name == elements::METHOD_NAME) {
stm->pushMethodNameState();
} else if(name == elements::A2_PARAMS) {
stm->setCurrentFrameValue(List::g());
stm->pushParamsState();
if(strcmp(name, "methodName") == 0) {
psm->pushMethodNameState();
} else if(strcmp(name, "params") == 0) {
psm->setCurrentFrameValue(List::g());
psm->pushParamsState();
} else {
stm->pushUnknownElementState();
psm->pushUnknownElementState();
}
}
// MethodNameXmlRpcRequestParserState
void MethodNameXmlRpcRequestParserState::beginElement
(XmlRpcRequestParserStateMachine* stm,
(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::map<std::string, std::string>& attrs)
const std::vector<XmlAttr>& attrs)
{
stm->pushUnknownElementState();
psm->pushUnknownElementState();
}
void MethodNameXmlRpcRequestParserState::endElement
(XmlRpcRequestParserStateMachine* stm,
(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::string& characters)
{
stm->setMethodName(characters);
psm->setMethodName(characters);
}
// ParamsXmlRpcRequestParserState
void ParamsXmlRpcRequestParserState::beginElement
(XmlRpcRequestParserStateMachine* stm,
(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::map<std::string, std::string>& attrs)
const std::vector<XmlAttr>& attrs)
{
if(name == elements::PARAM) {
stm->pushFrame();
stm->pushParamState();
if(strcmp(name, "param") == 0) {
psm->pushFrame();
psm->pushParamState();
} else {
stm->pushUnknownElementState();
psm->pushUnknownElementState();
}
}
// ParamXmlRpcRequestParserState
void ParamXmlRpcRequestParserState::beginElement
(XmlRpcRequestParserStateMachine* stm,
(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::map<std::string, std::string>& attrs)
const std::vector<XmlAttr>& attrs)
{
if(name == elements::VALUE) {
stm->pushValueState();
if(strcmp(name, "value") == 0) {
psm->pushValueState();
} else {
stm->pushUnknownElementState();
psm->pushUnknownElementState();
}
}
void ParamXmlRpcRequestParserState::endElement
(XmlRpcRequestParserStateMachine* stm,
(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::string& characters)
{
stm->popArrayFrame();
psm->popArrayFrame();
}
// ValueXmlRpcRequestParserState
void ValueXmlRpcRequestParserState::beginElement
(XmlRpcRequestParserStateMachine* stm,
(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::map<std::string, std::string>& attrs)
const std::vector<XmlAttr>& attrs)
{
if(name == elements::I4 || name == elements::INT) {
stm->pushIntState();
} else if(name == elements::STRUCT) {
stm->setCurrentFrameValue(Dict::g());
stm->pushStructState();
} else if(name == elements::ARRAY) {
stm->setCurrentFrameValue(List::g());
stm->pushArrayState();
} else if(name == elements::STRING || name == elements::DOUBLE) {
stm->pushStringState();
} else if(name == elements::BASE64) {
stm->pushBase64State();
if(strcmp(name, "i4") == 0 || strcmp(name, "int") == 0) {
psm->pushIntState();
} else if(strcmp(name, "struct") == 0) {
psm->setCurrentFrameValue(Dict::g());
psm->pushStructState();
} else if(strcmp(name, "array") == 0) {
psm->setCurrentFrameValue(List::g());
psm->pushArrayState();
} else if(strcmp(name, "string") == 0 || strcmp(name, "double") == 0) {
psm->pushStringState();
} else if(strcmp(name, "base64") == 0) {
psm->pushBase64State();
} else {
stm->pushUnknownElementState();
psm->pushUnknownElementState();
}
}
void ValueXmlRpcRequestParserState::endElement
(XmlRpcRequestParserStateMachine* stm,
(XmlRpcRequestParserStateMachine* psm,
const char* 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));
if(!psm->getCurrentFrameValue() && !characters.empty()) {
psm->setCurrentFrameValue(String::g(characters));
}
}
// IntXmlRpcRequestParserState
void IntXmlRpcRequestParserState::beginElement
(XmlRpcRequestParserStateMachine* stm,
(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::map<std::string, std::string>& attrs)
const std::vector<XmlAttr>& attrs)
{
stm->pushUnknownElementState();
psm->pushUnknownElementState();
}
void IntXmlRpcRequestParserState::endElement
(XmlRpcRequestParserStateMachine* stm,
(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::string& characters)
{
try {
int64_t value = util::parseLLInt(characters.begin(), characters.end());
stm->setCurrentFrameValue(Integer::g(value));
psm->setCurrentFrameValue(Integer::g(value));
} catch(RecoverableException& e) {
// nothing to do here: We just leave current frame value to null.
}
@ -208,135 +211,135 @@ void IntXmlRpcRequestParserState::endElement
// StringXmlRpcRequestParserState
void StringXmlRpcRequestParserState::beginElement
(XmlRpcRequestParserStateMachine* stm,
(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::map<std::string, std::string>& attrs)
const std::vector<XmlAttr>& attrs)
{
stm->pushUnknownElementState();
psm->pushUnknownElementState();
}
void StringXmlRpcRequestParserState::endElement
(XmlRpcRequestParserStateMachine* stm,
(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::string& characters)
{
stm->setCurrentFrameValue(String::g(characters));
psm->setCurrentFrameValue(String::g(characters));
}
// Base64XmlRpcRequestParserState
void Base64XmlRpcRequestParserState::beginElement
(XmlRpcRequestParserStateMachine* stm,
(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::map<std::string, std::string>& attrs)
const std::vector<XmlAttr>& attrs)
{
stm->pushUnknownElementState();
psm->pushUnknownElementState();
}
void Base64XmlRpcRequestParserState::endElement
(XmlRpcRequestParserStateMachine* stm,
(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::string& characters)
{
stm->setCurrentFrameValue
psm->setCurrentFrameValue
(String::g(base64::decode(characters.begin(), characters.end())));
}
// StructXmlRpcRequestParserState
void StructXmlRpcRequestParserState::beginElement
(XmlRpcRequestParserStateMachine* stm,
(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::map<std::string, std::string>& attrs)
const std::vector<XmlAttr>& attrs)
{
if(name == elements::MEMBER) {
stm->pushFrame();
stm->pushMemberState();
if(strcmp(name, "member") == 0) {
psm->pushFrame();
psm->pushMemberState();
} else {
stm->pushUnknownElementState();
psm->pushUnknownElementState();
}
}
// MemberXmlRpcRequestParserState
void MemberXmlRpcRequestParserState::beginElement
(XmlRpcRequestParserStateMachine* stm,
(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::map<std::string, std::string>& attrs)
const std::vector<XmlAttr>& attrs)
{
if(name == elements::NAME) {
stm->pushNameState();
} else if(name == elements::VALUE) {
stm->pushValueState();
if(strcmp(name, "name") == 0) {
psm->pushNameState();
} else if(strcmp(name, "value") == 0) {
psm->pushValueState();
} else {
stm->pushUnknownElementState();
psm->pushUnknownElementState();
}
}
void MemberXmlRpcRequestParserState::endElement
(XmlRpcRequestParserStateMachine* stm,
(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::string& characters)
{
stm->popStructFrame();
psm->popStructFrame();
}
// NameXmlRpcRequestParserState
void NameXmlRpcRequestParserState::beginElement
(XmlRpcRequestParserStateMachine* stm,
(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::map<std::string, std::string>& attrs)
const std::vector<XmlAttr>& attrs)
{
stm->pushUnknownElementState();
psm->pushUnknownElementState();
}
void NameXmlRpcRequestParserState::endElement
(XmlRpcRequestParserStateMachine* stm,
(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::string& characters)
{
stm->setCurrentFrameName(characters);
psm->setCurrentFrameName(characters);
}
// ArrayXmlRpcRequestParserState
void ArrayXmlRpcRequestParserState::beginElement
(XmlRpcRequestParserStateMachine* stm,
(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::map<std::string, std::string>& attrs)
const std::vector<XmlAttr>& attrs)
{
if(name == elements::DATA) {
stm->pushDataState();
if(strcmp(name, "data") == 0) {
psm->pushDataState();
} else {
stm->pushUnknownElementState();
psm->pushUnknownElementState();
}
}
// DataXmlRpcRequestParserState
void DataXmlRpcRequestParserState::beginElement
(XmlRpcRequestParserStateMachine* stm,
(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::map<std::string, std::string>& attrs)
const std::vector<XmlAttr>& attrs)
{
if(name == elements::VALUE) {
stm->pushFrame();
stm->pushArrayValueState();
if(strcmp(name, "value") == 0) {
psm->pushFrame();
psm->pushArrayValueState();
} else {
stm->pushUnknownElementState();
psm->pushUnknownElementState();
}
}
// ArrayValueXmlRpcRequestParserState
void ArrayValueXmlRpcRequestParserState::endElement
(XmlRpcRequestParserStateMachine* stm,
(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::string& characters)
{
ValueXmlRpcRequestParserState::endElement(stm, name, characters);
stm->popArrayFrame();
ValueXmlRpcRequestParserState::endElement(psm, name, characters);
psm->popArrayFrame();
}
} // namespace rpc

View File

@ -43,11 +43,11 @@ namespace rpc {
class InitialXmlRpcRequestParserState:public XmlRpcRequestParserState {
public:
virtual void beginElement(XmlRpcRequestParserStateMachine* stm,
virtual void beginElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::map<std::string, std::string>& attrs);
const std::vector<XmlAttr>& attrs);
virtual void endElement(XmlRpcRequestParserStateMachine* stm,
virtual void endElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::string& characters);
@ -56,11 +56,11 @@ public:
class UnknownElementXmlRpcRequestParserState:public XmlRpcRequestParserState {
public:
virtual void beginElement(XmlRpcRequestParserStateMachine* stm,
virtual void beginElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::map<std::string, std::string>& attrs);
const std::vector<XmlAttr>& attrs);
virtual void endElement(XmlRpcRequestParserStateMachine* stm,
virtual void endElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::string& characters) {}
@ -69,11 +69,11 @@ public:
class MethodCallXmlRpcRequestParserState:public XmlRpcRequestParserState {
public:
virtual void beginElement(XmlRpcRequestParserStateMachine* stm,
virtual void beginElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::map<std::string, std::string>& attrs);
const std::vector<XmlAttr>& attrs);
virtual void endElement(XmlRpcRequestParserStateMachine* stm,
virtual void endElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::string& characters) {}
@ -82,11 +82,11 @@ public:
class MethodNameXmlRpcRequestParserState:public XmlRpcRequestParserState {
public:
virtual void beginElement(XmlRpcRequestParserStateMachine* stm,
virtual void beginElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::map<std::string, std::string>& attrs);
const std::vector<XmlAttr>& attrs);
virtual void endElement(XmlRpcRequestParserStateMachine* stm,
virtual void endElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::string& characters);
@ -94,11 +94,11 @@ public:
};
class ParamsXmlRpcRequestParserState:public XmlRpcRequestParserState {
virtual void beginElement(XmlRpcRequestParserStateMachine* stm,
virtual void beginElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::map<std::string, std::string>& attrs);
const std::vector<XmlAttr>& attrs);
virtual void endElement(XmlRpcRequestParserStateMachine* stm,
virtual void endElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::string& characters) {}
@ -106,11 +106,11 @@ class ParamsXmlRpcRequestParserState:public XmlRpcRequestParserState {
};
class ParamXmlRpcRequestParserState:public XmlRpcRequestParserState {
virtual void beginElement(XmlRpcRequestParserStateMachine* stm,
virtual void beginElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::map<std::string, std::string>& attrs);
const std::vector<XmlAttr>& attrs);
virtual void endElement(XmlRpcRequestParserStateMachine* stm,
virtual void endElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::string& characters);
@ -118,11 +118,11 @@ class ParamXmlRpcRequestParserState:public XmlRpcRequestParserState {
};
class ValueXmlRpcRequestParserState:public XmlRpcRequestParserState {
virtual void beginElement(XmlRpcRequestParserStateMachine* stm,
virtual void beginElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::map<std::string, std::string>& attrs);
const std::vector<XmlAttr>& attrs);
protected:
virtual void endElement(XmlRpcRequestParserStateMachine* stm,
virtual void endElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::string& characters);
@ -130,11 +130,11 @@ protected:
};
class IntXmlRpcRequestParserState:public XmlRpcRequestParserState {
virtual void beginElement(XmlRpcRequestParserStateMachine* stm,
virtual void beginElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::map<std::string, std::string>& attrs);
const std::vector<XmlAttr>& attrs);
virtual void endElement(XmlRpcRequestParserStateMachine* stm,
virtual void endElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::string& characters);
@ -142,11 +142,11 @@ class IntXmlRpcRequestParserState:public XmlRpcRequestParserState {
};
class StringXmlRpcRequestParserState:public XmlRpcRequestParserState {
virtual void beginElement(XmlRpcRequestParserStateMachine* stm,
virtual void beginElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::map<std::string, std::string>& attrs);
const std::vector<XmlAttr>& attrs);
virtual void endElement(XmlRpcRequestParserStateMachine* stm,
virtual void endElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::string& characters);
@ -154,11 +154,11 @@ class StringXmlRpcRequestParserState:public XmlRpcRequestParserState {
};
class Base64XmlRpcRequestParserState:public XmlRpcRequestParserState {
virtual void beginElement(XmlRpcRequestParserStateMachine* stm,
virtual void beginElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::map<std::string, std::string>& attrs);
const std::vector<XmlAttr>& attrs);
virtual void endElement(XmlRpcRequestParserStateMachine* stm,
virtual void endElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::string& characters);
@ -166,11 +166,11 @@ class Base64XmlRpcRequestParserState:public XmlRpcRequestParserState {
};
class StructXmlRpcRequestParserState:public XmlRpcRequestParserState {
virtual void beginElement(XmlRpcRequestParserStateMachine* stm,
virtual void beginElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::map<std::string, std::string>& attrs);
const std::vector<XmlAttr>& attrs);
virtual void endElement(XmlRpcRequestParserStateMachine* stm,
virtual void endElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::string& characters) {}
@ -178,11 +178,11 @@ class StructXmlRpcRequestParserState:public XmlRpcRequestParserState {
};
class MemberXmlRpcRequestParserState:public XmlRpcRequestParserState {
virtual void beginElement(XmlRpcRequestParserStateMachine* stm,
virtual void beginElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::map<std::string, std::string>& attrs);
const std::vector<XmlAttr>& attrs);
virtual void endElement(XmlRpcRequestParserStateMachine* stm,
virtual void endElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::string& characters);
@ -190,11 +190,11 @@ class MemberXmlRpcRequestParserState:public XmlRpcRequestParserState {
};
class NameXmlRpcRequestParserState:public XmlRpcRequestParserState {
virtual void beginElement(XmlRpcRequestParserStateMachine* stm,
virtual void beginElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::map<std::string, std::string>& attrs);
const std::vector<XmlAttr>& attrs);
virtual void endElement(XmlRpcRequestParserStateMachine* stm,
virtual void endElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::string& characters);
@ -202,11 +202,11 @@ class NameXmlRpcRequestParserState:public XmlRpcRequestParserState {
};
class ArrayXmlRpcRequestParserState:public XmlRpcRequestParserState {
virtual void beginElement(XmlRpcRequestParserStateMachine* stm,
virtual void beginElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::map<std::string, std::string>& attrs);
const std::vector<XmlAttr>& attrs);
virtual void endElement(XmlRpcRequestParserStateMachine* stm,
virtual void endElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::string& characters) {}
@ -214,11 +214,11 @@ class ArrayXmlRpcRequestParserState:public XmlRpcRequestParserState {
};
class DataXmlRpcRequestParserState:public XmlRpcRequestParserState {
virtual void beginElement(XmlRpcRequestParserStateMachine* stm,
virtual void beginElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::map<std::string, std::string>& attrs);
const std::vector<XmlAttr>& attrs);
virtual void endElement(XmlRpcRequestParserStateMachine* stm,
virtual void endElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::string& characters) {}
@ -226,7 +226,7 @@ class DataXmlRpcRequestParserState:public XmlRpcRequestParserState {
};
class ArrayValueXmlRpcRequestParserState:public ValueXmlRpcRequestParserState {
virtual void endElement(XmlRpcRequestParserStateMachine* stm,
virtual void endElement(XmlRpcRequestParserStateMachine* psm,
const char* name,
const std::string& characters);
};

View File

@ -2,7 +2,7 @@
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2009 Tatsuhiro Tsujikawa
* Copyright (C) 2011 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -33,79 +33,67 @@
*/
/* copyright --> */
#include "XmlRpcRequestParserStateMachine.h"
#include "XmlRpcRequestParserController.h"
#include "XmlRpcRequestParserStateImpl.h"
namespace aria2 {
namespace rpc {
namespace {
InitialXmlRpcRequestParserState*
XmlRpcRequestParserStateMachine::initialState_ =
new InitialXmlRpcRequestParserState();
initialState = new InitialXmlRpcRequestParserState();
UnknownElementXmlRpcRequestParserState*
XmlRpcRequestParserStateMachine::unknownElementState_ =
new UnknownElementXmlRpcRequestParserState();
unknownElementState = new UnknownElementXmlRpcRequestParserState();
MethodCallXmlRpcRequestParserState*
XmlRpcRequestParserStateMachine::methodCallState_ =
new MethodCallXmlRpcRequestParserState();
methodCallState = new MethodCallXmlRpcRequestParserState();
MethodNameXmlRpcRequestParserState*
XmlRpcRequestParserStateMachine::methodNameState_ =
new MethodNameXmlRpcRequestParserState();
methodNameState = new MethodNameXmlRpcRequestParserState();
ParamsXmlRpcRequestParserState*
XmlRpcRequestParserStateMachine::paramsState_ =
new ParamsXmlRpcRequestParserState();
paramsState = new ParamsXmlRpcRequestParserState();
ParamXmlRpcRequestParserState*
XmlRpcRequestParserStateMachine::paramState_ =
new ParamXmlRpcRequestParserState();
paramState = new ParamXmlRpcRequestParserState();
ValueXmlRpcRequestParserState*
XmlRpcRequestParserStateMachine::valueState_ =
new ValueXmlRpcRequestParserState();
valueState = new ValueXmlRpcRequestParserState();
IntXmlRpcRequestParserState*
XmlRpcRequestParserStateMachine::intState_ =
new IntXmlRpcRequestParserState();
intState = new IntXmlRpcRequestParserState();
StringXmlRpcRequestParserState*
XmlRpcRequestParserStateMachine::stringState_ =
new StringXmlRpcRequestParserState();
stringState = new StringXmlRpcRequestParserState();
Base64XmlRpcRequestParserState*
XmlRpcRequestParserStateMachine::base64State_ =
new Base64XmlRpcRequestParserState();
base64State = new Base64XmlRpcRequestParserState();
StructXmlRpcRequestParserState*
XmlRpcRequestParserStateMachine::structState_ =
new StructXmlRpcRequestParserState();
structState = new StructXmlRpcRequestParserState();
MemberXmlRpcRequestParserState*
XmlRpcRequestParserStateMachine::memberState_ =
new MemberXmlRpcRequestParserState();
memberState = new MemberXmlRpcRequestParserState();
NameXmlRpcRequestParserState*
XmlRpcRequestParserStateMachine::nameState_ =
new NameXmlRpcRequestParserState();
nameState = new NameXmlRpcRequestParserState();
ArrayXmlRpcRequestParserState*
XmlRpcRequestParserStateMachine::arrayState_ =
new ArrayXmlRpcRequestParserState();
arrayState = new ArrayXmlRpcRequestParserState();
DataXmlRpcRequestParserState*
XmlRpcRequestParserStateMachine::dataState_ =
new DataXmlRpcRequestParserState();
dataState = new DataXmlRpcRequestParserState();
ArrayValueXmlRpcRequestParserState*
XmlRpcRequestParserStateMachine::arrayValueState_ =
new ArrayValueXmlRpcRequestParserState();
arrayValueState = new ArrayValueXmlRpcRequestParserState();
} // namespace
XmlRpcRequestParserStateMachine::XmlRpcRequestParserStateMachine():
controller_(new XmlRpcRequestParserController())
{
stateStack_.push(initialState_);
stateStack_.push(initialState);
}
XmlRpcRequestParserStateMachine::~XmlRpcRequestParserStateMachine()
@ -113,6 +101,154 @@ XmlRpcRequestParserStateMachine::~XmlRpcRequestParserStateMachine()
delete controller_;
}
bool XmlRpcRequestParserStateMachine::needsCharactersBuffering() const
{
return stateStack_.top()->needsCharactersBuffering();
}
bool XmlRpcRequestParserStateMachine::finished() const
{
return stateStack_.top() == initialState;
}
void XmlRpcRequestParserStateMachine::beginElement
(const char* localname,
const char* prefix,
const char* nsUri,
const std::vector<XmlAttr>& attrs)
{
stateStack_.top()->beginElement(this, localname, attrs);
}
void XmlRpcRequestParserStateMachine::endElement
(const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters)
{
stateStack_.top()->endElement(this, localname, characters);
stateStack_.pop();
}
void XmlRpcRequestParserStateMachine::setMethodName
(const std::string& methodName)
{
controller_->setMethodName(methodName);
}
const std::string& XmlRpcRequestParserStateMachine::getMethodName() const
{
return controller_->getMethodName();
}
void XmlRpcRequestParserStateMachine::popArrayFrame()
{
controller_->popArrayFrame();
}
void XmlRpcRequestParserStateMachine::popStructFrame()
{
controller_->popStructFrame();
}
void XmlRpcRequestParserStateMachine::pushFrame()
{
controller_->pushFrame();
}
void XmlRpcRequestParserStateMachine::setCurrentFrameValue
(const SharedHandle<ValueBase>& value)
{
controller_->setCurrentFrameValue(value);
}
const SharedHandle<ValueBase>&
XmlRpcRequestParserStateMachine::getCurrentFrameValue() const
{
return controller_->getCurrentFrameValue();
}
void XmlRpcRequestParserStateMachine::setCurrentFrameName
(const std::string& name)
{
controller_->setCurrentFrameName(name);
}
void XmlRpcRequestParserStateMachine::pushUnknownElementState()
{
stateStack_.push(unknownElementState);
}
void XmlRpcRequestParserStateMachine::pushMethodCallState()
{
stateStack_.push(methodCallState);
}
void XmlRpcRequestParserStateMachine::pushMethodNameState()
{
stateStack_.push(methodNameState);
}
void XmlRpcRequestParserStateMachine::pushParamsState()
{
stateStack_.push(paramsState);
}
void XmlRpcRequestParserStateMachine::pushParamState()
{
stateStack_.push(paramState);
}
void XmlRpcRequestParserStateMachine::pushValueState()
{
stateStack_.push(valueState);
}
void XmlRpcRequestParserStateMachine::pushIntState()
{
stateStack_.push(intState);
}
void XmlRpcRequestParserStateMachine::pushStringState()
{
stateStack_.push(stringState);
}
void XmlRpcRequestParserStateMachine::pushBase64State()
{
stateStack_.push(base64State);
}
void XmlRpcRequestParserStateMachine::pushStructState()
{
stateStack_.push(structState);
}
void XmlRpcRequestParserStateMachine::pushMemberState()
{
stateStack_.push(memberState);
}
void XmlRpcRequestParserStateMachine::pushNameState()
{
stateStack_.push(nameState);
}
void XmlRpcRequestParserStateMachine::pushArrayState()
{
stateStack_.push(arrayState);
}
void XmlRpcRequestParserStateMachine::pushDataState()
{
stateStack_.push(dataState);
}
void XmlRpcRequestParserStateMachine::pushArrayValueState()
{
stateStack_.push(arrayValueState);
}
} // namespace rpc
} // namespace aria2

View File

@ -2,7 +2,7 @@
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2009 Tatsuhiro Tsujikawa
* Copyright (C) 2011 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -35,134 +35,69 @@
#ifndef D_XML_RPC_REQUEST_PARSER_STATE_MACHINE_H
#define D_XML_RPC_REQUEST_PARSER_STATE_MACHINE_H
#include "common.h"
#include "ParserStateMachine.h"
#include <string>
#include <map>
#include <stack>
#include "XmlRpcRequestParserController.h"
#include "XmlRpcRequestParserStateImpl.h"
#include "ValueBase.h"
#include "SharedHandle.h"
namespace aria2 {
class ValueBase;
namespace rpc {
class XmlRpcRequestParserStateMachine {
private:
XmlRpcRequestParserController* controller_;
class XmlRpcRequestParserController;
class XmlRpcRequestParserState;
std::stack<XmlRpcRequestParserState*> stateStack_;
static InitialXmlRpcRequestParserState* initialState_;
static MethodCallXmlRpcRequestParserState* methodCallState_;
static MethodNameXmlRpcRequestParserState* methodNameState_;
static ParamsXmlRpcRequestParserState* paramsState_;
static ParamXmlRpcRequestParserState* paramState_;
static ValueXmlRpcRequestParserState* valueState_;
static IntXmlRpcRequestParserState* intState_;
static StringXmlRpcRequestParserState* stringState_;
static Base64XmlRpcRequestParserState* base64State_;
static StructXmlRpcRequestParserState* structState_;
static MemberXmlRpcRequestParserState* memberState_;
static NameXmlRpcRequestParserState* nameState_;
static ArrayXmlRpcRequestParserState* arrayState_;
static DataXmlRpcRequestParserState* dataState_;
static ArrayValueXmlRpcRequestParserState* arrayValueState_;
static UnknownElementXmlRpcRequestParserState* unknownElementState_;
class XmlRpcRequestParserStateMachine : public ParserStateMachine {
public:
XmlRpcRequestParserStateMachine();
virtual ~XmlRpcRequestParserStateMachine();
~XmlRpcRequestParserStateMachine();
virtual bool needsCharactersBuffering() const;
virtual bool finished() const;
void beginElement(const char* name,
const std::map<std::string, std::string>& attrs)
{
stateStack_.top()->beginElement(this, name, attrs);
}
void endElement(const char* name, const std::string& characters)
{
stateStack_.top()->endElement(this, name, characters);
stateStack_.pop();
}
virtual void beginElement
(const char* localname,
const char* prefix,
const char* nsUri,
const std::vector<XmlAttr>& attrs);
void setMethodName(const std::string& methodName)
{
controller_->setMethodName(methodName);
}
virtual void endElement
(const char* localname,
const char* prefix,
const char* nsUri,
const std::string& characters);
const std::string& getMethodName() const
{
return controller_->getMethodName();
}
void setMethodName(const std::string& methodName);
const std::string& getMethodName() const;
void popArrayFrame();
void popStructFrame();
void pushFrame();
void setCurrentFrameValue(const SharedHandle<ValueBase>& value);
const SharedHandle<ValueBase>& getCurrentFrameValue() const;
void setCurrentFrameName(const std::string& name);
void popArrayFrame()
{
controller_->popArrayFrame();
}
void popStructFrame()
{
controller_->popStructFrame();
}
void pushFrame()
{
controller_->pushFrame();
}
void setCurrentFrameValue(const SharedHandle<ValueBase>& value)
{
controller_->setCurrentFrameValue(value);
}
const SharedHandle<ValueBase>& getCurrentFrameValue() const
{
return controller_->getCurrentFrameValue();
}
void setCurrentFrameName(const std::string& name)
{
controller_->setCurrentFrameName(name);
}
bool needsCharactersBuffering() const
{
return stateStack_.top()->needsCharactersBuffering();
}
void pushUnknownElementState() { stateStack_.push(unknownElementState_); }
void pushMethodCallState() { stateStack_.push(methodCallState_); }
void pushMethodNameState() { stateStack_.push(methodNameState_); }
void pushParamsState() { stateStack_.push(paramsState_); }
void pushParamState() { stateStack_.push(paramState_); }
void pushValueState() { stateStack_.push(valueState_); }
void pushIntState() { stateStack_.push(intState_); }
void pushStringState() { stateStack_.push(stringState_); }
void pushBase64State() { stateStack_.push(base64State_); }
void pushStructState() { stateStack_.push(structState_); }
void pushMemberState() { stateStack_.push(memberState_); }
void pushNameState() { stateStack_.push(nameState_); }
void pushArrayState() { stateStack_.push(arrayState_); }
void pushDataState() { stateStack_.push(dataState_); }
void pushArrayValueState() { stateStack_.push(arrayValueState_); }
void pushUnknownElementState();
void pushMethodCallState();
void pushMethodNameState();
void pushParamsState();
void pushParamState();
void pushValueState();
void pushIntState();
void pushStringState();
void pushBase64State();
void pushStructState();
void pushMemberState();
void pushNameState();
void pushArrayState();
void pushDataState();
void pushArrayValueState();
private:
std::stack<XmlRpcRequestParserState*> stateStack_;
XmlRpcRequestParserController* controller_;
};
} // namespace rpc

View File

@ -2,7 +2,7 @@
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2009 Tatsuhiro Tsujikawa
* Copyright (C) 2011 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -32,31 +32,32 @@
* files in the program, then also delete it here.
*/
/* copyright --> */
#ifndef D_EXPAT_XML_RPC_REQUEST_PROCESSOR_H
#define D_EXPAT_XML_RPC_REQUEST_PROCESSOR_H
#include "common.h"
#include <string>
#include "SharedHandle.h"
#include "rpc_helper.h"
#include "XmlParser.h"
#include "RpcRequest.h"
#include "XmlRpcRequestParserStateMachine.h"
#include "message.h"
#include "DlAbortEx.h"
namespace aria2 {
namespace rpc {
class XmlRpcRequestParserStateMachine;
class XmlRpcRequestProcessor {
private:
SharedHandle<XmlRpcRequestParserStateMachine> stm_;
public:
RpcRequest parseMemory(const std::string& xml);
};
#ifdef ENABLE_XML_RPC
RpcRequest xmlParseMemory(const char* xml, size_t size)
{
XmlRpcRequestParserStateMachine psm;
if(!XmlParser(&psm).parseMemory(xml, size)) {
throw DL_ABORT_EX(MSG_CANNOT_PARSE_XML_RPC_REQUEST);
}
if(!downcast<List>(psm.getCurrentFrameValue())) {
throw DL_ABORT_EX("Bad XML-RPC parameter list");
}
return RpcRequest(psm.getMethodName(),
static_pointer_cast<List>(psm.getCurrentFrameValue()));
}
#endif // ENABLE_XML_RPC
} // namespace rpc
} // namespace aria2
#endif // D_EXPAT_XML_RPC_REQUEST_PROCESSOR_H

View File

@ -2,7 +2,7 @@
/*
* aria2 - The high speed download utility
*
* Copyright (C) 2009 Tatsuhiro Tsujikawa
* Copyright (C) 2011 Tatsuhiro Tsujikawa
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -32,15 +32,25 @@
* files in the program, then also delete it here.
*/
/* copyright --> */
#ifndef D_XML_RPC_REQUEST_PROCESSOR_H
#define D_XML_RPC_REQUEST_PROCESSOR_H
#ifndef D_RPC_HELPER_H
#define D_RPC_HELPER_H
#include "common.h"
#ifdef HAVE_LIBXML2
# include "Xml2XmlRpcRequestProcessor.h"
#elif HAVE_LIBEXPAT
# include "ExpatXmlRpcRequestProcessor.h"
#endif // HAVE_LIBEXPAT
#include <cstdlib>
#endif // D_XML_RPC_REQUEST_PROCESSOR_H
namespace aria2 {
namespace rpc {
class RpcRequest;
#ifdef ENABLE_XML_RPC
RpcRequest xmlParseMemory(const char* xml, size_t size);
#endif // ENABLE_XML_RPC
} // namespace rpc
} // namespace aria2
#endif // D_RPC_HELPER_H

View File

@ -79,11 +79,11 @@ aria2c_SOURCES = AllTest.cc\
BufferedFileTest.cc\
GeomStreamPieceSelectorTest.cc\
SegListTest.cc\
ParamedStringTest.cc
ParamedStringTest.cc\
RpcHelperTest.cc
if ENABLE_XML_RPC
aria2c_SOURCES += XmlRpcRequestParserControllerTest.cc\
XmlRpcRequestProcessorTest.cc
aria2c_SOURCES += XmlRpcRequestParserControllerTest.cc
endif # ENABLE_XML_RPC
if HAVE_SOME_FALLOCATE

187
test/RpcHelperTest.cc Normal file
View File

@ -0,0 +1,187 @@
#include "rpc_helper.h"
#include <cppunit/extensions/HelperMacros.h>
#include "RpcRequest.h"
#include "RecoverableException.h"
#ifdef ENABLE_XML_RPC
# include "XmlRpcRequestParserStateMachine.h"
#endif // ENABLE_XML_RPC
namespace aria2 {
namespace rpc {
class RpcHelperTest:public CppUnit::TestFixture {
CPPUNIT_TEST_SUITE(RpcHelperTest);
#ifdef ENABLE_XML_RPC
CPPUNIT_TEST(testParseMemory);
CPPUNIT_TEST(testParseMemory_shouldFail);
CPPUNIT_TEST(testParseMemory_withoutStringTag);
#endif // ENABLE_XML_RPC
CPPUNIT_TEST_SUITE_END();
public:
void setUp() {}
void tearDown() {}
#ifdef ENABLE_XML_RPC
void testParseMemory();
void testParseMemory_shouldFail();
void testParseMemory_withoutStringTag();
#endif // ENABLE_XML_RPC
};
CPPUNIT_TEST_SUITE_REGISTRATION(RpcHelperTest);
#ifdef ENABLE_XML_RPC
void RpcHelperTest::testParseMemory()
{
std::string s =
"<?xml version=\"1.0\"?>"
"<methodCall>"
" <methodName>aria2.addURI</methodName>"
" <params>"
" <param>"
" <value><i4>100</i4></value>"
" </param>"
" <param>"
" <value>"
" <struct>"
" <member>"
" <name>max-count</name>"
" <value><i4>65535</i4></value>"
" </member>"
" <member>"
" <name>seed-ratio</name>"
" <value><double>0.99</double></value>"
" </member>"
" </struct>"
" </value>"
" </param>"
" <param>"
" <value>"
" <array>"
" <data>"
" <value><string>pudding</string></value>"
" <value><base64>aGVsbG8gd29ybGQ=</base64></value>"
" </data>"
" </array>"
" </value>"
" </param>"
" </params>"
"</methodCall>";
RpcRequest req = xmlParseMemory(s.c_str(), s.size());
CPPUNIT_ASSERT_EQUAL(std::string("aria2.addURI"), req.methodName);
CPPUNIT_ASSERT_EQUAL((size_t)3, req.params->size());
CPPUNIT_ASSERT_EQUAL((Integer::ValueType)100,
downcast<Integer>(req.params->get(0))->i());
const Dict* dict = downcast<Dict>(req.params->get(1));
CPPUNIT_ASSERT_EQUAL((Integer::ValueType)65535,
downcast<Integer>(dict->get("max-count"))->i());
// Current implementation handles double as string.
CPPUNIT_ASSERT_EQUAL(std::string("0.99"),
downcast<String>(dict->get("seed-ratio"))->s());
const List* list = downcast<List>(req.params->get(2));
CPPUNIT_ASSERT_EQUAL(std::string("pudding"), downcast<String>(list->get(0))->s());
CPPUNIT_ASSERT_EQUAL(std::string("hello world"), downcast<String>(list->get(1))->s());
}
void RpcHelperTest::testParseMemory_shouldFail()
{
try {
std::string s =
"<methodCall>"
" <methodName>aria2.addURI</methodName>"
" <params>"
" <param>"
" <value><i4>100</i4></value>"
" </param>";
xmlParseMemory(s.c_str(), s.size());
CPPUNIT_FAIL("exception must be thrown.");
} catch(RecoverableException& e) {
// success
}
{
std::string s =
"<methodCall>"
" <methodName>aria2.addURI</methodName>"
" <params>"
" </params>"
"</methodCall>";
RpcRequest req = xmlParseMemory(s.c_str(), s.size());
CPPUNIT_ASSERT(req.params);
}
try {
std::string s =
"<methodCall>"
" <methodName>aria2.addURI</methodName>"
"</methodCall>";
xmlParseMemory(s.c_str(), s.size());
CPPUNIT_FAIL("exception must be thrown.");
} catch(RecoverableException& e) {
// success
}
}
void RpcHelperTest::testParseMemory_withoutStringTag()
{
std::string s =
"<?xml version=\"1.0\"?>"
"<methodCall>"
" <methodName>aria2.addUri</methodName>"
" <params>"
" <param>"
" <value>http://aria2.sourceforge.net</value>"
" </param>"
" <param>"
" <value>http://aria2.<foo/>sourceforge.net</value>"
" </param>"
" <param>"
" <value>"
" <struct>"
" <member>"
" <name>hello</name>"
" <value>world</value>"
" </member>"
" </struct>"
" </value>"
" </param>"
" <param>"
" <value>"
" <array>"
" <data>"
" <value>apple</value>"
" <value>banana</value>"
" <value><string>lemon</string>peanuts</value>"
" </data>"
" </array>"
" </value>"
" </param>"
" </params>"
"</methodCall>";
RpcRequest req =
xmlParseMemory(s.c_str(), s.size());
CPPUNIT_ASSERT_EQUAL((size_t)4, req.params->size());
CPPUNIT_ASSERT_EQUAL(std::string("http://aria2.sourceforge.net"),
downcast<String>(req.params->get(0))->s());
CPPUNIT_ASSERT_EQUAL(std::string("http://aria2.sourceforge.net"),
downcast<String>(req.params->get(1))->s());
const Dict* dict = downcast<Dict>(req.params->get(2));
CPPUNIT_ASSERT_EQUAL(std::string("world"),
downcast<String>(dict->get("hello"))->s());
const List* list = downcast<List>(req.params->get(3));
CPPUNIT_ASSERT_EQUAL(std::string("apple"), downcast<String>(list->get(0))->s());
CPPUNIT_ASSERT_EQUAL(std::string("banana"), downcast<String>(list->get(1))->s());
CPPUNIT_ASSERT_EQUAL(std::string("lemon"), downcast<String>(list->get(2))->s());
}
#endif // ENABLE_XML_RPC
} // namespace rpc
} // namespace aria2

View File

@ -1,173 +0,0 @@
#include "XmlRpcRequestProcessor.h"
#include <cppunit/extensions/HelperMacros.h>
#include "XmlRpcRequestParserStateMachine.h"
#include "RecoverableException.h"
namespace aria2 {
namespace rpc {
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() {}
void tearDown() {}
void testParseMemory();
void testParseMemory_shouldFail();
void testParseMemory_withoutStringTag();
};
CPPUNIT_TEST_SUITE_REGISTRATION(XmlRpcRequestProcessorTest);
void XmlRpcRequestProcessorTest::testParseMemory()
{
XmlRpcRequestProcessor proc;
RpcRequest req =
proc.parseMemory("<?xml version=\"1.0\"?>"
"<methodCall>"
" <methodName>aria2.addURI</methodName>"
" <params>"
" <param>"
" <value><i4>100</i4></value>"
" </param>"
" <param>"
" <value>"
" <struct>"
" <member>"
" <name>max-count</name>"
" <value><i4>65535</i4></value>"
" </member>"
" <member>"
" <name>seed-ratio</name>"
" <value><double>0.99</double></value>"
" </member>"
" </struct>"
" </value>"
" </param>"
" <param>"
" <value>"
" <array>"
" <data>"
" <value><string>pudding</string></value>"
" <value><base64>aGVsbG8gd29ybGQ=</base64></value>"
" </data>"
" </array>"
" </value>"
" </param>"
" </params>"
"</methodCall>");
CPPUNIT_ASSERT_EQUAL(std::string("aria2.addURI"), req.methodName);
CPPUNIT_ASSERT_EQUAL((size_t)3, req.params->size());
CPPUNIT_ASSERT_EQUAL((Integer::ValueType)100,
downcast<Integer>(req.params->get(0))->i());
const Dict* dict = downcast<Dict>(req.params->get(1));
CPPUNIT_ASSERT_EQUAL((Integer::ValueType)65535,
downcast<Integer>(dict->get("max-count"))->i());
// Current implementation handles double as string.
CPPUNIT_ASSERT_EQUAL(std::string("0.99"),
downcast<String>(dict->get("seed-ratio"))->s());
const List* list = downcast<List>(req.params->get(2));
CPPUNIT_ASSERT_EQUAL(std::string("pudding"), downcast<String>(list->get(0))->s());
CPPUNIT_ASSERT_EQUAL(std::string("hello world"), downcast<String>(list->get(1))->s());
}
void XmlRpcRequestProcessorTest::testParseMemory_shouldFail()
{
XmlRpcRequestProcessor proc;
try {
proc.parseMemory("<methodCall>"
" <methodName>aria2.addURI</methodName>"
" <params>"
" <param>"
" <value><i4>100</i4></value>"
" </param>");
CPPUNIT_FAIL("exception must be thrown.");
} catch(RecoverableException& e) {
// success
}
{
RpcRequest req =
proc.parseMemory("<methodCall>"
" <methodName>aria2.addURI</methodName>"
" <params>"
" </params>"
"</methodCall>");
CPPUNIT_ASSERT(req.params);
}
try {
RpcRequest req =
proc.parseMemory("<methodCall>"
" <methodName>aria2.addURI</methodName>"
"</methodCall>");
CPPUNIT_FAIL("exception must be thrown.");
} catch(RecoverableException& e) {
// success
}
}
void XmlRpcRequestProcessorTest::testParseMemory_withoutStringTag()
{
XmlRpcRequestProcessor proc;
RpcRequest req =
proc.parseMemory("<?xml version=\"1.0\"?>"
"<methodCall>"
" <methodName>aria2.addUri</methodName>"
" <params>"
" <param>"
" <value>http://aria2.sourceforge.net</value>"
" </param>"
" <param>"
" <value>http://aria2.<foo/>sourceforge.net</value>"
" </param>"
" <param>"
" <value>"
" <struct>"
" <member>"
" <name>hello</name>"
" <value>world</value>"
" </member>"
" </struct>"
" </value>"
" </param>"
" <param>"
" <value>"
" <array>"
" <data>"
" <value>apple</value>"
" <value>banana</value>"
" <value><string>lemon</string>peanuts</value>"
" </data>"
" </array>"
" </value>"
" </param>"
" </params>"
"</methodCall>");
CPPUNIT_ASSERT_EQUAL((size_t)4, req.params->size());
CPPUNIT_ASSERT_EQUAL(std::string("http://aria2.sourceforge.net"),
downcast<String>(req.params->get(0))->s());
CPPUNIT_ASSERT_EQUAL(std::string("http://aria2.sourceforge.net"),
downcast<String>(req.params->get(1))->s());
const Dict* dict = downcast<Dict>(req.params->get(2));
CPPUNIT_ASSERT_EQUAL(std::string("world"),
downcast<String>(dict->get("hello"))->s());
const List* list = downcast<List>(req.params->get(3));
CPPUNIT_ASSERT_EQUAL(std::string("apple"), downcast<String>(list->get(0))->s());
CPPUNIT_ASSERT_EQUAL(std::string("banana"), downcast<String>(list->get(1))->s());
CPPUNIT_ASSERT_EQUAL(std::string("lemon"), downcast<String>(list->get(2))->s());
}
} // namespace rpc
} // namespace aria2