/* */ #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, RpcResponse::authorization_t authorized, std::unique_ptr param, std::unique_ptr id) : param{std::move(param)}, id{std::move(id)}, code{code}, authorized{authorized} { } 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