/* */ #include "RpcResponse.h" #include #include #include "util.h" #include "json.h" #ifdef HAVE_ZLIB # include "GZipEncoder.h" #endif // HAVE_ZLIB namespace aria2 { namespace rpc { namespace { template void encodeValue(const ValueBase* value, OutputStream& o) { class XmlValueBaseVisitor:public ValueBaseVisitor { private: OutputStream& o_; public: XmlValueBaseVisitor(OutputStream& o):o_(o) {} virtual ~XmlValueBaseVisitor() {} virtual void visit(const String& v) CXX11_OVERRIDE { o_ << "" << util::htmlEscape(v.s()) << ""; } virtual void visit(const Integer& v) CXX11_OVERRIDE { o_ << "" << v.i() << ""; } virtual void visit(const Bool& boolValue) CXX11_OVERRIDE {} virtual void visit(const Null& nullValue) CXX11_OVERRIDE {} virtual void visit(const List& v) CXX11_OVERRIDE { o_ << ""; for(const auto& e: v) { e->accept(*this); } o_ << ""; } virtual void visit(const Dict& v) CXX11_OVERRIDE { o_ << ""; for(const auto& e: v) { o_ << "" << util::htmlEscape(e.first) << ""; e.second->accept(*this); o_ << ""; } o_ << ""; } }; XmlValueBaseVisitor visitor(o); value->accept(visitor); } } // namespace namespace { template std::string encodeAll (OutputStream& o, int code, const ValueBase* param) { o << "" << ""; if(code == 0) { o << "" << ""; encodeValue(param, o); o << "" << ""; } else { o << ""; encodeValue(param, o); o << ""; } o << ""; return o.str(); } } // namespace RpcResponse::RpcResponse (int code, std::unique_ptr param, std::unique_ptr id) : code{code}, param{std::move(param)}, id{std::move(id)} {} std::string toXml(const RpcResponse& res, bool gzip) { if(gzip) { #ifdef HAVE_ZLIB GZipEncoder o; o.init(); return encodeAll(o, res.code, res.param.get()); #else // !HAVE_ZLIB abort(); #endif // !HAVE_ZLIB } else { std::stringstream o; return encodeAll(o, res.code, res.param.get()); } } namespace { template OutputStream& encodeJsonAll (OutputStream& o, int code, const ValueBase* param, const ValueBase* id, const std::string& callback = A2STR::NIL) { if(!callback.empty()) { o << callback << "("; } o << "{\"id\":"; json::encode(o, id); o << ",\"jsonrpc\":\"2.0\","; if(code == 0) { o << "\"result\":"; } else { o << "\"error\":"; } json::encode(o, param); o << "}"; if(!callback.empty()) { o << ")"; } return o; } } // namespace std::string toJson (const RpcResponse& res, const std::string& callback, bool gzip) { if(gzip) { #ifdef HAVE_ZLIB GZipEncoder o; o.init(); return encodeJsonAll(o, res.code, res.param.get(), res.id.get(), callback).str(); #else // !HAVE_ZLIB abort(); #endif // !HAVE_ZLIB } else { std::stringstream o; return encodeJsonAll(o, res.code, res.param.get(), res.id.get(), callback).str(); } } namespace { template OutputStream& encodeJsonBatchAll (OutputStream& o, const std::vector& results, const std::string& callback) { if(!callback.empty()) { o << callback << "("; } o << "["; if(!results.empty()) { encodeJsonAll(o, results[0].code, results[0].param.get(), results[0].id.get()); } for(auto i = std::begin(results)+1, eoi = std::end(results); i != eoi; ++i) { o << ","; encodeJsonAll(o, (*i).code, (*i).param.get(), (*i).id.get()); } o << "]"; if(!callback.empty()) { o << ")"; } return o; } } // namespace std::string toJsonBatch (const std::vector& results, const std::string& callback, bool gzip) { if(gzip) { #ifdef HAVE_ZLIB GZipEncoder o; o.init(); return encodeJsonBatchAll(o, results, callback).str(); #else // !HAVE_ZLIB abort(); #endif // !HAVE_ZLIB } else { std::stringstream o; return encodeJsonBatchAll(o, results, callback).str(); } } } // namespace rpc } // namespace aria2