Changeset - 19106c7ec482
[Not reviewed]
36 17 0
Vitaly Takmazov - 8 years ago 2018-03-23 12:28:26
vitalyster@gmail.com
Switch to jsoncpp
53 files changed with 218 insertions and 16602 deletions:
0 comments (0 inline, 0 general)
CMakeLists.txt
Show inline comments
 
@@ -169,12 +169,16 @@ if (NOT PROTOBUF_FOUND AND PROTOBUF_INCLUDE_DIR AND PROTOBUF_LIBRARY)
 
	else()
 
		set(PROTOBUF_PROTOC_EXECUTABLE protoc)
 
	endif()
 
	message(STATUS "Using protobuf: ${PROTOBUF_INCLUDE_DIRS} ${PROTOBUF_LIBRARY}")
 
endif()
 

	
 
find_package(PkgConfig REQUIRED)
 
pkg_check_modules(JSONCPP jsoncpp)
 
include_directories(${JSONCPP_INCLUDE_DIRS})
 

	
 
if (WIN32)
 
	add_definitions(-DSWIFTEN_STATIC=1)
 
	ADD_DEFINITIONS(-D_WIN32_WINNT=0x0600)
 
	ADD_DEFINITIONS(-DWIN32_LEAN_AND_MEAN)
 
	ADD_DEFINITIONS(-DBOOST_USE_WINDOWS_H)
 
	ADD_DEFINITIONS(-D_UNICODE)
include/rapidjson/allocators.h
Show inline comments
 
deleted file
include/rapidjson/cursorstreamwrapper.h
Show inline comments
 
deleted file
include/rapidjson/document.h
Show inline comments
 
deleted file
include/rapidjson/encodedstream.h
Show inline comments
 
deleted file
include/rapidjson/encodings.h
Show inline comments
 
deleted file
include/rapidjson/error/en.h
Show inline comments
 
deleted file
include/rapidjson/error/error.h
Show inline comments
 
deleted file
include/rapidjson/filereadstream.h
Show inline comments
 
deleted file
include/rapidjson/filewritestream.h
Show inline comments
 
deleted file
include/rapidjson/fwd.h
Show inline comments
 
deleted file
include/rapidjson/internal/biginteger.h
Show inline comments
 
deleted file
include/rapidjson/internal/diyfp.h
Show inline comments
 
deleted file
include/rapidjson/internal/dtoa.h
Show inline comments
 
deleted file
include/rapidjson/internal/ieee754.h
Show inline comments
 
deleted file
include/rapidjson/internal/itoa.h
Show inline comments
 
deleted file
include/rapidjson/internal/meta.h
Show inline comments
 
deleted file
include/rapidjson/internal/pow10.h
Show inline comments
 
deleted file
include/rapidjson/internal/regex.h
Show inline comments
 
deleted file
include/rapidjson/internal/stack.h
Show inline comments
 
deleted file
include/rapidjson/internal/strfunc.h
Show inline comments
 
deleted file
include/rapidjson/internal/strtod.h
Show inline comments
 
deleted file
include/rapidjson/internal/swap.h
Show inline comments
 
deleted file
include/rapidjson/istreamwrapper.h
Show inline comments
 
deleted file
include/rapidjson/memorybuffer.h
Show inline comments
 
deleted file
include/rapidjson/memorystream.h
Show inline comments
 
deleted file
include/rapidjson/msinttypes/inttypes.h
Show inline comments
 
deleted file
include/rapidjson/msinttypes/stdint.h
Show inline comments
 
deleted file
include/rapidjson/ostreamwrapper.h
Show inline comments
 
deleted file
include/rapidjson/pointer.h
Show inline comments
 
deleted file
include/rapidjson/prettywriter.h
Show inline comments
 
deleted file
include/rapidjson/rapidjson.h
Show inline comments
 
deleted file
include/rapidjson/reader.h
Show inline comments
 
deleted file
include/rapidjson/schema.h
Show inline comments
 
deleted file
include/rapidjson/stream.h
Show inline comments
 
deleted file
include/rapidjson/stringbuffer.h
Show inline comments
 
deleted file
include/rapidjson/writer.h
Show inline comments
 
deleted file
include/transport/HTTPRequest.h
Show inline comments
 
@@ -4,31 +4,31 @@
 
#include "curl/curl.h"
 
#include "transport/Logging.h"
 
#include "transport/ThreadPool.h"
 
#include <iostream>
 
#include <sstream>
 
#include <string.h>
 
#include "rapidjson/document.h"
 
#include <json/json.h>
 

	
 
#include <Swiften/SwiftenCompat.h>
 

	
 
namespace Transport {
 

	
 
class HTTPRequest : public Thread {
 
	public:
 
		typedef enum { Get } Type;
 
		typedef boost::function< void (HTTPRequest *, bool, rapidjson::Document &json, const std::string &data) > Callback;
 
		typedef boost::function< void (HTTPRequest *, bool, Json::Value &json, const std::string &data) > Callback;
 

	
 
		HTTPRequest(ThreadPool *tp, Type type, const std::string &url, Callback callback);
 
		HTTPRequest(Type type, const std::string &url);
 

	
 
		virtual ~HTTPRequest();
 

	
 
		void setProxy(std::string, std::string, std::string, std::string);
 
		bool execute();
 
		bool execute(rapidjson::Document &json);
 
		bool execute(Json::Value &json);
 
		std::string getError() {return std::string(curl_errorbuffer);}
 
		const std::string &getRawData() {
 
			return m_data;
 
		}
 

	
 
		void run();
 
@@ -48,23 +48,23 @@ class HTTPRequest : public Thread {
 
			curl_global_cleanup();
 
		}
 

	
 
	private:
 
		bool init();
 
		bool GET(std::string url, std::string &output);
 
		bool GET(std::string url, rapidjson::Document &json);
 
		bool GET(std::string url, Json::Value &json);
 

	
 

	
 
		CURL *curlhandle;
 
		char curl_errorbuffer[1024];
 
		std::string error;
 
		std::string callbackdata;
 
		ThreadPool *m_tp;
 
		std::string m_url;
 
		bool m_ok;
 
		rapidjson::Document m_json;
 
		Json::Value m_json;
 
		std::string m_data;
 
		Callback m_callback;
 
		Type m_type;
 

	
 
		static int curlCallBack(char* data, size_t size, size_t nmemb, HTTPRequest *obj);
 

	
include/transport/HTTPRequestQueue.h
Show inline comments
 
@@ -4,13 +4,12 @@
 
#include "curl/curl.h"
 
#include "transport/Logging.h"
 
#include "transport/ThreadPool.h"
 
#include <iostream>
 
#include <sstream>
 
#include <string.h>
 
#include "rapidjson/document.h"
 

	
 
#include "Swiften/Network/Timer.h"
 

	
 
namespace Transport {
 

	
 
class HTTPRequest;
libtransport/CMakeLists.txt
Show inline comments
 
@@ -44,15 +44,15 @@ endif(PROTOBUF_FOUND)
 
# endif()
 

	
 
find_package(CURL)
 

	
 
if (WIN32)
 
	include_directories("${CMAKE_SOURCE_DIR}/msvc-deps/sqlite3")
 
	TARGET_LINK_LIBRARIES(transport transport-plugin ${PQXX_LIBRARY} ${CURL_LIBRARIES} ${PQ_LIBRARY} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES} ${PROTOBUF_LIBRARY} psapi.lib)
 
	TARGET_LINK_LIBRARIES(transport transport-plugin ${PQXX_LIBRARY} ${CURL_LIBRARIES} ${PQ_LIBRARY} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES} ${PROTOBUF_LIBRARY} ${JSONCPP_LIBRARIES} psapi.lib)
 
else()
 
	TARGET_LINK_LIBRARIES(transport transport-plugin ${PQXX_LIBRARY} ${CURL_LIBRARIES} ${PQ_LIBRARY} ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES} ${POPT_LIBRARY} ${PROTOBUF_LIBRARY})
 
	TARGET_LINK_LIBRARIES(transport transport-plugin ${PQXX_LIBRARY} ${CURL_LIBRARIES} ${PQ_LIBRARY} ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES} ${POPT_LIBRARY} ${PROTOBUF_LIBRARY} ${JSONCPP_LIBRARIES})
 
endif()
 

	
 
SET_TARGET_PROPERTIES(transport PROPERTIES
 
      VERSION ${TRANSPORT_VERSION} SOVERSION ${TRANSPORT_VERSION}
 
)
 
if (APPLE)
libtransport/HTTPRequest.cpp
Show inline comments
 
@@ -95,20 +95,20 @@ bool HTTPRequest::GET(std::string url, 	std::string &data) {
 
		strcpy(curl_errorbuffer, "CURL not initialized!");
 
	}
 
	LOG4CXX_ERROR(logger, "Error fetching " << url);
 
	return false;
 
}
 

	
 
bool HTTPRequest::GET(std::string url, rapidjson::Document &json) {
 
bool HTTPRequest::GET(std::string url, Json::Value &json) {
 
	if (!GET(url, m_data)) {
 
		return false;
 
	}
 

	
 
	if(json.Parse<0>(m_data.c_str()).HasParseError()) {
 
	Json::Reader reader;
 
	if(!reader.parse(m_data.c_str(), json)) {
 
		LOG4CXX_ERROR(logger, "Error while parsing JSON");
 
        LOG4CXX_ERROR(logger, m_data);
 
	        LOG4CXX_ERROR(logger, m_data);
 
		strcpy(curl_errorbuffer, "Error while parsing JSON");
 
		return false;
 
	}
 

	
 
	return true;
 
}
 
@@ -140,13 +140,13 @@ bool HTTPRequest::execute() {
 
	}
 

	
 
	m_tp->runAsThread(this);
 
	return true;
 
}
 

	
 
bool HTTPRequest::execute(rapidjson::Document &json) {
 
bool HTTPRequest::execute(Json::Value &json) {
 
	init();
 
	switch (m_type) {
 
		case Get:
 
			m_ok = GET(m_url, json);
 
			break;
 
	}
libtransport/OAuth2.cpp
Show inline comments
 
@@ -78,42 +78,42 @@ std::string OAuth2::requestToken(const std::string &code, std::string &token, st
 
	url += "&code=" + Util::urlencode(code);
 

	
 
	if (!m_redirectURL.empty()) {
 
		url += "&redirect_uri=" + Util::urlencode(m_redirectURL);
 
	}
 

	
 
	rapidjson::Document resp;
 
	Json::Value resp;
 
	HTTPRequest req(HTTPRequest::Get, url);
 
	if (!req.execute(resp)) {
 
		LOG4CXX_ERROR(logger, url);
 
		LOG4CXX_ERROR(logger, req.getError());
 
		return req.getError();
 
	}
 

	
 
	LOG4CXX_ERROR(logger, req.getRawData());
 
	rapidjson::Value& access_token = resp["access_token"];
 
	if (!access_token.IsString()) {
 
	Json::Value& access_token = resp["access_token"];
 
	if (!access_token.isString()) {
 
		LOG4CXX_ERROR(logger, "No 'access_token' object in the reply.");
 
		LOG4CXX_ERROR(logger, url);
 
		LOG4CXX_ERROR(logger, req.getRawData());
 
		return "No 'access_token' object in the reply.";
 
	}
 

	
 
	token = access_token.GetString();
 
	token = access_token.asString();
 
	if (token.empty()) {
 
		LOG4CXX_ERROR(logger, "Empty 'access_token' object in the reply.");
 
		LOG4CXX_ERROR(logger, url);
 
		LOG4CXX_ERROR(logger, req.getRawData());
 
		return "Empty 'access_token' object in the reply.";
 
	}
 

	
 
	rapidjson::Value& bot = resp["bot"];
 
	if (bot.IsObject()) {
 
		rapidjson::Value& bot_access_token = bot["bot_access_token"];
 
		if (bot_access_token.IsString()) {
 
			bot_token = bot_access_token.GetString();
 
	Json::Value& bot = resp["bot"];
 
	if (bot.isObject()) {
 
		Json::Value& bot_access_token = bot["bot_access_token"];
 
		if (bot_access_token.isString()) {
 
			bot_token = bot_access_token.asString();
 
		}
 
	}
 

	
 
	return "";
 
}
 

	
spectrum/src/frontends/slack/SlackAPI.cpp
Show inline comments
 
@@ -34,57 +34,57 @@
 
#include <iterator>
 

	
 
namespace Transport {
 

	
 
DEFINE_LOGGER(logger, "SlackAPI");
 

	
 
#define GET_ARRAY(FROM, NAME) rapidjson::Value &NAME = FROM[#NAME]; \
 
	if (!NAME.IsArray()) { \
 
#define GET_ARRAY(FROM, NAME) Json::Value &NAME = FROM[#NAME]; \
 
	if (!NAME.isArray()) { \
 
		LOG4CXX_ERROR(logger, "No '" << #NAME << "' object in the reply."); \
 
		return; \
 
	}
 
	
 
#define STORE_STRING(FROM, NAME) rapidjson::Value &NAME##_tmp = FROM[#NAME]; \
 
	if (!NAME##_tmp.IsString()) {  \
 
#define STORE_STRING(FROM, NAME) Json::Value &NAME##_tmp = FROM[#NAME]; \
 
	if (!NAME##_tmp.isString()) {  \
 
		LOG4CXX_ERROR(logger, "No '" << #NAME << "' string in the reply."); \
 
		LOG4CXX_ERROR(logger, data); \
 
		return; \
 
	} \
 
	std::string NAME = NAME##_tmp.GetString();
 
	std::string NAME = NAME##_tmp.asString();
 

	
 
#define STORE_BOOL(FROM, NAME) rapidjson::Value &NAME##_tmp = FROM[#NAME]; \
 
	if (!NAME##_tmp.IsBool()) {  \
 
#define STORE_BOOL(FROM, NAME) Json::Value &NAME##_tmp = FROM[#NAME]; \
 
	if (!NAME##_tmp.isBool()) {  \
 
		LOG4CXX_ERROR(logger, "No '" << #NAME << "' string in the reply."); \
 
		LOG4CXX_ERROR(logger, data); \
 
		return; \
 
	} \
 
	bool NAME = NAME##_tmp.GetBool();
 
	bool NAME = NAME##_tmp.asBool();
 

	
 
#define GET_OBJECT(FROM, NAME) rapidjson::Value &NAME = FROM[#NAME]; \
 
	if (!NAME.IsObject()) { \
 
#define GET_OBJECT(FROM, NAME) Json::Value &NAME = FROM[#NAME]; \
 
	if (!NAME.isObject()) { \
 
		LOG4CXX_ERROR(logger, "No '" << #NAME << "' object in the reply."); \
 
		return; \
 
	}
 

	
 
#define STORE_STRING_OPTIONAL(FROM, NAME) rapidjson::Value &NAME##_tmp = FROM[#NAME]; \
 
#define STORE_STRING_OPTIONAL(FROM, NAME) Json::Value &NAME##_tmp = FROM[#NAME]; \
 
	std::string NAME; \
 
	if (NAME##_tmp.IsString()) {  \
 
		 NAME = NAME##_tmp.GetString(); \
 
	if (NAME##_tmp.isString()) {  \
 
		 NAME = NAME##_tmp.asString(); \
 
	}
 

	
 
SlackAPI::SlackAPI(Component *component, SlackIdManager *idManager, const std::string &token, const std::string &domain) : HTTPRequestQueue(component, domain) {
 
	m_component = component;
 
	m_token = token;
 
	m_idManager = idManager;
 
	m_domain = domain;
 
}
 

	
 
SlackAPI::~SlackAPI() {
 
}
 

	
 
void SlackAPI::handleSendMessage(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data) {
 
void SlackAPI::handleSendMessage(HTTPRequest *req, bool ok, Json::Value &resp, const std::string &data) {
 
	LOG4CXX_INFO(logger, data);
 
}
 

	
 
void SlackAPI::sendMessage(const std::string &from, const std::string &to, const std::string &text) {
 
	std::string url = "https://slack.com/api/chat.postMessage?";
 
	url += "&username=" + Util::urlencode(from);
 
@@ -117,34 +117,34 @@ void SlackAPI::setPurpose(const std::string &channel, const std::string &purpose
 

	
 
	HTTPRequest *req = new HTTPRequest(THREAD_POOL(m_component), HTTPRequest::Get, url,
 
			boost::bind(&SlackAPI::handleSendMessage, this, _1, _2, _3, _4));
 
	queueRequest(req);
 
}
 

	
 
std::string SlackAPI::getChannelId(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data) {
 
std::string SlackAPI::getChannelId(HTTPRequest *req, bool ok, Json::Value &resp, const std::string &data) {
 
	if (!ok) {
 
		LOG4CXX_ERROR(logger, req->getError());
 
		LOG4CXX_ERROR(logger, data);
 
		return "";
 
	}
 

	
 
	rapidjson::Value &channel = resp["channel"];
 
	if (!channel.IsObject()) {
 
	Json::Value &channel = resp["channel"];
 
	if (!channel.isObject()) {
 
		LOG4CXX_ERROR(logger, "No 'channel' object in the reply.");
 
		LOG4CXX_ERROR(logger, data);
 
		return "";
 
	}
 

	
 
	rapidjson::Value &id = channel["id"];
 
	if (!id.IsString()) {
 
	Json::Value &id = channel["id"];
 
	if (!id.isString()) {
 
		LOG4CXX_ERROR(logger, "No 'id' string in the reply.");
 
		LOG4CXX_ERROR(logger, data);
 
		return "";
 
	}
 

	
 
	return id.GetString();
 
	return id.asString();
 
}
 

	
 
void SlackAPI::channelsList( HTTPRequest::Callback callback) {
 
	std::string url = "https://slack.com/api/channels.list?token=" + Util::urlencode(m_token);
 
	HTTPRequest *req = new HTTPRequest(THREAD_POOL(m_component), HTTPRequest::Get, url, callback);
 
	queueRequest(req);
 
@@ -168,123 +168,123 @@ void SlackAPI::channelsCreate(const std::string &name, HTTPRequest::Callback cal
 
void SlackAPI::imOpen(const std::string &uid, HTTPRequest::Callback callback) {
 
	std::string url = "https://slack.com/api/im.open?user=" + Util::urlencode(uid) + "&token=" + Util::urlencode(m_token);
 
	HTTPRequest *req = new HTTPRequest(THREAD_POOL(m_component), HTTPRequest::Get, url, callback);
 
	queueRequest(req);
 
}
 

	
 
std::string SlackAPI::getOwnerId(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data) {
 
std::string SlackAPI::getOwnerId(HTTPRequest *req, bool ok, Json::Value &resp, const std::string &data) {
 
	if (!ok) {
 
		LOG4CXX_ERROR(logger, req->getError());
 
		return "";
 
	}
 

	
 
	rapidjson::Value &members = resp["members"];
 
	if (!members.IsArray()) {
 
	Json::Value &members = resp["members"];
 
	if (!members.isArray()) {
 
		LOG4CXX_ERROR(logger, "No 'members' object in the reply.");
 
		return "";
 
	}
 

	
 
	for (unsigned i = 0; i < members.Size(); i++) {
 
		if (!members[i].IsObject()) {
 
	for (unsigned i = 0; i < members.size(); i++) {
 
		if (!members[i].isObject()) {
 
			continue;
 
		}
 

	
 
		rapidjson::Value &is_primary_owner = members[i]["is_primary_owner"];
 
		if (!is_primary_owner.IsBool()) {
 
		Json::Value &is_primary_owner = members[i]["is_primary_owner"];
 
		if (!is_primary_owner.isBool()) {
 
			continue;
 
		}
 

	
 
		if (is_primary_owner.GetBool()) {
 
			rapidjson::Value &name = members[i]["id"];
 
			if (!name.IsString()) {
 
		if (is_primary_owner.asBool()) {
 
			Json::Value &name = members[i]["id"];
 
			if (!name.isString()) {
 
				LOG4CXX_ERROR(logger, "No 'name' string in the reply.");
 
				return "";
 
			}
 
			return name.GetString();
 
			return name.asString();
 
		}
 
	}
 

	
 
	return "";
 
}
 

	
 
void SlackAPI::usersList(HTTPRequest::Callback callback) {
 
	std::string url = "https://slack.com/api/users.list?presence=0&token=" + Util::urlencode(m_token);
 
	HTTPRequest *req = new HTTPRequest(THREAD_POOL(m_component), HTTPRequest::Get, url, callback);
 
	queueRequest(req);
 
}
 

	
 
void SlackAPI::getSlackChannelInfo(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data, std::map<std::string, SlackChannelInfo> &ret) {
 
void SlackAPI::getSlackChannelInfo(HTTPRequest *req, bool ok, Json::Value &resp, const std::string &data, std::map<std::string, SlackChannelInfo> &ret) {
 
	if (!ok) {
 
		LOG4CXX_ERROR(logger, req->getError());
 
		return;
 
	}
 

	
 
	rapidjson::Value &channels = resp["channels"];
 
	if (!channels.IsArray()) {
 
		rapidjson::Value &channel = resp["channel"];
 
		if (channel.IsObject()) {
 
	Json::Value &channels = resp["channels"];
 
	if (!channels.isArray()) {
 
		Json::Value &channel = resp["channel"];
 
		if (channel.isObject()) {
 
			SlackChannelInfo info;
 

	
 
			STORE_STRING(channel, id);
 
			info.id = id;
 

	
 
			STORE_STRING(channel, name);
 
			info.name = name;
 

	
 
			rapidjson::Value &members = channel["members"];
 
			for (unsigned y = 0; members.IsArray() && y < members.Size(); y++) {
 
				if (!members[y].IsString()) {
 
			Json::Value &members = channel["members"];
 
			for (unsigned y = 0; members.isArray() && y < members.size(); y++) {
 
				if (!members[y].isString()) {
 
					continue;
 
				}
 

	
 
				info.members.push_back(members[y].GetString());
 
				info.members.push_back(members[y].asString());
 
			}
 

	
 
			ret[info.name] = info;
 
		}
 
		return;
 
	}
 

	
 
	for (unsigned i = 0; i < channels.Size(); i++) {
 
		if (!channels[i].IsObject()) {
 
	for (unsigned i = 0; i < channels.size(); i++) {
 
		if (!channels[i].isObject()) {
 
			continue;
 
		}
 

	
 
		SlackChannelInfo info;
 

	
 
		STORE_STRING(channels[i], id);
 
		info.id = id;
 

	
 
		STORE_STRING(channels[i], name);
 
		info.name = name;
 

	
 
		rapidjson::Value &members = channels[i]["members"];
 
		for (unsigned y = 0; members.IsArray() && y < members.Size(); y++) {
 
			if (!members[y].IsString()) {
 
		Json::Value &members = channels[i]["members"];
 
		for (unsigned y = 0; members.isArray() && y < members.size(); y++) {
 
			if (!members[y].isString()) {
 
				continue;
 
			}
 

	
 
			info.members.push_back(members[y].GetString());
 
			info.members.push_back(members[y].asString());
 
		}
 

	
 
		ret[info.name] = info;
 
	}
 

	
 
	return;
 
}
 

	
 
void SlackAPI::getSlackImInfo(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data, std::map<std::string, SlackImInfo> &ret) {
 
void SlackAPI::getSlackImInfo(HTTPRequest *req, bool ok, Json::Value &resp, const std::string &data, std::map<std::string, SlackImInfo> &ret) {
 
	if (!ok) {
 
		LOG4CXX_ERROR(logger, req->getError());
 
		return;
 
	}
 

	
 
	GET_ARRAY(resp, ims);
 

	
 
	for (unsigned i = 0; i < ims.Size(); i++) {
 
		if (!ims[i].IsObject()) {
 
	for (unsigned i = 0; i < ims.size(); i++) {
 
		if (!ims[i].isObject()) {
 
			continue;
 
		}
 

	
 
		SlackImInfo info;
 

	
 
		STORE_STRING(ims[i], id);
 
@@ -297,22 +297,22 @@ void SlackAPI::getSlackImInfo(HTTPRequest *req, bool ok, rapidjson::Document &re
 
		LOG4CXX_INFO(logger, info.id << " " << info.user);
 
	}
 

	
 
	return;
 
}
 

	
 
void SlackAPI::getSlackUserInfo(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data, std::map<std::string, SlackUserInfo> &ret) {
 
void SlackAPI::getSlackUserInfo(HTTPRequest *req, bool ok, Json::Value &resp, const std::string &data, std::map<std::string, SlackUserInfo> &ret) {
 
	if (!ok) {
 
		LOG4CXX_ERROR(logger, req->getError());
 
		return;
 
	}
 

	
 
	GET_ARRAY(resp, users);
 

	
 
	for (unsigned i = 0; i < users.Size(); i++) {
 
		if (!users[i].IsObject()) {
 
	for (unsigned i = 0; i < users.size(); i++) {
 
		if (!users[i].isObject()) {
 
			continue;
 
		}
 

	
 
		SlackUserInfo info;
 

	
 
		STORE_STRING(users[i], id);
 
@@ -334,14 +334,14 @@ void SlackAPI::getSlackUserInfo(HTTPRequest *req, bool ok, rapidjson::Document &
 
			LOG4CXX_INFO(logger, bot_id << " " << info.name);
 
		}
 
	}
 

	
 
	GET_ARRAY(resp, bots);
 

	
 
	for (unsigned i = 0; i < bots.Size(); i++) {
 
		if (!bots[i].IsObject()) {
 
	for (unsigned i = 0; i < bots.size(); i++) {
 
		if (!bots[i].isObject()) {
 
			continue;
 
		}
 

	
 
		SlackUserInfo info;
 

	
 
		STORE_STRING(bots[i], id);
 
@@ -377,17 +377,17 @@ std::string SlackAPI::SlackObjectToPlainText(const std::string &object, bool isC
 
		}
 
	}
 

	
 
	return ret;
 
}
 

	
 
void SlackAPI::handleSlackChannelInvite(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data, const std::string &channel, const std::string &userId, CreateChannelCallback callback) {
 
void SlackAPI::handleSlackChannelInvite(HTTPRequest *req, bool ok, Json::Value &resp, const std::string &data, const std::string &channel, const std::string &userId, CreateChannelCallback callback) {
 
	callback(channel);
 
}
 

	
 
void SlackAPI::handleSlackChannelCreate(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data, const std::string &channel, const std::string &userId, CreateChannelCallback callback) {
 
void SlackAPI::handleSlackChannelCreate(HTTPRequest *req, bool ok, Json::Value &resp, const std::string &data, const std::string &channel, const std::string &userId, CreateChannelCallback callback) {
 
	std::map<std::string, SlackChannelInfo> &channels = m_idManager->getChannels();
 
	SlackAPI::getSlackChannelInfo(req, ok, resp, data, channels);
 

	
 
	std::string channelId = m_idManager->getId(channel);
 
	if (channelId == channel) {
 
		LOG4CXX_INFO(logger, "Error creating channel " << channel << ".");
 
@@ -395,13 +395,13 @@ void SlackAPI::handleSlackChannelCreate(HTTPRequest *req, bool ok, rapidjson::Do
 
	}
 

	
 
	LOG4CXX_INFO(logger, m_domain << ": createChannel: Channel " << channel << " created, going to invite " << userId << " there.");
 
	channelsInvite(channelId, userId, boost::bind(&SlackAPI::handleSlackChannelInvite, this, _1, _2, _3, _4, channelId, userId, callback));
 
}
 

	
 
void SlackAPI::handleSlackChannelList(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data, const std::string &channel, const std::string &userId, CreateChannelCallback callback) {
 
void SlackAPI::handleSlackChannelList(HTTPRequest *req, bool ok, Json::Value &resp, const std::string &data, const std::string &channel, const std::string &userId, CreateChannelCallback callback) {
 
	std::map<std::string, SlackChannelInfo> &channels = m_idManager->getChannels();
 
	SlackAPI::getSlackChannelInfo(req, ok, resp, data, channels);
 

	
 
	std::string channelId = m_idManager->getId(channel);
 
	if (channelId != channel) {
 
		LOG4CXX_INFO(logger, m_domain << ": createChannel: Channel " << channel << " already exists, will just invite " << userId << " there.");
spectrum/src/frontends/slack/SlackAPI.h
Show inline comments
 
@@ -19,13 +19,13 @@
 
 */
 

	
 
#pragma once
 

	
 
#include "transport/HTTPRequestQueue.h"
 
#include "transport/HTTPRequest.h"
 
#include "rapidjson/document.h"
 
#include <json/json.h>
 

	
 
#include <string>
 
#include <algorithm>
 
#include <map>
 

	
 
namespace Transport {
 
@@ -69,40 +69,40 @@ class SlackAPI : public HTTPRequestQueue {
 
	public:
 
		SlackAPI(Component *component, SlackIdManager *idManager, const std::string &token, const std::string &domain);
 

	
 
		virtual ~SlackAPI();
 

	
 
		void usersList(HTTPRequest::Callback callback);
 
		std::string getOwnerId(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data);
 
		std::string getOwnerId(HTTPRequest *req, bool ok, Json::Value &resp, const std::string &data);
 

	
 
		void channelsCreate(const std::string &name, HTTPRequest::Callback callback);
 
		void channelsInvite(const std::string &channel, const std::string &user, HTTPRequest::Callback callback);
 
		void channelsList(HTTPRequest::Callback callback);
 

	
 
		void imOpen(const std::string &uid, HTTPRequest::Callback callback);
 
		std::string getChannelId(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data);
 
		std::string getChannelId(HTTPRequest *req, bool ok, Json::Value &resp, const std::string &data);
 

	
 
		void deleteMessage(const std::string &channel, const std::string &ts);
 
		void sendMessage(const std::string &from, const std::string &to, const std::string &text);
 
		void setPurpose(const std::string &channel, const std::string &purpose);
 

	
 
		static void getSlackChannelInfo(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data, std::map<std::string, SlackChannelInfo> &channels);
 
		static void getSlackImInfo(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data, std::map<std::string, SlackImInfo> &ims);
 
		static void getSlackUserInfo(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data, std::map<std::string, SlackUserInfo> &users);
 
		static void getSlackChannelInfo(HTTPRequest *req, bool ok, Json::Value &resp, const std::string &data, std::map<std::string, SlackChannelInfo> &channels);
 
		static void getSlackImInfo(HTTPRequest *req, bool ok, Json::Value &resp, const std::string &data, std::map<std::string, SlackImInfo> &ims);
 
		static void getSlackUserInfo(HTTPRequest *req, bool ok, Json::Value &resp, const std::string &data, std::map<std::string, SlackUserInfo> &users);
 
		static std::string SlackObjectToPlainText(const std::string &object, bool isChannel = false, bool returnName = false);
 

	
 
		// Creates channel if it does not exist and invites the user to the channel.
 
		typedef boost::function< void (const std::string &channelId) > CreateChannelCallback;
 
		void createChannel(const std::string &channel, const std::string &user, CreateChannelCallback callback);
 

	
 
	private:
 
		void handleSendMessage(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data);
 
		void handleSendMessage(HTTPRequest *req, bool ok, Json::Value &resp, const std::string &data);
 

	
 
		void handleSlackChannelCreate(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data, const std::string &channel, const std::string &user, CreateChannelCallback callback);
 
		void handleSlackChannelList(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data, const std::string &channel, const std::string &user, CreateChannelCallback callback);
 
		void handleSlackChannelInvite(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data, const std::string &channel, const std::string &user, CreateChannelCallback callback);
 
		void handleSlackChannelCreate(HTTPRequest *req, bool ok, Json::Value &resp, const std::string &data, const std::string &channel, const std::string &user, CreateChannelCallback callback);
 
		void handleSlackChannelList(HTTPRequest *req, bool ok, Json::Value &resp, const std::string &data, const std::string &channel, const std::string &user, CreateChannelCallback callback);
 
		void handleSlackChannelInvite(HTTPRequest *req, bool ok, Json::Value &resp, const std::string &data, const std::string &channel, const std::string &user, CreateChannelCallback callback);
 

	
 
	private:
 
		Component *m_component;
 
		SlackIdManager *m_idManager;
 
		std::string m_token;
 
		std::string m_domain;
spectrum/src/frontends/slack/SlackIdManager.h
Show inline comments
 
@@ -20,13 +20,12 @@
 

	
 
#pragma once
 

	
 
#include "SlackAPI.h"
 

	
 
#include "transport/StorageBackend.h"
 
#include "rapidjson/document.h"
 

	
 
#include <Swiften/Network/TLSConnectionFactory.h>
 
#include <Swiften/Network/HostAddressPort.h>
 
#include <Swiften/TLS/PlatformTLSFactories.h>
 
#include <Swiften/Network/DomainNameResolveError.h>
 
#include <Swiften/Network/DomainNameAddressQuery.h>
spectrum/src/frontends/slack/SlackRTM.cpp
Show inline comments
 
@@ -69,43 +69,44 @@ void SlackRTM::start() {
 
	url += "token=" + Util::urlencode(m_token);
 

	
 
	HTTPRequest *req = new HTTPRequest(THREAD_POOL(m_component), HTTPRequest::Get, url, boost::bind(&SlackRTM::handleRTMStart, this, _1, _2, _3, _4));
 
	req->execute();
 
}
 

	
 
#define STORE_STRING(FROM, NAME) rapidjson::Value &NAME##_tmp = FROM[#NAME]; \
 
	if (!NAME##_tmp.IsString()) {  \
 
#define STORE_STRING(FROM, NAME) Json::Value &NAME##_tmp = FROM[#NAME]; \
 
	if (!NAME##_tmp.isString()) {  \
 
		LOG4CXX_ERROR(logger, "No '" << #NAME << "' string in the reply."); \
 
		LOG4CXX_ERROR(logger, payload); \
 
		return; \
 
	} \
 
	std::string NAME = NAME##_tmp.GetString();
 
	std::string NAME = NAME##_tmp.asString();
 

	
 
#define STORE_STRING_OPTIONAL(FROM, NAME) rapidjson::Value &NAME##_tmp = FROM[#NAME]; \
 
#define STORE_STRING_OPTIONAL(FROM, NAME) Json::Value &NAME##_tmp = FROM[#NAME]; \
 
	std::string NAME; \
 
	if (NAME##_tmp.IsString()) {  \
 
		 NAME = NAME##_tmp.GetString(); \
 
	if (NAME##_tmp.isString()) {  \
 
		 NAME = NAME##_tmp.asString(); \
 
	}
 

	
 
#define GET_OBJECT(FROM, NAME) rapidjson::Value &NAME = FROM[#NAME]; \
 
	if (!NAME.IsObject()) { \
 
#define GET_OBJECT(FROM, NAME) Json::Value &NAME = FROM[#NAME]; \
 
	if (!NAME.isObject()) { \
 
		LOG4CXX_ERROR(logger, "No '" << #NAME << "' object in the reply."); \
 
		return; \
 
	}
 

	
 
#define STORE_INT(FROM, NAME) rapidjson::Value &NAME##_tmp = FROM[#NAME]; \
 
	if (!NAME##_tmp.IsInt()) {  \
 
#define STORE_INT(FROM, NAME) Json::Value &NAME##_tmp = FROM[#NAME]; \
 
	if (!NAME##_tmp.isInt()) {  \
 
		LOG4CXX_ERROR(logger, "No '" << #NAME << "' number in the reply."); \
 
		LOG4CXX_ERROR(logger, payload); \
 
		return; \
 
	} \
 
	int NAME = NAME##_tmp.GetInt();
 
	int NAME = NAME##_tmp.asInt();
 

	
 
void SlackRTM::handlePayloadReceived(const std::string &payload) {
 
	rapidjson::Document d;
 
	if (d.Parse<0>(payload.c_str()).HasParseError()) {
 
	Json::Value d;
 
	Json::Reader reader;
 
	if (!reader.parse(payload.c_str(), d)) {
 
		LOG4CXX_ERROR(logger, "Error while parsing JSON");
 
		LOG4CXX_ERROR(logger, payload);
 
		return;
 
	}
 

	
 
	STORE_STRING(d, type);
 
@@ -114,15 +115,15 @@ void SlackRTM::handlePayloadReceived(const std::string &payload) {
 
		STORE_STRING(d, channel);
 
		STORE_STRING(d, text);
 
		STORE_STRING(d, ts);
 
		STORE_STRING_OPTIONAL(d, subtype);
 
		STORE_STRING_OPTIONAL(d, purpose);
 

	
 
		rapidjson::Value &attachments = d["attachments"];
 
		if (attachments.IsArray()) {
 
			for (unsigned i = 0; i < attachments.Size(); i++) {
 
		Json::Value &attachments = d["attachments"];
 
		if (attachments.isArray()) {
 
			for (unsigned i = 0; i < attachments.size(); i++) {
 
				STORE_STRING_OPTIONAL(attachments[i], fallback);
 
				if (!fallback.empty()) {
 
					text += fallback;
 
				}
 
			}
 
		}
 
@@ -178,66 +179,64 @@ void SlackRTM::sendPing() {
 
	m_counter++;
 
	std::string msg = "{\"id\": " + boost::lexical_cast<std::string>(m_counter) + ", \"type\": \"ping\"}";
 
	m_client->write(msg);
 
	m_pingTimer->start();
 
}
 

	
 
void SlackRTM::handleRTMStart(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data) {
 
void SlackRTM::handleRTMStart(HTTPRequest *req, bool ok, Json::Value &resp, const std::string &data) {
 
	if (!ok) {
 
		LOG4CXX_ERROR(logger, req->getError());
 
		LOG4CXX_ERROR(logger, data);
 
		return;
 
	}
 

	
 
	STORE_STRING_OPTIONAL(resp, error);
 
	if (!error.empty()) {
 
		if (error == "account_inactive") {
 
			LOG4CXX_INFO(logger, "Account inactive, will not try connecting again");
 
			m_pingTimer->stop();
 
			m_client->disconnectServer();
 
			return;
 
		}
 
	}
 

	
 
	rapidjson::Value &url = resp["url"];
 
	if (!url.IsString()) {
 
	Json::Value &url = resp["url"];
 
	if (!url.isString()) {
 
		LOG4CXX_ERROR(logger, "No 'url' object in the reply.");
 
		LOG4CXX_ERROR(logger, data);
 
		return;
 
	}
 

	
 
	rapidjson::Value &self = resp["self"];
 
	if (!self.IsObject()) {
 
	Json::Value &self = resp["self"];
 
	if (!self.isObject()) {
 
		LOG4CXX_ERROR(logger, "No 'self' object in the reply.");
 
		LOG4CXX_ERROR(logger, data);
 
		return;
 
	}
 

	
 
	rapidjson::Value &selfName = self["name"];
 
	if (!selfName.IsString()) {
 
	Json::Value &selfName = self["name"];
 
	if (!selfName.isString()) {
 
		LOG4CXX_ERROR(logger, "No 'name' string in the reply.");
 
		LOG4CXX_ERROR(logger, data);
 
		return;
 
	}
 

	
 
	m_idManager->setSelfName(selfName.GetString());
 
	m_idManager->setSelfName(selfName.asString());
 

	
 
	rapidjson::Value &selfId = self["id"];
 
	if (!selfId.IsString()) {
 
	Json::Value &selfId = self["id"];
 
	if (!selfId.isString()) {
 
		LOG4CXX_ERROR(logger, "No 'id' string in the reply.");
 
		LOG4CXX_ERROR(logger, data);
 
		return;
 
	}
 

	
 
	m_idManager->setSelfId(selfId.GetString());
 
	m_idManager->setSelfId(selfId.asString());
 

	
 
	SlackAPI::getSlackChannelInfo(req, ok, resp, data, m_idManager->getChannels());
 
	SlackAPI::getSlackImInfo(req, ok, resp, data, m_idManager->getIMs());
 
	SlackAPI::getSlackUserInfo(req, ok, resp, data, m_idManager->getUsers());
 

	
 
	std::string u = url.GetString();
 
	std::string u = url.asString();
 
	LOG4CXX_INFO(logger, "Started RTM, WebSocket URL is " << u);
 
	LOG4CXX_INFO(logger, data);
 

	
 
#ifndef LIBTRANSPORT_TEST
 
	m_client->connectServer(u);
 
#endif
spectrum/src/frontends/slack/SlackRTM.h
Show inline comments
 
@@ -20,13 +20,13 @@
 

	
 
#pragma once
 

	
 
#include "SlackAPI.h"
 

	
 
#include "transport/StorageBackend.h"
 
#include "rapidjson/document.h"
 
#include <json/json.h>
 

	
 
#include <Swiften/Network/TLSConnectionFactory.h>
 
#include <Swiften/Network/HostAddressPort.h>
 
#include <Swiften/TLS/PlatformTLSFactories.h>
 
#include <Swiften/Network/DomainNameResolveError.h>
 
#include <Swiften/Network/DomainNameAddressQuery.h>
 
@@ -77,13 +77,13 @@ class SlackRTM {
 
		SWIFTEN_SIGNAL_NAMESPACE::signal<void (const std::string &channel, const std::string &user, const std::string &text, const std::string &ts)> onMessageReceived;
 

	
 
#ifndef LIBTRANSPORT_TEST
 
	private:
 
#endif
 
		void handlePayloadReceived(const std::string &payload);
 
		void handleRTMStart(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data);
 
		void handleRTMStart(HTTPRequest *req, bool ok, Json::Value &resp, const std::string &data);
 
		void handleWebSocketConnected();
 
		void handleWebSocketDisconnected(const boost::optional<Swift::Connection::Error> &error);
 

	
 
	private:
 
		Component *m_component;
 
		StorageBackend *m_storageBackend;
spectrum/src/frontends/slack/SlackSession.h
Show inline comments
 
@@ -18,13 +18,12 @@
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
 */
 

	
 
#pragma once
 

	
 
#include "transport/StorageBackend.h"
 
#include "rapidjson/document.h"
 

	
 
#include <string>
 
#include <algorithm>
 
#include <map>
 

	
 
#include "Swiften/Elements/Message.h"
spectrum/src/frontends/slack/SlackUserRegistration.cpp
Show inline comments
 
@@ -31,13 +31,13 @@
 
#include "transport/Buddy.h"
 
#include "transport/Config.h"
 
#include "transport/OAuth2.h"
 
#include "transport/Util.h"
 
#include "transport/HTTPRequest.h"
 

	
 
#include "rapidjson/document.h"
 
#include <json/json.h>
 

	
 
#include <boost/shared_ptr.hpp>
 
#include <boost/thread.hpp>
 
#include <boost/date_time/posix_time/posix_time.hpp>
 
#include <boost/regex.hpp> 
 

	
 
@@ -84,37 +84,37 @@ std::string SlackUserRegistration::createOAuth2URL(const std::vector<std::string
 
	return url;
 
}
 

	
 
std::string SlackUserRegistration::getTeamDomain(const std::string &token) {
 
	std::string url = "https://slack.com/api/team.info?token=" + Util::urlencode(token);
 

	
 
	rapidjson::Document resp;
 
	Json::Value resp;
 
	HTTPRequest req(HTTPRequest::Get, url);
 
	if (!req.execute(resp)) {
 
		LOG4CXX_ERROR(logger, url);
 
		LOG4CXX_ERROR(logger, req.getError());
 
		return "";
 
	}
 

	
 
	rapidjson::Value &team = resp["team"];
 
	if (!team.IsObject()) {
 
	Json::Value &team = resp["team"];
 
	if (!team.isObject()) {
 
		LOG4CXX_ERROR(logger, "No 'team' object in the reply.");
 
		LOG4CXX_ERROR(logger, url);
 
		LOG4CXX_ERROR(logger, req.getRawData());
 
		return "";
 
	}
 

	
 
	rapidjson::Value &domain = team["domain"];
 
	if (!domain.IsString()) {
 
	Json::Value &domain = team["domain"];
 
	if (!domain.isString()) {
 
		LOG4CXX_ERROR(logger, "No 'domain' string in the reply.");
 
		LOG4CXX_ERROR(logger, url);
 
		LOG4CXX_ERROR(logger, req.getRawData());
 
		return "";
 
	}
 

	
 
	return domain.GetString();
 
	return domain.asString();
 
}
 

	
 
std::string SlackUserRegistration::handleOAuth2Code(const std::string &code, const std::string &state) {
 
	OAuth2 *oauth2 = NULL;
 
	std::string token;
 
	std::string access_token;
spectrum_manager/src/APIServer.cpp
Show inline comments
 
@@ -9,15 +9,13 @@
 
#include <stdarg.h>
 
#include <pthread.h>
 
#include <fstream>
 
#include <string>
 
#include <cerrno>
 

	
 
#include "rapidjson/rapidjson.h"
 
#include "rapidjson/stringbuffer.h"
 
#include "rapidjson/writer.h"
 
#include <json/json.h>
 

	
 
#include <boost/tokenizer.hpp>
 
using boost::tokenizer;
 
using boost::escaped_list_separator;
 

	
 
#define ALLOW_ONLY_ADMIN() 	if (!session->admin) { \
 
@@ -52,17 +50,15 @@ APIServer::APIServer(ManagerConfig *config, StorageBackend *storage) {
 
	m_storage = storage;
 
}
 

	
 
APIServer::~APIServer() {
 
}
 

	
 
void APIServer::send_json(struct mg_connection *conn, const Document &d) {
 
	StringBuffer buffer;
 
	Writer<StringBuffer> writer(buffer);
 
	d.Accept(writer);
 
	std::string json(buffer.GetString());
 
void APIServer::send_json(struct mg_connection *conn, const Json::Value &d) {
 
	Json::FastWriter writer;
 
	std::string json = writer.write(d);
 

	
 
	std::cout << "Sending JSON:\n";
 
	std::cout << json << "\n";
 
	mg_printf(conn,
 
			"HTTP/1.1 200 OK\r\n"
 
			"Content-Type: text/json\r\n"
 
@@ -70,78 +66,75 @@ void APIServer::send_json(struct mg_connection *conn, const Document &d) {
 
			"\r\n"
 
			"%s",
 
			(int) json.size(), json.c_str());
 
}
 

	
 
void APIServer::send_ack(struct mg_connection *conn, bool error, const std::string &message) {
 
	Document json;
 
	json.SetObject();
 
	json.AddMember("error", error, json.GetAllocator());
 
	json.AddMember("message", StringRef(message.c_str()), json.GetAllocator());
 
	Json::Value json;
 
	json["error"] = error;
 
	json["message"] = message;
 

	
 
	send_json(conn, json);
 
}
 

	
 
void APIServer::serve_instances(Server *server, Server::session *session, struct mg_connection *conn, struct http_message *hm) {
 
	// rapidjson stores const char* pointer to status, so we have to keep
 
	// the std::string stored out of BOOST_FOREACH scope, otherwise the
 
	// const char * returned by c_str() would be invalid during send_json.
 
	std::vector<std::string> statuses;
 
	std::vector<std::string> usernames;
 
	std::vector<std::string> list = show_list(m_config, false);
 

	
 
	Document json;
 
	json.SetObject();
 
	json.AddMember("error", 0, json.GetAllocator());
 
	Json::Value json;
 
	json["error"] = 0;
 

	
 
	Value instances(kArrayType);
 
	Json::Value instances(Json::ValueType::arrayValue);
 
	BOOST_FOREACH(std::string &id, list) {
 
		Value instance;
 
		instance.SetObject();
 
		instance.AddMember("id", StringRef(id.c_str()), json.GetAllocator());
 
		Json::Value instance;
 
		instance["id"] = id;
 

	
 
		std::string name = get_config(m_config, id, "identity.name");
 
		if (name.empty() || name == "Spectrum 2 Transport") {
 
			instance.AddMember("name", StringRef(id.c_str()), json.GetAllocator());
 
			instance["name"] = id;
 
		}
 
		else {
 
			statuses.push_back(name);
 
			instance.AddMember("name", StringRef(statuses.back().c_str()), json.GetAllocator());
 
			instance["name"] = statuses.back();
 
		}
 

	
 
		std::string status = server->send_command(id, "status");
 
		if (status.empty()) {
 
			status = "Cannot get the instance status.";
 
		}
 

	
 
		statuses.push_back(status);
 
		instance.AddMember("status", StringRef(statuses.back().c_str()), json.GetAllocator());
 
		instance["status"] = statuses.back();
 

	
 
		bool running = true;
 
		if (status.find("Running") == std::string::npos) {
 
			running = false;
 
		}
 
		instance.AddMember("running", running, json.GetAllocator());
 
		instance["running"] = running;
 

	
 
		UserInfo info;
 
		m_storage->getUser(session->user, info);
 
		std::string username = "";
 
		int type = (int) TYPE_STRING;
 
		m_storage->getUserSetting(info.id, id, type, username);
 

	
 
		usernames.push_back(username);
 
		instance.AddMember("registered", !username.empty(), json.GetAllocator());
 
		instance.AddMember("username", StringRef(usernames.back().c_str()), json.GetAllocator());
 
		instance["registered"] = !username.empty();
 
		instance["username"] = usernames.back();
 

	
 
		usernames.push_back(get_config(m_config, id, "service.frontend"));
 
		instance.AddMember("frontend", StringRef(usernames.back().c_str()), json.GetAllocator());
 
		instance["frontend"] = usernames.back();
 

	
 
		instances.PushBack(instance, json.GetAllocator());
 
		instances.append(instance);
 
	}
 

	
 
	json.AddMember("instances", instances, json.GetAllocator());
 
	json["instances"] = instances;
 
	send_json(conn, json);
 
}
 

	
 
void APIServer::serve_instances_start(Server *server, Server::session *session, struct mg_connection *conn, struct http_message *hm) {
 
	ALLOW_ONLY_ADMIN();
 

	
 
@@ -229,16 +222,15 @@ void APIServer::serve_instances_register(Server *server, Server::session *sessio
 
		send_ack(conn, true, "Insufficient data.");
 
	}
 
	else {
 
		// Check if the frontend wants to use OAuth2 (Slack for example).
 
		std::string response = server->send_command(instance, "get_oauth2_url " + jid + " " + uin + " " + password);
 
		if (!response.empty() && response.find("Error:") != 0) {
 
			Document json;
 
			json.SetObject();
 
			json.AddMember("error", false, json.GetAllocator());
 
			json.AddMember("oauth2_url", StringRef(response.c_str()), json.GetAllocator());
 
			Json::Value json;
 
			json["error"] = false;
 
			json["oauth2_url"] = response;
 
			send_json(conn, json);
 
		}
 
		else {
 
			response = server->send_command(instance, "register " + jid + " " + uin + " " + password);
 
			if (!response.empty()) {
 
				std::string value = jid;
 
@@ -291,18 +283,17 @@ void APIServer::serve_instances_commands(Server *server, Server::session *sessio
 

	
 
	std::string response = server->send_command(instance, "commands");
 

	
 
	std::vector<std::string> commands;
 
	boost::split(commands, response, boost::is_any_of("\n"));
 

	
 
	Document json;
 
	json.SetObject();
 
	json.AddMember("error", 0, json.GetAllocator());
 
	Json::Value json;
 
	json["error"] = 0;
 

	
 
	std::vector<std::vector<std::string> > tmp;
 
	Value cmds(kArrayType);
 
	Json::Value cmds(Json::ValueType::arrayValue);
 
	BOOST_FOREACH(const std::string &command, commands) {
 
		escaped_list_separator<char> els('\\', ' ', '\"');
 
		tokenizer<escaped_list_separator<char> > tok(command, els);
 

	
 
		std::vector<std::string> tokens;
 
		for(tokenizer<escaped_list_separator<char> >::iterator beg=tok.begin(); beg!=tok.end(); ++beg) {
 
@@ -327,23 +318,22 @@ void APIServer::serve_instances_commands(Server *server, Server::session *sessio
 
		if (!session->admin && !username.empty() && tokens[0] == "register") {
 
			continue;
 
		}
 

	
 
		tmp.push_back(tokens);
 

	
 
		Value cmd;
 
		cmd.SetObject();
 
		cmd.AddMember("name", StringRef(tokens[0].c_str()), json.GetAllocator());
 
		cmd.AddMember("desc", StringRef(tokens[2].c_str()), json.GetAllocator());
 
		cmd.AddMember("category", StringRef(tokens[4].c_str()), json.GetAllocator());
 
		cmd.AddMember("context", StringRef(tokens[8].c_str()), json.GetAllocator());
 
		cmd.AddMember("label", StringRef(tokens[10].c_str()), json.GetAllocator());
 
		cmds.PushBack(cmd, json.GetAllocator());
 
		Json::Value cmd;
 
		cmd["name"] = tokens[0];
 
		cmd["desc"] = tokens[2];
 
		cmd["category"] = tokens[4];
 
		cmd["context"] = tokens[8];
 
		cmd["label"] = tokens[10];
 
		cmds.append(cmd);
 
	}
 

	
 
	json.AddMember("commands", cmds, json.GetAllocator());
 
	json["commands"] = cmds;
 
	send_json(conn, json);
 
}
 

	
 
void APIServer::serve_instances_variables(Server *server, Server::session *session, struct mg_connection *conn, struct http_message *hm) {
 
	std::string uri(hm->uri.p, hm->uri.len);
 
	std::string instance = uri.substr(uri.rfind("/") + 1);
 
@@ -357,18 +347,17 @@ void APIServer::serve_instances_variables(Server *server, Server::session *sessi
 

	
 
	std::string response = server->send_command(instance, "variables");
 

	
 
	std::vector<std::string> commands;
 
	boost::split(commands, response, boost::is_any_of("\n"));
 

	
 
	Document json;
 
	json.SetObject();
 
	json.AddMember("error", 0, json.GetAllocator());
 
	Json::Value json;
 
	json["error"] = 0;
 

	
 
	std::vector<std::vector<std::string> > tmp;
 
	Value cmds(kArrayType);
 
	Json::Value cmds(Json::ValueType::arrayValue);
 
	BOOST_FOREACH(const std::string &command, commands) {
 
		escaped_list_separator<char> els('\\', ' ', '\"');
 
		tokenizer<escaped_list_separator<char> > tok(command, els);
 

	
 
		std::vector<std::string> tokens;
 
		for(tokenizer<escaped_list_separator<char> >::iterator beg=tok.begin(); beg!=tok.end(); ++beg) {
 
@@ -382,24 +371,23 @@ void APIServer::serve_instances_variables(Server *server, Server::session *sessi
 
		if (!session->admin && tokens[10] == "Admin") {
 
			continue;
 
		}
 

	
 
		tmp.push_back(tokens);
 

	
 
		Value cmd;
 
		cmd.SetObject();
 
		cmd.AddMember("name", StringRef(tokens[0].c_str()), json.GetAllocator());
 
		cmd.AddMember("desc", StringRef(tokens[2].c_str()), json.GetAllocator());
 
		cmd.AddMember("value", StringRef(tokens[4].c_str()), json.GetAllocator());
 
		cmd.AddMember("read_only", StringRef(tokens[6].c_str()), json.GetAllocator());
 
		cmd.AddMember("category", StringRef(tokens[8].c_str()), json.GetAllocator());
 
		cmd.AddMember("context", StringRef(tokens[12].c_str()), json.GetAllocator());
 
		cmds.PushBack(cmd, json.GetAllocator());
 
		Json::Value cmd;
 
		cmd["name"] = tokens[0];
 
		cmd["desc"] = tokens[2];
 
		cmd["value"] = tokens[4];
 
		cmd["read_only"] = tokens[6];
 
		cmd["category"] = tokens[8];
 
		cmd["context"] = tokens[12];
 
		cmds.append(cmd);
 
	}
 

	
 
	json.AddMember("variables", cmds, json.GetAllocator());
 
	json["variables"] = cmds;
 
	send_json(conn, json);
 
}
 

	
 

	
 
void APIServer::serve_instances_command_args(Server *server, Server::session *session, struct mg_connection *conn, struct http_message *hm) {
 
	std::string uri(hm->uri.p, hm->uri.len);
 
@@ -456,26 +444,24 @@ void APIServer::serve_instances_command_args(Server *server, Server::session *se
 

	
 
	
 

	
 
	std::vector<std::string> args;
 
	boost::split(args, response, boost::is_any_of("\n"));
 

	
 
	Document json;
 
	json.SetObject();
 
	json.AddMember("error", 0, json.GetAllocator());
 
	Json::Value json;
 
	json["error"] = 0;
 

	
 
	std::vector<std::vector<std::string> > tmp;
 
	Value argList(kArrayType);
 
	Json::Value argList(Json::ValueType::arrayValue);
 

	
 
	if (userContext && session->admin) {
 
		Value arg;
 
		arg.SetObject();
 
		arg.AddMember("name", "username", json.GetAllocator());
 
		arg.AddMember("label", "Username", json.GetAllocator());
 
		arg.AddMember("example", "", json.GetAllocator());
 
		argList.PushBack(arg, json.GetAllocator());
 
		Json::Value arg;
 
		arg["name"] = "username";
 
		arg["label"] = "Username";
 
		arg["example"] = "";
 
		argList.append(arg);
 
	}
 

	
 
	BOOST_FOREACH(const std::string &argument, args) {
 
		escaped_list_separator<char> els('\\', ' ', '\"');
 
		tokenizer<escaped_list_separator<char> > tok(argument, els);
 

	
 
@@ -487,22 +473,21 @@ void APIServer::serve_instances_command_args(Server *server, Server::session *se
 
		if (tokens.size() != 7) {
 
			continue;
 
		}
 

	
 
		tmp.push_back(tokens);
 

	
 
		Value arg;
 
		arg.SetObject();
 
		arg.AddMember("name", StringRef(tokens[0].c_str()), json.GetAllocator());
 
		arg.AddMember("label", StringRef(tokens[2].c_str()), json.GetAllocator());
 
		arg.AddMember("example", StringRef(tokens[4].c_str()), json.GetAllocator());
 
		arg.AddMember("type", StringRef(tokens[6].c_str()), json.GetAllocator());
 
		argList.PushBack(arg, json.GetAllocator());
 
		Json::Value arg;
 
		arg["name"] = tokens[0];
 
		arg["label"] = tokens[2];
 
		arg["example"] = tokens[4];
 
		arg["type"] = tokens[6];
 
		argList.append(arg);
 
	}
 

	
 
	json.AddMember("args", argList, json.GetAllocator());
 
	json["args"] = argList;
 
	send_json(conn, json);
 
}
 

	
 

	
 
void APIServer::serve_instances_execute(Server *server, Server::session *session, struct mg_connection *conn, struct http_message *hm) {
 
	std::string uri(hm->uri.p, hm->uri.len);
 
@@ -578,86 +563,82 @@ void APIServer::serve_instances_execute(Server *server, Server::session *session
 
		send_ack(conn, false, response);
 
	}
 

	
 
	std::vector<std::string> fields;
 
	boost::split(fields, response, boost::is_any_of("\n"));
 
	if (!fields.empty() && /*fields[0].find(" - ") != std::string::npos &&*/ (fields[0].find(": ") != std::string::npos || fields[0].find(":\"") != std::string::npos)) {
 
		Document json;
 
		json.SetObject();
 
		json.AddMember("error", 0, json.GetAllocator());
 
		Json::Value json;
 
		json["error"] = 0;
 

	
 
		std::vector<std::string> tmp;
 
		std::vector<std::string> tmp2;
 
		Value table(kArrayType);
 
		Json::Value table(Json::ValueType::arrayValue);
 

	
 
		BOOST_FOREACH(const std::string &line, fields) {
 
			escaped_list_separator<char> els('\\', ' ', '\"');
 
			tokenizer<escaped_list_separator<char> > tok(line, els);
 

	
 
			Value arg;
 
			arg.SetObject();
 
			Json::Value arg;
 

	
 
			std::string key;
 
			int i = 0;
 
			bool hasDesc = true;
 
			for(tokenizer<escaped_list_separator<char> >::iterator beg=tok.begin(); beg!=tok.end(); ++beg, ++i) {
 
				if (i == 1 && *beg != "-") {
 
					hasDesc = false;
 
				}
 
				if (i == 0) {
 
					tmp.push_back(*beg);
 
					arg.AddMember("Key", StringRef(tmp.back().c_str()), json.GetAllocator());
 
					arg["Key"] = tmp.back();
 
				}
 
				else if (i == 2 && hasDesc) {
 
					tmp.push_back(*beg);
 
					arg.AddMember("Description", StringRef(tmp.back().c_str()), json.GetAllocator());
 
					arg["Description"] = tmp.back();
 
				}
 
				else if (i > 1 || (!hasDesc && i > 0)) {
 
					if (key.empty()) {
 
						key = *beg;
 
					}
 
					else {
 
						tmp.push_back(key);
 
						tmp2.push_back(*beg);
 
						arg.AddMember(StringRef(tmp.back().c_str()), StringRef(tmp2.back().c_str()), json.GetAllocator());
 
						arg[tmp.back()] = tmp2.back();
 
						key = "";
 
					}
 
				}
 
			}
 
			table.PushBack(arg, json.GetAllocator());
 
			table.append(arg);
 
		}
 

	
 
		json.AddMember("table", table, json.GetAllocator());
 
		json.AddMember("message", StringRef(response.c_str()), json.GetAllocator());
 
		json["table"] = table;
 
		json["message"] = response;
 
		send_json(conn, json);
 
	}
 
	else {
 
		boost::replace_all(response, "\n", "<br/>");
 
		send_ack(conn, true, response);
 
	}
 
}
 

	
 
void APIServer::serve_users(Server *server, Server::session *session, struct mg_connection *conn, struct http_message *hm) {
 
	ALLOW_ONLY_ADMIN();
 

	
 
	Document json;
 
	json.SetObject();
 
	json.AddMember("error", 0, json.GetAllocator());
 
	Json::Value json;
 
	json["error"] = 0;
 

	
 
	std::vector<std::string> list;
 
	m_storage->getUsers(list);
 

	
 
	Value users(kArrayType);
 
	Json::Value users(Json::ValueType::arrayValue);
 
	BOOST_FOREACH(std::string &id, list) {
 
		Value user;
 
		user.SetObject();
 
		user.AddMember("username", StringRef(id.c_str()), json.GetAllocator());
 
		users.PushBack(user, json.GetAllocator());
 
		Json::Value user;
 
		user["username"] = id;
 
		users.append(user);
 
	}
 

	
 
	json.AddMember("users", users, json.GetAllocator());
 
	json["users"] = users;
 
	send_json(conn, json);
 
}
 

	
 
void APIServer::serve_users_add(Server *server, Server::session *session, struct mg_connection *conn, struct http_message *hm) {
 
	std::string user = get_http_var(hm, "username");
 
	std::string password = get_http_var(hm, "password");
spectrum_manager/src/APIServer.h
Show inline comments
 
@@ -24,26 +24,25 @@
 
#include <boost/foreach.hpp>
 
#include <boost/format.hpp>
 
#include <boost/algorithm/string.hpp>
 
#include <boost/assign.hpp>
 
#include <boost/bind.hpp>
 

	
 
#include "rapidjson/document.h"
 
#include <json/json.h>
 

	
 
#include "mongoose.h"
 
#include "managerconfig.h"
 
#include "server.h"
 

	
 
#include "transport/Config.h"
 
#include "transport/SQLite3Backend.h"
 
#include "transport/MySQLBackend.h"
 
#include "transport/PQXXBackend.h"
 
#include "transport/StorageBackend.h"
 

	
 
using namespace Transport;
 
using namespace rapidjson;
 

	
 
class APIServer {
 
	public:
 
		APIServer(ManagerConfig *config, StorageBackend *storage);
 

	
 
		virtual ~APIServer();
 
@@ -60,13 +59,13 @@ class APIServer {
 
		void serve_instances_command_args(Server *server, Server::session *sess, struct mg_connection *conn, struct http_message *hm);
 
		void serve_instances_execute(Server *server, Server::session *sess, struct mg_connection *conn, struct http_message *hm);
 
		void serve_instances_register(Server *server, Server::session *sess, struct mg_connection *conn, struct http_message *hm);
 
		void serve_users(Server *server, Server::session *sess, struct mg_connection *conn, struct http_message *hm);
 
		void serve_users_add(Server *server, Server::session *sess, struct mg_connection *conn, struct http_message *hm);
 
		void serve_users_remove(Server *server, Server::session *sess, struct mg_connection *conn, struct http_message *hm);
 
		void send_json(struct mg_connection *conn, const Document &d);
 
		void send_json(struct mg_connection *conn, const Json::Value &d);
 
		void send_ack(struct mg_connection *conn, bool error, const std::string &message);
 

	
 
	private:
 
		ManagerConfig *m_config;
 
		StorageBackend *m_storage;
 
};
tests/libtransport/HTTPRequest.cpp
Show inline comments
 
@@ -38,18 +38,18 @@ class HTTPRequestTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
 

	
 
		void tearDown (void) {
 
			tearMeDown();
 
			delete tp;
 
		}
 

	
 
	void handleResult(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data) {
 
	void handleResult(HTTPRequest *req, bool ok, Json::Value &resp, const std::string &data) {
 
		result = true;
 
	}
 

	
 
	void GET() {
 
		rapidjson::Document resp;
 
		Json::Value resp;
 
		HTTPRequest *req = new HTTPRequest(tp, HTTPRequest::Get, "http://spectrum.im/params.json", boost::bind(&HTTPRequestTest::handleResult, this, _1, _2, _3, _4));
 
		req->execute(resp);
 
		delete req;
 
	}
 

	
 
	void GETThreadPool() {
tests/libtransport/SlackRTM.cpp
Show inline comments
 
@@ -32,22 +32,23 @@ class SlackRTMTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
 
			delete m_rtm;
 
			delete m_idManager;
 
			tearMeDown();
 
		}
 

	
 
		void handleRTMStart() {
 
			rapidjson::Document json;
 
			json.Parse<0>(rtmStartPayload.c_str());
 
			Json::Value json;
 
			Json::Reader reader;
 
			bool ok = reader.parse(rtmStartPayload.c_str(), json);
 
			CPPUNIT_ASSERT_EQUAL(true, ok);
 
			m_rtm->handleRTMStart(NULL, true, json, rtmStartPayload);
 

	
 
			CPPUNIT_ASSERT_EQUAL(std::string("spectrum2"), m_idManager->getSelfName());
 
			CPPUNIT_ASSERT_EQUAL(std::string("U0KECRDJB"), m_idManager->getSelfId());
 
			CPPUNIT_ASSERT_EQUAL(std::string("owner"), m_idManager->getName("U0H6EEWNN"));
 
			CPPUNIT_ASSERT_EQUAL(std::string("C0H6B0SQM"), m_idManager->getId("spectrum2_contactlist"));
 
			CPPUNIT_ASSERT_EQUAL(true, m_idManager->hasMember("C0KH09UQ2", "U0KECRDJB"));
 
			CPPUNIT_ASSERT_EQUAL(false, m_idManager->hasMember("C0KH09UQ2", "U1KECRDJB"));
 
			CPPUNIT_ASSERT_MESSAGE("Has member", m_idManager->hasMember("C0KH09UQ2", "U1KECRDJB") == false);
 
		}
 

	
 
		void handlePayloadReceivedChannelJoined() {
 
			CPPUNIT_ASSERT_EQUAL(false, m_idManager->hasMember("C0KSK7V7E", "U0KECRDJB"));
 

	
 
			std::string payload = "{\"type\":\"channel_joined\",\"channel\":{\"id\":\"C0KSK7V7E\",\"name\":\"new_slack_channel\",\"is_channel\":true,\"created\":1454231085,\"creator\":\"U0H6EEWNN\",\"is_archived\":false,\"is_general\":false,\"is_member\":true,\"last_read\":\"1454231085.000002\",\"latest\":{\"user\":\"U0H6EEWNN\",\"type\":\"message\",\"subtype\":\"channel_join\",\"text\":\"<@U0H6EEWNN|owner> has joined the channel\",\"ts\":\"1454231085.000002\"},\"unread_count\":0,\"unread_count_display\":0,\"members\":[\"U0H6EEWNN\",\"U0KECRDJB\"],\"topic\":{\"value\":\"\",\"creator\":\"\",\"last_set\":0},\"purpose\":{\"value\":\"\",\"creator\":\"\",\"last_set\":0}}}";
0 comments (0 inline, 0 general)