aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitmodules3
-rw-r--r--README.md2
-rw-r--r--TODO3
m---------depends/rapidjson0
-rw-r--r--include/Program.h4
-rw-r--r--include/Storage.hpp5
-rw-r--r--plugins/Matrix.hpp14
-rw-r--r--project.conf5
-rw-r--r--src/Program.c10
-rw-r--r--src/QuickMedia.cpp6
-rw-r--r--src/Storage.cpp31
-rw-r--r--src/VideoPlayer.cpp2
-rw-r--r--src/plugins/Matrix.cpp770
13 files changed, 453 insertions, 402 deletions
diff --git a/.gitmodules b/.gitmodules
index 036c9dc..97f7a6d 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,6 @@
[submodule "depends/html-search"]
path = depends/html-search
url = https://git.dec05eba.com/html-search
+[submodule "depends/rapidjson"]
+ path = depends/rapidjson
+ url = https://git.dec05eba.com/rapidjson
diff --git a/README.md b/README.md
index d586ef9..df78618 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@ Config data, including manga progress is stored under `$HOME/.config/quickmedia`
Cache is stored under `$HOME/.cache/quickmedia`.
## Usage
```
-usage: QuickMedia <plugin> [--tor] [--use-system-mpv-config] [--dir <directory>] [-p <placeholder-text>]
+usage: QuickMedia <plugin> [--tor] [--use-system-mpv-config] [--dir <directory>]
OPTIONS:
plugin The plugin to use. Should be either 4chan, manganelo, mangatown, mangadex, youtube, nyaa.si, matrix, file-manager
--no-video Only play audio when playing a video. Disabled by default
diff --git a/TODO b/TODO
index 3e13fa9..950489e 100644
--- a/TODO
+++ b/TODO
@@ -105,4 +105,5 @@ Add file upload to 4chan.
Retry download if it fails, at least 3 times (observed to be needed for mangadex images).
Readd autocomplete, but make it better with a proper list. Also readd 4chan login page and manganelo creators page.
Fix logout/login in matrix. Currently it doesn't work because data is cleared while sync is in progress, leading to the first sync sometimes being with previous data...
-Modify sfml to use GL_COMPRESSED_LUMINANCE and other texture compression modes (in sf::Texture). This reduces memory usage by half. \ No newline at end of file
+Modify sfml to use GL_COMPRESSED_LUMINANCE and other texture compression modes (in sf::Texture). This reduces memory usage by half.
+Decrease memory usage even further (mostly in matrix /sync when part of large rooms) by using rapidjson SAX style API to stream downloaded json into the json parser, instead of using download_to_string with accumulate_string. \ No newline at end of file
diff --git a/depends/rapidjson b/depends/rapidjson
new file mode 160000
+Subproject 58dbb57768c257ea9cbb0112ad71b572906c8b7
diff --git a/include/Program.h b/include/Program.h
index cd45b30..3cbf09e 100644
--- a/include/Program.h
+++ b/include/Program.h
@@ -2,7 +2,6 @@
#define QUICKMEDIA_PROGRAM_H
#include <sys/types.h>
-#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
@@ -26,7 +25,8 @@ int exec_program(const char **args, ProgramOutputCallback output_callback, void
// Return the exit status, or a negative value if waiting failed
int wait_program(pid_t process_id);
-bool wait_program_non_blocking(pid_t process_id, int *status);
+/* Returns 1 if the program quit and exited properly (non-0 exit codes also count as exiting properly) */
+int wait_program_non_blocking(pid_t process_id, int *status);
/*
@args need to have at least 2 arguments. The first which is the program name
diff --git a/include/Storage.hpp b/include/Storage.hpp
index 8a1bbfa..10cbbb2 100644
--- a/include/Storage.hpp
+++ b/include/Storage.hpp
@@ -4,6 +4,10 @@
#include <functional>
#include <filesystem>
#include <json/value.h>
+#ifdef Bool
+#undef Bool
+#endif
+#include <rapidjson/document.h>
namespace QuickMedia {
// Return false to stop the iterator
@@ -29,6 +33,7 @@ namespace QuickMedia {
bool read_file_as_json(const Path &filepath, Json::Value &result);
bool save_json_to_file_atomic(const Path &path, const Json::Value &json);
+ bool save_json_to_file_atomic(const Path &path, const rapidjson::Value &json);
bool is_program_executable_by_name(const char *name);
} \ No newline at end of file
diff --git a/plugins/Matrix.hpp b/plugins/Matrix.hpp
index 5819420..09895b0 100644
--- a/plugins/Matrix.hpp
+++ b/plugins/Matrix.hpp
@@ -6,7 +6,7 @@
#include <SFML/Graphics/Color.hpp>
#include <unordered_map>
#include <mutex>
-#include <json/value.h>
+#include <rapidjson/document.h>
namespace QuickMedia {
// Dummy, only play one video. TODO: Play all videos in room, as related videos?
@@ -150,19 +150,19 @@ namespace QuickMedia {
bool use_tor = false;
private:
- PluginResult sync_response_to_body_items(const Json::Value &root, RoomSyncMessages &room_messages);
+ PluginResult sync_response_to_body_items(const rapidjson::Document &root, RoomSyncMessages &room_messages);
PluginResult get_previous_room_messages(std::shared_ptr<RoomData> &room_data);
- void events_add_user_info(const Json::Value &events_json, RoomData *room_data);
- void events_add_user_read_markers(const Json::Value &events_json, RoomData *room_data);
- void events_add_messages(const Json::Value &events_json, std::shared_ptr<RoomData> &room_data, MessageDirection message_dir, RoomSyncMessages *room_messages, bool has_unread_notifications);
- void events_set_room_name(const Json::Value &events_json, RoomData *room_data);
+ void events_add_user_info(const rapidjson::Value &events_json, RoomData *room_data);
+ void events_add_user_read_markers(const rapidjson::Value &events_json, RoomData *room_data);
+ void events_add_messages(const rapidjson::Value &events_json, std::shared_ptr<RoomData> &room_data, MessageDirection message_dir, RoomSyncMessages *room_messages, bool has_unread_notifications);
+ void events_set_room_name(const rapidjson::Value &events_json, RoomData *room_data);
PluginResult upload_file(const std::string &room_id, const std::string &filepath, UploadInfo &file_info, UploadInfo &thumbnail_info, std::string &err_msg);
std::shared_ptr<Message> get_edited_message_original_message(RoomData *room_data, std::shared_ptr<Message> message);
std::shared_ptr<RoomData> get_room_by_id(const std::string &id);
void add_room(std::shared_ptr<RoomData> room);
- DownloadResult download_json(Json::Value &result, const std::string &url, std::vector<CommandArg> additional_args, bool use_browser_useragent = false, std::string *err_msg = nullptr) const;
+ DownloadResult download_json(rapidjson::Document &result, const std::string &url, std::vector<CommandArg> additional_args, bool use_browser_useragent = false, std::string *err_msg = nullptr) const;
private:
std::unordered_map<std::string, std::shared_ptr<RoomData>> room_data_by_id;
std::mutex room_data_mutex;
diff --git a/project.conf b/project.conf
index e671b91..3950938 100644
--- a/project.conf
+++ b/project.conf
@@ -4,8 +4,9 @@ type = "executable"
version = "0.1.0"
platforms = ["posix"]
-[config]
-error_on_warning = "true"
+# This needs to be commented out for now because rapidjson depends on undefined behavior according to gcc...
+#[config]
+#error_on_warning = "true"
[lang.cpp]
version = "c++17"
diff --git a/src/Program.c b/src/Program.c
index 0ad19f2..2307798 100644
--- a/src/Program.c
+++ b/src/Program.c
@@ -116,26 +116,26 @@ int wait_program(pid_t process_id) {
return WEXITSTATUS(status);
}
-bool wait_program_non_blocking(pid_t process_id, int *status) {
+int wait_program_non_blocking(pid_t process_id, int *status) {
int s;
int wait_result = waitpid(process_id, &s, WNOHANG);
if(wait_result == -1) {
perror("waitpid failed");
*status = -errno;
- return false;
+ return 0;
} else if(wait_result == 0) {
/* the child process is still running */
*status = 0;
- return false;
+ return 0;
}
if(!WIFEXITED(s)) {
*status = -4;
- return false;
+ return 0;
}
*status = WEXITSTATUS(s);
- return true;
+ return 1;
}
int exec_program_async(const char **args, pid_t *result_process_id) {
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp
index 9a6ff3f..0139f37 100644
--- a/src/QuickMedia.cpp
+++ b/src/QuickMedia.cpp
@@ -391,7 +391,7 @@ namespace QuickMedia {
}
static void usage() {
- fprintf(stderr, "usage: QuickMedia <plugin> [--tor] [--no-video] [--use-system-mpv-config] [--dir <directory>] [-p <placeholder-text>]\n");
+ fprintf(stderr, "usage: QuickMedia <plugin> [--tor] [--no-video] [--use-system-mpv-config] [--dir <directory>]\n");
fprintf(stderr, "OPTIONS:\n");
fprintf(stderr, " plugin The plugin to use. Should be either 4chan, manganelo, mangatown, mangadex, pornhub, youtube, nyaa.si, matrix, file-manager\n");
fprintf(stderr, " --no-video Only play audio when playing a video. Disabled by default\n");
@@ -466,6 +466,10 @@ namespace QuickMedia {
if(i < argc - 1) {
start_dir = argv[i + 1];
++i;
+ } else {
+ fprintf(stderr, "Missing directory after --dir argument\n");
+ usage();
+ return -1;
}
} else if(argv[i][0] == '-') {
fprintf(stderr, "Invalid option %s\n", argv[i]);
diff --git a/src/Storage.cpp b/src/Storage.cpp
index c9dfb17..a1dc777 100644
--- a/src/Storage.cpp
+++ b/src/Storage.cpp
@@ -5,6 +5,8 @@
#include <assert.h>
#include <json/reader.h>
#include <json/writer.h>
+#include <rapidjson/writer.h>
+#include <rapidjson/stringbuffer.h>
#include <unordered_set>
#if OS_FAMILY == OS_FAMILY_POSIX
@@ -137,12 +139,12 @@ namespace QuickMedia {
return -1;
}
- int file_overwrite(const Path &path, const std::string &data) {
+ static int file_overwrite(const Path &path, const char *str, size_t size) {
FILE *file = fopen(path.data.c_str(), "wb");
if(!file)
return -1;
- if(fwrite(data.data(), 1, data.size(), file) != data.size()) {
+ if(fwrite(str, 1, size, file) != size) {
fclose(file);
return -1;
}
@@ -150,6 +152,10 @@ namespace QuickMedia {
return fclose(file);
}
+ int file_overwrite(const Path &path, const std::string &data) {
+ return file_overwrite(path, data.c_str(), data.size());
+ }
+
void for_files_in_dir(const Path &path, FileIteratorCallback callback) {
try {
for(auto &p : std::filesystem::directory_iterator(path.data)) {
@@ -226,6 +232,27 @@ namespace QuickMedia {
return true;
}
+ bool save_json_to_file_atomic(const Path &path, const rapidjson::Value &json) {
+ Path tmp_path = path;
+ tmp_path.append(".tmp");
+
+ rapidjson::StringBuffer buffer;
+ rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
+ json.Accept(writer);
+
+ Json::StreamWriterBuilder json_builder;
+ if(file_overwrite(tmp_path, buffer.GetString(), buffer.GetSize()) != 0)
+ return false;
+
+ // Rename is atomic under posix!
+ if(rename(tmp_path.data.c_str(), path.data.c_str()) != 0) {
+ perror("save_json_to_file_atomic rename");
+ return false;
+ }
+
+ return true;
+ }
+
bool is_program_executable_by_name(const char *name) {
// TODO: Implement for Windows. Windows also uses semicolon instead of colon as a separator
char *env = getenv("PATH");
diff --git a/src/VideoPlayer.cpp b/src/VideoPlayer.cpp
index a79ffd7..ce2fa82 100644
--- a/src/VideoPlayer.cpp
+++ b/src/VideoPlayer.cpp
@@ -1,6 +1,6 @@
#include "../include/VideoPlayer.hpp"
-#include "../include/Program.h"
#include "../include/Storage.hpp"
+#include "../include/Program.h"
#include <string>
#include <json/reader.h>
#include <json/writer.h>
diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp
index 4de7045..3637d41 100644
--- a/src/plugins/Matrix.cpp
+++ b/src/plugins/Matrix.cpp
@@ -1,8 +1,8 @@
#include "../../plugins/Matrix.hpp"
#include "../../include/Storage.hpp"
#include "../../include/StringUtils.hpp"
-#include <json/reader.h>
-#include <json/writer.h>
+#include <rapidjson/writer.h>
+#include <rapidjson/stringbuffer.h>
#include <fcntl.h>
#include <unistd.h>
@@ -21,6 +21,15 @@
static const char* SERVICE_NAME = "matrix";
+static rapidjson::Value nullValue(rapidjson::kNullType);
+
+static const rapidjson::Value& GetMember(const rapidjson::Value &obj, const char *key) {
+ auto it = obj.FindMember(key);
+ if(it != obj.MemberEnd())
+ return it->value;
+ return nullValue;
+}
+
namespace QuickMedia {
std::shared_ptr<UserInfo> RoomData::get_user_by_id(const std::string &user_id) {
std::lock_guard<std::mutex> lock(room_mutex);
@@ -114,7 +123,7 @@ namespace QuickMedia {
else
snprintf(url, sizeof(url), "%s/_matrix/client/r0/sync?timeout=30000&since=%s", homeserver.c_str(), next_batch.c_str());
- Json::Value json_root;
+ rapidjson::Document json_root;
DownloadResult download_result = download_json(json_root, url, std::move(additional_args), true);
if(download_result != DownloadResult::OK) return download_result_to_plugin_result(download_result);
@@ -122,9 +131,9 @@ namespace QuickMedia {
if(result != PluginResult::OK)
return result;
- const Json::Value &next_batch_json = json_root["next_batch"];
- if(next_batch_json.isString()) {
- next_batch = next_batch_json.asString();
+ const rapidjson::Value &next_batch_json = GetMember(json_root, "next_batch");
+ if(next_batch_json.IsString()) {
+ next_batch = next_batch_json.GetString();
fprintf(stderr, "Matrix: next batch: %s\n", next_batch.c_str());
} else {
fprintf(stderr, "Matrix: missing next batch\n");
@@ -138,29 +147,29 @@ namespace QuickMedia {
{ "-H", "Authorization: Bearer " + access_token }
};
- Json::Value json_root;
+ rapidjson::Document json_root;
DownloadResult download_result = download_json(json_root, homeserver + "/_matrix/client/r0/joined_rooms", std::move(additional_args), true);
if(download_result != DownloadResult::OK) return download_result_to_plugin_result(download_result);
- if(!json_root.isObject())
+ if(!json_root.IsObject())
return PluginResult::ERR;
- const Json::Value &joined_rooms_json = json_root["joined_rooms"];
- if(!joined_rooms_json.isArray())
+ const rapidjson::Value &joined_rooms_json = GetMember(json_root, "joined_rooms");
+ if(!joined_rooms_json.IsArray())
return PluginResult::ERR;
- for(const Json::Value &room_id_json : joined_rooms_json) {
- if(!room_id_json.isString())
+ for(const rapidjson::Value &room_id_json : joined_rooms_json.GetArray()) {
+ if(!room_id_json.IsString())
continue;
- std::string room_id_str = room_id_json.asString();
+ std::string room_id_str = room_id_json.GetString();
std::string room_name;
std::string avatar_url;
auto room = get_room_by_id(room_id_str);
if(!room) {
room = std::make_shared<RoomData>();
- room->id = room_id_json.asString();
+ room->id = room_id_json.GetString();
add_room(std::move(room));
room_name = room_id_str;
fprintf(stderr, "Missing room %s from /sync, adding in joined_rooms\n", room_id_str.c_str());
@@ -277,27 +286,27 @@ namespace QuickMedia {
return PluginResult::OK;
}
- PluginResult Matrix::sync_response_to_body_items(const Json::Value &root, RoomSyncMessages &room_messages) {
- if(!root.isObject())
+ PluginResult Matrix::sync_response_to_body_items(const rapidjson::Document &root, RoomSyncMessages &room_messages) {
+ if(!root.IsObject())
return PluginResult::ERR;
- const Json::Value &rooms_json = root["rooms"];
- if(!rooms_json.isObject())
+ const rapidjson::Value &rooms_json = GetMember(root, "rooms");
+ if(!rooms_json.IsObject())
return PluginResult::OK;
- const Json::Value &join_json = rooms_json["join"];
- if(!join_json.isObject())
+ const rapidjson::Value &join_json = GetMember(rooms_json, "join");
+ if(!join_json.IsObject())
return PluginResult::OK;
- for(Json::Value::const_iterator it = join_json.begin(); it != join_json.end(); ++it) {
- if(!it->isObject())
+ for(auto const &it : join_json.GetObject()) {
+ if(!it.value.IsObject())
continue;
- Json::Value room_id = it.key();
- if(!room_id.isString())
+ const rapidjson::Value &room_id = it.name;
+ if(!room_id.IsString())
continue;
- std::string room_id_str = room_id.asString();
+ std::string room_id_str = room_id.GetString();
auto room = get_room_by_id(room_id_str);
if(!room) {
@@ -306,40 +315,40 @@ namespace QuickMedia {
add_room(room);
}
- const Json::Value &state_json = (*it)["state"];
- if(state_json.isObject()) {
- const Json::Value &events_json = state_json["events"];
+ const rapidjson::Value &state_json = GetMember(it.value, "state");
+ if(state_json.IsObject()) {
+ const rapidjson::Value &events_json = GetMember(state_json, "events");
events_add_user_info(events_json, room.get());
events_set_room_name(events_json, room.get());
}
- const Json::Value &timeline_json = (*it)["timeline"];
- if(timeline_json.isObject()) {
+ const rapidjson::Value &timeline_json = GetMember(it.value, "timeline");
+ if(timeline_json.IsObject()) {
if(room->prev_batch.empty()) {
// This may be non-existent if this is the first event in the room
- const Json::Value &prev_batch_json = timeline_json["prev_batch"];
- if(prev_batch_json.isString())
- room->prev_batch = prev_batch_json.asString();
+ const rapidjson::Value &prev_batch_json = GetMember(timeline_json, "prev_batch");
+ if(prev_batch_json.IsString())
+ room->prev_batch = prev_batch_json.GetString();
}
// TODO: Is there no better way to check for notifications? this is not robust...
bool has_unread_notifications = false;
- const Json::Value &unread_notification_json = (*it)["unread_notifications"];
- if(unread_notification_json.isObject()) {
- const Json::Value &highlight_count_json = unread_notification_json["highlight_count"];
- if(highlight_count_json.isNumeric() && highlight_count_json.asInt64() > 0)
+ const rapidjson::Value &unread_notification_json = GetMember(it.value, "unread_notifications");
+ if(unread_notification_json.IsObject()) {
+ const rapidjson::Value &highlight_count_json = GetMember(unread_notification_json, "highlight_count");
+ if(highlight_count_json.IsNumber() && highlight_count_json.GetInt64() > 0)
has_unread_notifications = true;
}
- const Json::Value &events_json = timeline_json["events"];
+ const rapidjson::Value &events_json = GetMember(timeline_json, "events");
events_add_user_info(events_json, room.get());
events_add_messages(events_json, room, MessageDirection::AFTER, &room_messages, has_unread_notifications);
events_set_room_name(events_json, room.get());
}
- const Json::Value &ephemeral_json = (*it)["ephemeral"];
- if(ephemeral_json.isObject()) {
- const Json::Value &events_json = ephemeral_json["events"];
+ const rapidjson::Value &ephemeral_json = GetMember(it.value, "ephemeral");
+ if(ephemeral_json.IsObject()) {
+ const rapidjson::Value &events_json = GetMember(ephemeral_json, "events");
events_add_user_read_markers(events_json, room.get());
}
}
@@ -360,38 +369,38 @@ namespace QuickMedia {
return result;
}
- void Matrix::events_add_user_info(const Json::Value &events_json, RoomData *room_data) {
- if(!events_json.isArray())
+ void Matrix::events_add_user_info(const rapidjson::Value &events_json, RoomData *room_data) {
+ if(!events_json.IsArray())
return;
- for(const Json::Value &event_item_json : events_json) {
- if(!event_item_json.isObject())
+ for(const rapidjson::Value &event_item_json : events_json.GetArray()) {
+ if(!event_item_json.IsObject())
continue;
- const Json::Value &type_json = event_item_json["type"];
- if(!type_json.isString() || strcmp(type_json.asCString(), "m.room.member") != 0)
+ const rapidjson::Value &type_json = GetMember(event_item_json, "type");
+ if(!type_json.IsString() || strcmp(type_json.GetString(), "m.room.member") != 0)
continue;
- const Json::Value &sender_json = event_item_json["sender"];
- if(!sender_json.isString())
+ const rapidjson::Value &sender_json = GetMember(event_item_json, "sender");
+ if(!sender_json.IsString())
continue;
- const Json::Value &content_json = event_item_json["content"];
- if(!content_json.isObject())
+ const rapidjson::Value &content_json = GetMember(event_item_json, "content");
+ if(!content_json.IsObject())
continue;
- const Json::Value &membership_json = content_json["membership"];
- if(!membership_json.isString() || strcmp(membership_json.asCString(), "join") != 0)
+ const rapidjson::Value &membership_json = GetMember(content_json, "membership");
+ if(!membership_json.IsString() || strcmp(membership_json.GetString(), "join") != 0)
continue;
std::string avatar_url_str;
- const Json::Value &avatar_url_json = content_json["avatar_url"];
- if(avatar_url_json.isString())
- avatar_url_str = avatar_url_json.asString();
+ const rapidjson::Value &avatar_url_json = GetMember(content_json, "avatar_url");
+ if(avatar_url_json.IsString())
+ avatar_url_str = avatar_url_json.GetString();
- const Json::Value &display_name_json = content_json["displayname"];
+ const rapidjson::Value &display_name_json = GetMember(content_json, "displayname");
- std::string sender_json_str = sender_json.asString();
+ std::string sender_json_str = sender_json.GetString();
auto user_info = std::make_shared<UserInfo>();
user_info->user_id = sender_json_str;
@@ -400,7 +409,7 @@ namespace QuickMedia {
user_info->avatar_url.erase(user_info->avatar_url.begin(), user_info->avatar_url.begin() + 6);
if(!user_info->avatar_url.empty())
user_info->avatar_url = homeserver + "/_matrix/media/r0/thumbnail/" + user_info->avatar_url + "?width=32&height=32&method=crop";
- user_info->display_name = display_name_json.isString() ? display_name_json.asString() : sender_json_str;
+ user_info->display_name = display_name_json.IsString() ? display_name_json.GetString() : sender_json_str;
user_info->display_name_color = user_id_to_color(sender_json_str);
// Overwrites user data
@@ -408,47 +417,47 @@ namespace QuickMedia {
}
}
- void Matrix::events_add_user_read_markers(const Json::Value &events_json, RoomData *room_data) {
- if(!events_json.isArray())
+ void Matrix::events_add_user_read_markers(const rapidjson::Value &events_json, RoomData *room_data) {
+ if(!events_json.IsArray())
return;
- for(const Json::Value &event_item_json : events_json) {
- if(!event_item_json.isObject())
+ for(const rapidjson::Value &event_item_json : events_json.GetArray()) {
+ if(!event_item_json.IsObject())
continue;
- const Json::Value &type_json = event_item_json["type"];
- if(!type_json.isString() || strcmp(type_json.asCString(), "m.receipt") != 0)
+ const rapidjson::Value &type_json = GetMember(event_item_json, "type");
+ if(!type_json.IsString() || strcmp(type_json.GetString(), "m.receipt") != 0)
continue;
- const Json::Value &content_json = event_item_json["content"];
- if(!content_json.isObject())
+ const rapidjson::Value &content_json = GetMember(event_item_json, "content");
+ if(!content_json.IsObject())
continue;
- for(Json::Value::const_iterator it = content_json.begin(); it != content_json.end(); ++it) {
- if(!it->isObject())
+ for(auto const &it2 : content_json.GetObject()) {
+ if(!it2.value.IsObject())
continue;
- Json::Value event_id_json = it.key();
- if(!event_id_json.isString())
+ const rapidjson::Value &event_id_json = it2.name;
+ if(!event_id_json.IsString())
continue;
- const Json::Value &read_json = (*it)["m.read"];
- if(!read_json.isObject())
+ const rapidjson::Value &read_json = GetMember(it2.value, "m.read");
+ if(!read_json.IsObject())
continue;
- std::string event_id_str = event_id_json.asString();
+ std::string event_id_str = event_id_json.GetString();
- for(Json::Value::const_iterator user_id_it = read_json.begin(); user_id_it != read_json.end(); ++user_id_it) {
- if(!user_id_it->isObject())
+ for(auto const &it3 : read_json.GetObject()) {
+ if(!it3.value.IsObject())
continue;
- Json::Value user_id_json = user_id_it.key();
- if(!user_id_json.isString())
+ const rapidjson::Value &user_id_json = it3.name;
+ if(!user_id_json.IsString())
continue;
- auto user = room_data->get_user_by_id(user_id_json.asString());
+ auto user = room_data->get_user_by_id(user_id_json.GetString());
if(!user) {
- fprintf(stderr, "Receipt read receipt for unknown user: %s, ignoring...\n", user_id_json.asCString());
+ fprintf(stderr, "Receipt read receipt for unknown user: %s, ignoring...\n", user_id_json.GetString());
continue;
}
@@ -458,12 +467,12 @@ namespace QuickMedia {
}
}
- static std::string message_content_extract_thumbnail_url(const Json::Value &content_json, const std::string &homeserver) {
- const Json::Value &info_json = content_json["info"];
- if(info_json.isObject()) {
- const Json::Value &thumbnail_url_json = info_json["thumbnail_url"];
- if(thumbnail_url_json.isString()) {
- std::string thumbnail_str = thumbnail_url_json.asString();
+ static std::string message_content_extract_thumbnail_url(const rapidjson::Value &content_json, const std::string &homeserver) {
+ const rapidjson::Value &info_json = GetMember(content_json, "info");
+ if(info_json.IsObject()) {
+ const rapidjson::Value &thumbnail_url_json = GetMember(info_json, "thumbnail_url");
+ if(thumbnail_url_json.IsString()) {
+ std::string thumbnail_str = thumbnail_url_json.GetString();
if(strncmp(thumbnail_str.c_str(), "mxc://", 6) == 0) {
thumbnail_str.erase(thumbnail_str.begin(), thumbnail_str.begin() + 6);
return homeserver + "/_matrix/media/r0/download/" + std::move(thumbnail_str);
@@ -524,8 +533,8 @@ namespace QuickMedia {
return false;
}
- void Matrix::events_add_messages(const Json::Value &events_json, std::shared_ptr<RoomData> &room_data, MessageDirection message_dir, RoomSyncMessages *room_messages, bool has_unread_notifications) {
- if(!events_json.isArray())
+ void Matrix::events_add_messages(const rapidjson::Value &events_json, std::shared_ptr<RoomData> &room_data, MessageDirection message_dir, RoomSyncMessages *room_messages, bool has_unread_notifications) {
+ if(!events_json.IsArray())
return;
std::vector<std::shared_ptr<Message>> *room_sync_messages = nullptr;
@@ -534,32 +543,32 @@ namespace QuickMedia {
std::vector<std::shared_ptr<Message>> new_messages;
- for(const Json::Value &event_item_json : events_json) {
- if(!event_item_json.isObject())
+ for(const rapidjson::Value &event_item_json : events_json.GetArray()) {
+ if(!event_item_json.IsObject())
continue;
- const Json::Value &type_json = event_item_json["type"];
- if(!type_json.isString() || strcmp(type_json.asCString(), "m.room.message") != 0)
+ const rapidjson::Value &type_json = GetMember(event_item_json, "type");
+ if(!type_json.IsString() || strcmp(type_json.GetString(), "m.room.message") != 0)
continue;
- const Json::Value &sender_json = event_item_json["sender"];
- if(!sender_json.isString())
+ const rapidjson::Value &sender_json = GetMember(event_item_json, "sender");
+ if(!sender_json.IsString())
continue;
- std::string sender_json_str = sender_json.asString();
+ std::string sender_json_str = sender_json.GetString();
- const Json::Value &event_id_json = event_item_json["event_id"];
- if(!event_id_json.isString())
+ const rapidjson::Value &event_id_json = GetMember(event_item_json, "event_id");
+ if(!event_id_json.IsString())
continue;
- std::string event_id_str = event_id_json.asString();
+ std::string event_id_str = event_id_json.GetString();
- const Json::Value &content_json = event_item_json["content"];
- if(!content_json.isObject())
+ const rapidjson::Value &content_json = GetMember(event_item_json, "content");
+ if(!content_json.IsObject())
continue;
- const Json::Value &content_type = content_json["msgtype"];
- if(!content_type.isString())
+ const rapidjson::Value &content_type = GetMember(content_json, "msgtype");
+ if(!content_type.IsString())
continue;
auto user = room_data->get_user_by_id(sender_json_str);
@@ -569,22 +578,22 @@ namespace QuickMedia {
continue;
}
- const Json::Value &body_json = content_json["body"];
- if(!body_json.isString())
+ const rapidjson::Value &body_json = GetMember(content_json, "body");
+ if(!body_json.IsString())
continue;
time_t timestamp = 0;
- const Json::Value &origin_server_ts = event_item_json["origin_server_ts"];
- if(origin_server_ts.isNumeric())
- timestamp = origin_server_ts.asInt64();
+ const rapidjson::Value &origin_server_ts = GetMember(event_item_json, "origin_server_ts");
+ if(origin_server_ts.IsNumber())
+ timestamp = origin_server_ts.GetInt64();
std::string replaces_event_id;
- const Json::Value &relates_to_json = content_json["m.relates_to"];
- if(relates_to_json.isObject()) {
- const Json::Value &replaces_event_id_json = relates_to_json["event_id"];
- const Json::Value &rel_type_json = relates_to_json["rel_type"];
- if(replaces_event_id_json.isString() && rel_type_json.isString() && strcmp(rel_type_json.asCString(), "m.replace") == 0)
- replaces_event_id = replaces_event_id_json.asString();
+ const rapidjson::Value &relates_to_json = GetMember(content_json, "m.relates_to");
+ if(relates_to_json.IsObject()) {
+ const rapidjson::Value &replaces_event_id_json = GetMember(relates_to_json, "event_id");
+ const rapidjson::Value &rel_type_json = GetMember(relates_to_json, "rel_type");
+ if(replaces_event_id_json.IsString() && rel_type_json.IsString() && strcmp(rel_type_json.GetString(), "m.replace") == 0)
+ replaces_event_id = replaces_event_id_json.GetString();
}
auto message = std::make_shared<Message>();
@@ -592,48 +601,48 @@ namespace QuickMedia {
// TODO: Also show joins, leave, invites, bans, kicks, mutes, etc
- if(strcmp(content_type.asCString(), "m.text") == 0) {
+ if(strcmp(content_type.GetString(), "m.text") == 0) {
message->type = MessageType::TEXT;
- } else if(strcmp(content_type.asCString(), "m.image") == 0) {
- const Json::Value &url_json = content_json["url"];
- if(!url_json.isString() || strncmp(url_json.asCString(), "mxc://", 6) != 0)
+ } else if(strcmp(content_type.GetString(), "m.image") == 0) {
+ const rapidjson::Value &url_json = GetMember(content_json, "url");
+ if(!url_json.IsString() || strncmp(url_json.GetString(), "mxc://", 6) != 0)
continue;
- message->url = homeserver + "/_matrix/media/r0/download/" + url_json.asString().substr(6);
+ message->url = homeserver + "/_matrix/media/r0/download/" + (url_json.GetString() + 6);
message->thumbnail_url = message_content_extract_thumbnail_url(content_json, homeserver);
message->type = MessageType::IMAGE;
- } else if(strcmp(content_type.asCString(), "m.video") == 0) {
- const Json::Value &url_json = content_json["url"];
- if(!url_json.isString() || strncmp(url_json.asCString(), "mxc://", 6) != 0)
+ } else if(strcmp(content_type.GetString(), "m.video") == 0) {
+ const rapidjson::Value &url_json = GetMember(content_json, "url");
+ if(!url_json.IsString() || strncmp(url_json.GetString(), "mxc://", 6) != 0)
continue;
- message->url = homeserver + "/_matrix/media/r0/download/" + url_json.asString().substr(6);
+ message->url = homeserver + "/_matrix/media/r0/download/" + (url_json.GetString() + 6);
message->thumbnail_url = message_content_extract_thumbnail_url(content_json, homeserver);
message->type = MessageType::VIDEO;
- } else if(strcmp(content_type.asCString(), "m.audio") == 0) {
- const Json::Value &url_json = content_json["url"];
- if(!url_json.isString() || strncmp(url_json.asCString(), "mxc://", 6) != 0)
+ } else if(strcmp(content_type.GetString(), "m.audio") == 0) {
+ const rapidjson::Value &url_json = GetMember(content_json, "url");
+ if(!url_json.IsString() || strncmp(url_json.GetString(), "mxc://", 6) != 0)
continue;
- message->url = homeserver + "/_matrix/media/r0/download/" + url_json.asString().substr(6);
+ message->url = homeserver + "/_matrix/media/r0/download/" + (url_json.GetString() + 6);
message->type = MessageType::AUDIO;
- } else if(strcmp(content_type.asCString(), "m.file") == 0) {
- const Json::Value &url_json = content_json["url"];
- if(!url_json.isString() || strncmp(url_json.asCString(), "mxc://", 6) != 0)
+ } else if(strcmp(content_type.GetString(), "m.file") == 0) {
+ const rapidjson::Value &url_json = GetMember(content_json, "url");
+ if(!url_json.IsString() || strncmp(url_json.GetString(), "mxc://", 6) != 0)
continue;
- message->url = homeserver + "/_matrix/media/r0/download/" + url_json.asString().substr(6);
+ message->url = homeserver + "/_matrix/media/r0/download/" + (url_json.GetString() + 6);
message->type = MessageType::FILE;
- } else if(strcmp(content_type.asCString(), "m.emote") == 0) { // this is a /me message, TODO: show /me messages differently
+ } else if(strcmp(content_type.GetString(), "m.emote") == 0) { // this is a /me message, TODO: show /me messages differently
message->type = MessageType::TEXT;
prefix = "*" + user->display_name + "* ";
- } else if(strcmp(content_type.asCString(), "m.notice") == 0) { // TODO: show notices differently
+ } else if(strcmp(content_type.GetString(), "m.notice") == 0) { // TODO: show notices differently
message->type = MessageType::TEXT;
prefix = "* NOTICE * ";
- } else if(strcmp(content_type.asCString(), "m.location") == 0) { // TODO: show locations differently
- const Json::Value &geo_uri_json = content_json["geo_uri"];
- if(geo_uri_json.isString())
- prefix = geo_uri_json.asString() + " | ";
+ } else if(strcmp(content_type.GetString(), "m.location") == 0) { // TODO: show locations differently
+ const rapidjson::Value &geo_uri_json = GetMember(content_json, "geo_uri");
+ if(geo_uri_json.IsString())
+ prefix = geo_uri_json.GetString() + std::string(" | ");
message->type = MessageType::TEXT;
message->thumbnail_url = message_content_extract_thumbnail_url(content_json, homeserver);
@@ -643,7 +652,7 @@ namespace QuickMedia {
message->user = user;
message->event_id = event_id_str;
- message->body = prefix + body_json.asString();
+ message->body = prefix + body_json.GetString();
message->replaces_event_id = std::move(replaces_event_id);
// TODO: Is @room ok? shouldn't we also check if the user has permission to do @room? (only when notifications are limited to @mentions)
if(has_unread_notifications && !username.empty())
@@ -686,55 +695,55 @@ namespace QuickMedia {
return result;
}
- void Matrix::events_set_room_name(const Json::Value &events_json, RoomData *room_data) {
- if(!events_json.isArray())
+ void Matrix::events_set_room_name(const rapidjson::Value &events_json, RoomData *room_data) {
+ if(!events_json.IsArray())
return;
- for(const Json::Value &event_item_json : events_json) {
- if(!event_item_json.isObject())
+ for(const rapidjson::Value &event_item_json : events_json.GetArray()) {
+ if(!event_item_json.IsObject())
continue;
- const Json::Value &type_json = event_item_json["type"];
- if(!type_json.isString() || strcmp(type_json.asCString(), "m.room.name") != 0)
+ const rapidjson::Value &type_json = GetMember(event_item_json, "type");
+ if(!type_json.IsString() || strcmp(type_json.GetString(), "m.room.name") != 0)
continue;
- const Json::Value &content_json = event_item_json["content"];
- if(!content_json.isObject())
+ const rapidjson::Value &content_json = GetMember(event_item_json, "content");
+ if(!content_json.IsObject())
continue;
- const Json::Value &name_json = content_json["name"];
- if(!name_json.isString())
+ const rapidjson::Value &name_json = GetMember(content_json, "name");
+ if(!name_json.IsString())
continue;
- room_data->name = name_json.asString();
+ room_data->name = name_json.GetString();
}
std::vector<std::shared_ptr<UserInfo>> users_excluding_me;
if(room_data->name.empty() || room_data->avatar_url.empty())
users_excluding_me = room_data->get_users_excluding_me(user_id); // TODO: What about thread safety with user_id? its reset in /logout
- for(const Json::Value &event_item_json : events_json) {
- if(!event_item_json.isObject())
+ for(const rapidjson::Value &event_item_json : events_json.GetArray()) {
+ if(!event_item_json.IsObject())
continue;
- const Json::Value &type_json = event_item_json["type"];
- if(!type_json.isString() || strcmp(type_json.asCString(), "m.room.create") != 0)
+ const rapidjson::Value &type_json = GetMember(event_item_json, "type");
+ if(!type_json.IsString() || strcmp(type_json.GetString(), "m.room.create") != 0)
continue;
- const Json::Value &content_json = event_item_json["content"];
- if(!content_json.isObject())
+ const rapidjson::Value &content_json = GetMember(event_item_json, "content");
+ if(!content_json.IsObject())
continue;
- const Json::Value &creator_json = content_json["creator"];
- if(!creator_json.isString())
+ const rapidjson::Value &creator_json = GetMember(content_json, "creator");
+ if(!creator_json.IsString())
continue;
if(room_data->name.empty())
- room_data->name = combine_user_display_names_for_room_name(users_excluding_me, creator_json.asString());
+ room_data->name = combine_user_display_names_for_room_name(users_excluding_me, creator_json.GetString());
if(room_data->avatar_url.empty()) {
if(users_excluding_me.empty()) {
- auto user = room_data->get_user_by_id(creator_json.asString());
+ auto user = room_data->get_user_by_id(creator_json.GetString());
if(user)
room_data->avatar_url = user->avatar_url;
} else {
@@ -744,23 +753,23 @@ namespace QuickMedia {
}
}
- for(const Json::Value &event_item_json : events_json) {
- if(!event_item_json.isObject())
+ for(const rapidjson::Value &event_item_json : events_json.GetArray()) {
+ if(!event_item_json.IsObject())
continue;
- const Json::Value &type_json = event_item_json["type"];
- if(!type_json.isString() || strcmp(type_json.asCString(), "m.room.avatar") != 0)
+ const rapidjson::Value &type_json = GetMember(event_item_json, "type");
+ if(!type_json.IsString() || strcmp(type_json.GetString(), "m.room.avatar") != 0)
continue;
- const Json::Value &content_json = event_item_json["content"];
- if(!content_json.isObject())
+ const rapidjson::Value &content_json = GetMember(event_item_json, "content");
+ if(!content_json.IsObject())
continue;
- const Json::Value &url_json = content_json["url"];
- if(!url_json.isString() || strncmp(url_json.asCString(), "mxc://", 6) != 0)
+ const rapidjson::Value &url_json = GetMember(content_json, "url");
+ if(!url_json.IsString() || strncmp(url_json.GetString(), "mxc://", 6) != 0)
continue;
- std::string url_json_str = url_json.asCString() + 6;
+ std::string url_json_str = url_json.GetString() + 6;
room_data->avatar_url = homeserver + "/_matrix/media/r0/thumbnail/" + std::move(url_json_str) + "?width=32&height=32&method=crop";
}
}
@@ -776,43 +785,43 @@ namespace QuickMedia {
}
}
- Json::Value request_data(Json::objectValue);
- request_data["lazy_load_members"] = true;
+ rapidjson::Document request_data(rapidjson::kObjectType);
+ request_data.AddMember("lazy_load_members", true, request_data.GetAllocator());
- Json::StreamWriterBuilder builder;
- builder["commentStyle"] = "None";
- builder["indentation"] = "";
+ rapidjson::StringBuffer buffer;
+ rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
+ request_data.Accept(writer);
std::vector<CommandArg> additional_args = {
{ "-H", "Authorization: Bearer " + access_token }
};
- std::string filter = url_param_encode(Json::writeString(builder, std::move(request_data)));
+ std::string filter = url_param_encode(buffer.GetString());
char url[512];
snprintf(url, sizeof(url), "%s/_matrix/client/r0/rooms/%s/messages?from=%s&limit=20&dir=b&filter=%s", homeserver.c_str(), room_data->id.c_str(), from.c_str(), filter.c_str());
- Json::Value json_root;
+ rapidjson::Document json_root;
DownloadResult download_result = download_json(json_root, url, std::move(additional_args), true);
if(download_result != DownloadResult::OK) return download_result_to_plugin_result(download_result);
- if(!json_root.isObject())
+ if(!json_root.IsObject())
return PluginResult::ERR;
- const Json::Value &state_json = json_root["state"];
+ const rapidjson::Value &state_json = GetMember(json_root, "state");
events_add_user_info(state_json, room_data.get());
events_set_room_name(state_json, room_data.get());
- const Json::Value &chunk_json = json_root["chunk"];
+ const rapidjson::Value &chunk_json = GetMember(json_root, "chunk");
events_add_messages(chunk_json, room_data, MessageDirection::BEFORE, nullptr, false);
- const Json::Value &end_json = json_root["end"];
- if(!end_json.isString()) {
+ const rapidjson::Value &end_json = GetMember(json_root, "end");
+ if(!end_json.IsString()) {
fprintf(stderr, "Warning: matrix messages response is missing 'end', this could happen if we received the very first messages in the room\n");
return PluginResult::OK;
}
- room_data->prev_batch = end_json.asString();
+ room_data->prev_batch = end_json.GetString();
return PluginResult::OK;
}
@@ -881,71 +890,71 @@ namespace QuickMedia {
});
}
- Json::Value request_data(Json::objectValue);
- request_data["msgtype"] = (file_info ? content_type_to_message_type(file_info->content_type) : "m.text");
- request_data["body"] = body;
+ rapidjson::Document request_data(rapidjson::kObjectType);
+ request_data.AddMember("msgtype", rapidjson::StringRef(file_info ? content_type_to_message_type(file_info->content_type) : "m.text"), request_data.GetAllocator());
+ request_data.AddMember("body", rapidjson::StringRef(body.c_str()), request_data.GetAllocator());
if(contains_formatted_text) {
- request_data["format"] = "org.matrix.custom.html";
- request_data["formatted_body"] = std::move(formatted_body);
+ request_data.AddMember("format", "org.matrix.custom.html", request_data.GetAllocator());
+ request_data.AddMember("formatted_body", rapidjson::StringRef(formatted_body.c_str()), request_data.GetAllocator());
}
// TODO: Add hashblur?
if(file_info) {
- Json::Value info_json(Json::objectValue);
- info_json["size"] = file_info->file_size;
- info_json["mimetype"] = content_type_to_string(file_info->content_type);
+ rapidjson::Value info_json(rapidjson::kObjectType);
+ info_json.AddMember("size", file_info->file_size, request_data.GetAllocator());
+ info_json.AddMember("mimetype", rapidjson::StringRef(content_type_to_string(file_info->content_type)), request_data.GetAllocator());
if(file_info->dimensions) {
- info_json["w"] = file_info->dimensions->width;
- info_json["h"] = file_info->dimensions->height;
+ info_json.AddMember("w", file_info->dimensions->width, request_data.GetAllocator());
+ info_json.AddMember("h", file_info->dimensions->height, request_data.GetAllocator());
}
if(file_info->duration_seconds) {
// TODO: Check for overflow?
- info_json["duration"] = (int)file_info->duration_seconds.value() * 1000;
+ info_json.AddMember("duration", (int)file_info->duration_seconds.value() * 1000, request_data.GetAllocator());
}
if(thumbnail_info) {
- Json::Value thumbnail_info_json(Json::objectValue);
- thumbnail_info_json["size"] = thumbnail_info->file_size;
- thumbnail_info_json["mimetype"] = content_type_to_string(thumbnail_info->content_type);
+ rapidjson::Value thumbnail_info_json(rapidjson::kObjectType);
+ thumbnail_info_json.AddMember("size", thumbnail_info->file_size, request_data.GetAllocator());
+ thumbnail_info_json.AddMember("mimetype", rapidjson::StringRef(content_type_to_string(thumbnail_info->content_type)), request_data.GetAllocator());
if(thumbnail_info->dimensions) {
- thumbnail_info_json["w"] = thumbnail_info->dimensions->width;
- thumbnail_info_json["h"] = thumbnail_info->dimensions->height;
+ thumbnail_info_json.AddMember("w", thumbnail_info->dimensions->width, request_data.GetAllocator());
+ thumbnail_info_json.AddMember("h", thumbnail_info->dimensions->height, request_data.GetAllocator());
}
- info_json["thumbnail_url"] = thumbnail_info->content_uri;
- info_json["info"] = std::move(thumbnail_info_json);
+ info_json.AddMember("thumbnail_url", rapidjson::StringRef(thumbnail_info->content_uri.c_str()), request_data.GetAllocator());
+ info_json.AddMember("info", std::move(thumbnail_info_json), request_data.GetAllocator());
}
- request_data["info"] = std::move(info_json);
- request_data["url"] = file_info->content_uri;
+ request_data.AddMember("info", std::move(info_json), request_data.GetAllocator());
+ request_data.AddMember("url", rapidjson::StringRef(file_info->content_uri.c_str()), request_data.GetAllocator());
}
- Json::StreamWriterBuilder builder;
- builder["commentStyle"] = "None";
- builder["indentation"] = "";
+ rapidjson::StringBuffer buffer;
+ rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
+ request_data.Accept(writer);
std::vector<CommandArg> additional_args = {
{ "-X", "PUT" },
{ "-H", "content-type: application/json" },
{ "-H", "Authorization: Bearer " + access_token },
- { "--data-binary", Json::writeString(builder, std::move(request_data)) }
+ { "--data-binary", buffer.GetString() }
};
char request_url[512];
snprintf(request_url, sizeof(request_url), "%s/_matrix/client/r0/rooms/%s/send/m.room.message/m%ld.%.*s", homeserver.c_str(), room_id.c_str(), time(NULL), (int)random_readable_chars.size(), random_readable_chars.c_str());
- Json::Value json_root;
+ rapidjson::Document json_root;
DownloadResult download_result = download_json(json_root, request_url, std::move(additional_args), true);
if(download_result != DownloadResult::OK) return download_result_to_plugin_result(download_result);
- if(!json_root.isObject())
+ if(!json_root.IsObject())
return PluginResult::ERR;
- const Json::Value &event_id_json = json_root["event_id"];
- if(!event_id_json.isString())
+ const rapidjson::Value &event_id_json = GetMember(json_root, "event_id");
+ if(!event_id_json.IsString())
return PluginResult::ERR;
- fprintf(stderr, "Matrix post message, response event id: %s\n", event_id_json.asCString());
+ fprintf(stderr, "Matrix post message, response event id: %s\n", event_id_json.GetString());
return PluginResult::OK;
}
@@ -1041,45 +1050,48 @@ namespace QuickMedia {
std::string random_readable_chars = random_characters_to_readable_string(random_characters, sizeof(random_characters));
- Json::Value in_reply_to_json(Json::objectValue);
- in_reply_to_json["event_id"] = relates_to_message_original->event_id;
+ rapidjson::Document in_reply_to_json(rapidjson::kObjectType);
+ in_reply_to_json.AddMember("event_id", rapidjson::StringRef(relates_to_message_original->event_id.c_str()), in_reply_to_json.GetAllocator());
+
+ rapidjson::Document relates_to_json(rapidjson::kObjectType);
+ relates_to_json.AddMember("m.in_reply_to", std::move(in_reply_to_json), relates_to_json.GetAllocator());
- Json::Value relates_to_json(Json::objectValue);
- relates_to_json["m.in_reply_to"] = std::move(in_reply_to_json);
+ std::string message_reply_body = create_body_for_message_reply(relates_to_message_raw, body); // Yes, the reply is to the edited message but the event_id reference is to the original message...
+ std::string formatted_message_reply_body = create_formatted_body_for_message_reply(relates_to_message_raw, body);
- Json::Value request_data(Json::objectValue);
- request_data["msgtype"] = "m.text"; // TODO: Allow image reply? element doesn't do that but we could!
- request_data["body"] = create_body_for_message_reply(relates_to_message_raw, body); // Yes, the reply is to the edited message but the event_id reference is to the original message...
- request_data["format"] = "org.matrix.custom.html";
- request_data["formatted_body"] = create_formatted_body_for_message_reply(relates_to_message_raw, body);
- request_data["m.relates_to"] = std::move(relates_to_json);
+ rapidjson::Document request_data(rapidjson::kObjectType);
+ request_data.AddMember("msgtype", "m.text", request_data.GetAllocator()); // TODO: Allow image reply? element doesn't do that but we could!
+ request_data.AddMember("body", rapidjson::StringRef(message_reply_body.c_str()), request_data.GetAllocator());
+ request_data.AddMember("format", "org.matrix.custom.html", request_data.GetAllocator());
+ request_data.AddMember("formatted_body", rapidjson::StringRef(formatted_message_reply_body.c_str()), request_data.GetAllocator());
+ request_data.AddMember("m.relates_to", std::move(relates_to_json), request_data.GetAllocator());
- Json::StreamWriterBuilder builder;
- builder["commentStyle"] = "None";
- builder["indentation"] = "";
+ rapidjson::StringBuffer buffer;
+ rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
+ request_data.Accept(writer);
std::vector<CommandArg> additional_args = {
{ "-X", "PUT" },
{ "-H", "content-type: application/json" },
{ "-H", "Authorization: Bearer " + access_token },
- { "--data-binary", Json::writeString(builder, std::move(request_data)) }
+ { "--data-binary", buffer.GetString() }
};
char request_url[512];
snprintf(request_url, sizeof(request_url), "%s/_matrix/client/r0/rooms/%s/send/m.room.message/m%ld.%.*s", homeserver.c_str(), room_id.c_str(), time(NULL), (int)random_readable_chars.size(), random_readable_chars.c_str());
- Json::Value json_root;
+ rapidjson::Document json_root;
DownloadResult download_result = download_json(json_root, request_url, std::move(additional_args), true);
if(download_result != DownloadResult::OK) return download_result_to_plugin_result(download_result);
- if(!json_root.isObject())
+ if(!json_root.IsObject())
return PluginResult::ERR;
- const Json::Value &event_id_json = json_root["event_id"];
- if(!event_id_json.isString())
+ const rapidjson::Value &event_id_json = GetMember(json_root, "event_id");
+ if(!event_id_json.IsString())
return PluginResult::ERR;
- fprintf(stderr, "Matrix post reply, response event id: %s\n", event_id_json.asCString());
+ fprintf(stderr, "Matrix post reply, response event id: %s\n", event_id_json.GetString());
return PluginResult::OK;
}
@@ -1124,54 +1136,58 @@ namespace QuickMedia {
return true;
});
- Json::Value new_content_json(Json::objectValue);
- new_content_json["msgtype"] = "m.text";
- new_content_json["body"] = body;
+ rapidjson::Document new_content_json(rapidjson::kObjectType);
+ new_content_json.AddMember("msgtype", "m.text", new_content_json.GetAllocator());
+ new_content_json.AddMember("body", rapidjson::StringRef(body.c_str()), new_content_json.GetAllocator());
if(contains_formatted_text) {
- new_content_json["format"] = "org.matrix.custom.html";
- new_content_json["formatted_body"] = formatted_body;
+ new_content_json.AddMember("format", "org.matrix.custom.html", new_content_json.GetAllocator());
+ new_content_json.AddMember("formatted_body", rapidjson::StringRef(formatted_body.c_str()), new_content_json.GetAllocator());
}
- Json::Value relates_to_json(Json::objectValue);
- relates_to_json["event_id"] = relates_to_message_original->event_id;
- relates_to_json["rel_type"] = "m.replace";
+ rapidjson::Document relates_to_json(rapidjson::kObjectType);
+ relates_to_json.AddMember("event_id", rapidjson::StringRef(relates_to_message_original->event_id.c_str()), relates_to_json.GetAllocator());
+ relates_to_json.AddMember("rel_type", "m.replace", relates_to_json.GetAllocator());
- Json::Value request_data(Json::objectValue);
- request_data["msgtype"] = "m.text"; // TODO: Allow other types of edits
- request_data["body"] = " * " + body;
+ std::string body_edit_str = " * " + body;
+ std::string formatted_body_edit_str;
+
+ rapidjson::Document request_data(rapidjson::kObjectType);
+ request_data.AddMember("msgtype", "m.text", request_data.GetAllocator()); // TODO: Allow other types of edits
+ request_data.AddMember("body", rapidjson::StringRef(body_edit_str.c_str()), request_data.GetAllocator());
if(contains_formatted_text) {
- request_data["format"] = "org.matrix.custom.html";
- request_data["formatted_body"] = " * " + formatted_body;
+ formatted_body_edit_str = " * " + formatted_body;
+ request_data.AddMember("format", "org.matrix.custom.html", request_data.GetAllocator());
+ request_data.AddMember("formatted_body", rapidjson::StringRef(formatted_body_edit_str.c_str()), request_data.GetAllocator());
}
- request_data["m.new_content"] = std::move(new_content_json);
- request_data["m.relates_to"] = std::move(relates_to_json);
+ request_data.AddMember("m.new_content", std::move(new_content_json), request_data.GetAllocator());
+ request_data.AddMember("m.relates_to", std::move(relates_to_json), request_data.GetAllocator());
- Json::StreamWriterBuilder builder;
- builder["commentStyle"] = "None";
- builder["indentation"] = "";
+ rapidjson::StringBuffer buffer;
+ rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
+ request_data.Accept(writer);
std::vector<CommandArg> additional_args = {
{ "-X", "PUT" },
{ "-H", "content-type: application/json" },
{ "-H", "Authorization: Bearer " + access_token },
- { "--data-binary", Json::writeString(builder, std::move(request_data)) }
+ { "--data-binary", buffer.GetString() }
};
char request_url[512];
snprintf(request_url, sizeof(request_url), "%s/_matrix/client/r0/rooms/%s/send/m.room.message/m%ld.%.*s", homeserver.c_str(), room_id.c_str(), time(NULL), (int)random_readable_chars.size(), random_readable_chars.c_str());
- Json::Value json_root;
+ rapidjson::Document json_root;
DownloadResult download_result = download_json(json_root, request_url, std::move(additional_args), true);
if(download_result != DownloadResult::OK) return download_result_to_plugin_result(download_result);
- if(!json_root.isObject())
+ if(!json_root.IsObject())
return PluginResult::ERR;
- const Json::Value &event_id_json = json_root["event_id"];
- if(!event_id_json.isString())
+ const rapidjson::Value &event_id_json = GetMember(json_root, "event_id");
+ if(!event_id_json.IsString())
return PluginResult::ERR;
- fprintf(stderr, "Matrix post edit, response event id: %s\n", event_id_json.asCString());
+ fprintf(stderr, "Matrix post edit, response event id: %s\n", event_id_json.GetString());
return PluginResult::OK;
}
@@ -1183,70 +1199,70 @@ namespace QuickMedia {
auto replaced_message = room_data->get_message_by_id(message->replaces_event_id);
if(!replaced_message) {
- Json::Value request_data(Json::objectValue);
- request_data["lazy_load_members"] = true;
+ rapidjson::Document request_data(rapidjson::kObjectType);
+ request_data.AddMember("lazy_load_members", true, request_data.GetAllocator());
- Json::StreamWriterBuilder builder;
- builder["commentStyle"] = "None";
- builder["indentation"] = "";
+ rapidjson::StringBuffer buffer;
+ rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
+ request_data.Accept(writer);
std::vector<CommandArg> additional_args = {
{ "-H", "Authorization: Bearer " + access_token }
};
- std::string filter = url_param_encode(Json::writeString(builder, std::move(request_data)));
+ std::string filter = url_param_encode(buffer.GetString());
char url[512];
snprintf(url, sizeof(url), "%s/_matrix/client/r0/rooms/%s/context/%s?limit=0&filter=%s", homeserver.c_str(), room_data->id.c_str(), message->event_id.c_str(), filter.c_str());
- Json::Value json_root;
+ rapidjson::Document json_root;
DownloadResult download_result = download_json(json_root, url, std::move(additional_args), true);
if(download_result != DownloadResult::OK) return nullptr;
- if(!json_root.isObject())
+ if(!json_root.IsObject())
return nullptr;
- const Json::Value &event_json = json_root["event"];
- if(!event_json.isObject())
+ const rapidjson::Value &event_json = GetMember(json_root, "event");
+ if(!event_json.IsObject())
return nullptr;
- const Json::Value &event_id_json = event_json["event_id"];
- if(!event_id_json.isString())
+ const rapidjson::Value &event_id_json = GetMember(event_json, "event_id");
+ if(!event_id_json.IsString())
return nullptr;
- const Json::Value &content_json = event_json["content"];
- if(!content_json.isObject())
+ const rapidjson::Value &content_json = GetMember(event_json, "content");
+ if(!content_json.IsObject())
return nullptr;
- const Json::Value &body_json = content_json["body"];
- if(!body_json.isString())
+ const rapidjson::Value &body_json = GetMember(content_json, "body");
+ if(!body_json.IsString())
return nullptr;
std::string replaces_event_id;
- const Json::Value &relates_to_json = content_json["m.relates_to"];
- if(relates_to_json.isObject()) {
- const Json::Value &event_id_json = relates_to_json["event_id"];
- const Json::Value &rel_type_json = relates_to_json["rel_type"];
- if(event_id_json.isString() && rel_type_json.isString() && strcmp(rel_type_json.asCString(), "m.replace") == 0)
- replaces_event_id = event_id_json.asString();
+ const rapidjson::Value &relates_to_json = GetMember(content_json, "m.relates_to");
+ if(relates_to_json.IsObject()) {
+ const rapidjson::Value &event_id_json = GetMember(relates_to_json, "event_id");
+ const rapidjson::Value &rel_type_json = GetMember(relates_to_json, "rel_type");
+ if(event_id_json.IsString() && rel_type_json.IsString() && strcmp(rel_type_json.GetString(), "m.replace") == 0)
+ replaces_event_id = event_id_json.GetString();
}
- const Json::Value &content_type = content_json["msgtype"];
- if(!content_type.isString())
+ const rapidjson::Value &content_type = GetMember(content_json, "msgtype");
+ if(!content_type.IsString())
return nullptr;
auto new_message = std::make_shared<Message>();
- new_message->event_id = event_id_json.asString();
+ new_message->event_id = event_id_json.GetString();
new_message->replaces_event_id = std::move(replaces_event_id);
- if(strcmp(content_type.asCString(), "m.text") == 0) {
+ if(strcmp(content_type.GetString(), "m.text") == 0) {
new_message->type = MessageType::TEXT;
- } else if(strcmp(content_type.asCString(), "m.image") == 0) {
+ } else if(strcmp(content_type.GetString(), "m.image") == 0) {
new_message->type = MessageType::IMAGE;
- } else if(strcmp(content_type.asCString(), "m.video") == 0) {
+ } else if(strcmp(content_type.GetString(), "m.video") == 0) {
new_message->type = MessageType::VIDEO;
- } else if(strcmp(content_type.asCString(), "m.audio") == 0) {
+ } else if(strcmp(content_type.GetString(), "m.audio") == 0) {
new_message->type = MessageType::AUDIO;
- } else if(strcmp(content_type.asCString(), "m.file") == 0) {
+ } else if(strcmp(content_type.GetString(), "m.file") == 0) {
new_message->type = MessageType::FILE;
} else {
return nullptr;
@@ -1351,87 +1367,87 @@ namespace QuickMedia {
char url[512];
snprintf(url, sizeof(url), "%s/_matrix/media/r0/upload?filename=%s", homeserver.c_str(), filename_escaped.c_str());
- Json::Value json_root;
+ rapidjson::Document json_root;
DownloadResult download_result = download_json(json_root, url, std::move(additional_args), true, &err_msg);
if(download_result != DownloadResult::OK) return download_result_to_plugin_result(download_result);
- if(!json_root.isObject()) {
+ if(!json_root.IsObject()) {
err_msg = "Got corrupt response from server";
return PluginResult::ERR;
}
- const Json::Value &error_json = json_root["error"];
- if(error_json.isString()) {
- err_msg = error_json.asString();
+ const rapidjson::Value &error_json = GetMember(json_root, "error");
+ if(error_json.IsString()) {
+ err_msg = error_json.GetString();
return PluginResult::ERR;
}
- const Json::Value &content_uri_json = json_root["content_uri"];
- if(!content_uri_json.isString()) {
+ const rapidjson::Value &content_uri_json = GetMember(json_root, "content_uri");
+ if(!content_uri_json.IsString()) {
err_msg = "Missing content_uri is server response";
return PluginResult::ERR;
}
- fprintf(stderr, "Matrix upload, response content uri: %s\n", content_uri_json.asCString());
- file_info.content_uri = content_uri_json.asString();
+ fprintf(stderr, "Matrix upload, response content uri: %s\n", content_uri_json.GetString());
+ file_info.content_uri = content_uri_json.GetString();
return PluginResult::OK;
}
PluginResult Matrix::login(const std::string &username, const std::string &password, const std::string &homeserver, std::string &err_msg) {
- Json::Value identifier_json(Json::objectValue);
- identifier_json["type"] = "m.id.user"; // TODO: What if the server doesn't support this login type? redirect to sso web page etc
- identifier_json["user"] = username;
+ rapidjson::Document identifier_json(rapidjson::kObjectType);
+ identifier_json.AddMember("type", "m.id.user", identifier_json.GetAllocator()); // TODO: What if the server doesn't support this login type? redirect to sso web page etc
+ identifier_json.AddMember("user", rapidjson::StringRef(username.c_str()), identifier_json.GetAllocator());
- Json::Value request_data(Json::objectValue);
- request_data["type"] = "m.login.password";
- request_data["identifier"] = std::move(identifier_json);
- request_data["password"] = password;
- request_data["initial_device_display_name"] = "QuickMedia"; // :^)
+ rapidjson::Document request_data(rapidjson::kObjectType);
+ request_data.AddMember("type", "m.login.password", request_data.GetAllocator());
+ request_data.AddMember("identifier", std::move(identifier_json), request_data.GetAllocator());
+ request_data.AddMember("password", rapidjson::StringRef(password.c_str()), request_data.GetAllocator());
+ request_data.AddMember("initial_device_display_name", "QuickMedia", request_data.GetAllocator()); // :^)
- Json::StreamWriterBuilder builder;
- builder["commentStyle"] = "None";
- builder["indentation"] = "";
+ rapidjson::StringBuffer buffer;
+ rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
+ request_data.Accept(writer);
std::vector<CommandArg> additional_args = {
{ "-X", "POST" },
{ "-H", "content-type: application/json" },
- { "--data-binary", Json::writeString(builder, std::move(request_data)) }
+ { "--data-binary", buffer.GetString() }
};
- Json::Value json_root;
+ rapidjson::Document json_root;
DownloadResult download_result = download_json(json_root, homeserver + "/_matrix/client/r0/login", std::move(additional_args), true, &err_msg);
if(download_result != DownloadResult::OK) return download_result_to_plugin_result(download_result);
- if(!json_root.isObject()) {
+ if(!json_root.IsObject()) {
err_msg = "Failed to parse matrix login response";
return PluginResult::ERR;
}
- const Json::Value &error_json = json_root["error"];
- if(error_json.isString()) {
- err_msg = error_json.asString();
+ const rapidjson::Value &error_json = GetMember(json_root, "error");
+ if(error_json.IsString()) {
+ err_msg = error_json.GetString();
return PluginResult::ERR;
}
- const Json::Value &user_id_json = json_root["user_id"];
- if(!user_id_json.isString()) {
+ const rapidjson::Value &user_id_json = GetMember(json_root, "user_id");
+ if(!user_id_json.IsString()) {
err_msg = "Failed to parse matrix login response";
return PluginResult::ERR;
}
- const Json::Value &access_token_json = json_root["access_token"];
- if(!access_token_json.isString()) {
+ const rapidjson::Value &access_token_json = GetMember(json_root, "access_token");
+ if(!access_token_json.IsString()) {
err_msg = "Failed to parse matrix login response";
return PluginResult::ERR;
}
// Use the user-provided homeserver instead of the one the server tells us about, otherwise this wont work with a proxy
// such as pantalaimon
- json_root["homeserver"] = homeserver;
+ json_root.AddMember("homeserver", rapidjson::StringRef(homeserver.c_str()), request_data.GetAllocator());
- this->user_id = user_id_json.asString();
+ this->user_id = user_id_json.GetString();
this->username = extract_user_name_from_user_id(this->user_id);
- this->access_token = access_token_json.asString();
+ this->access_token = access_token_json.GetString();
this->homeserver = homeserver;
// TODO: Handle well_known field. The spec says clients SHOULD handle it if its provided
@@ -1484,41 +1500,41 @@ namespace QuickMedia {
Message *message_typed = (Message*)message;
// request_data could contains "reason", maybe it should be added sometime in the future?
- Json::Value request_data(Json::objectValue);
- Json::StreamWriterBuilder builder;
- builder["commentStyle"] = "None";
- builder["indentation"] = "";
+ rapidjson::Value request_data(rapidjson::kObjectType);
+ rapidjson::StringBuffer buffer;
+ rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
+ request_data.Accept(writer);
std::vector<CommandArg> additional_args = {
{ "-X", "PUT" },
{ "-H", "content-type: application/json" },
{ "-H", "Authorization: Bearer " + access_token },
- { "--data-binary", Json::writeString(builder, std::move(request_data)) }
+ { "--data-binary", buffer.GetString() }
};
char url[512];
snprintf(url, sizeof(url), "%s/_matrix/client/r0/rooms/%s/redact/%s/m%ld.%.*s", homeserver.c_str(), room_id.c_str(), message_typed->event_id.c_str(), time(NULL), (int)random_readable_chars.size(), random_readable_chars.c_str());
- Json::Value json_root;
+ rapidjson::Document json_root;
DownloadResult download_result = download_json(json_root, url, std::move(additional_args), true, &err_msg);
if(download_result != DownloadResult::OK) return download_result_to_plugin_result(download_result);
- if(!json_root.isObject()) {
+ if(!json_root.IsObject()) {
err_msg = "Failed to parse matrix login response";
return PluginResult::ERR;
}
- const Json::Value &error_json = json_root["error"];
- if(error_json.isString()) {
- err_msg = error_json.asString();
+ const rapidjson::Value &error_json = GetMember(json_root, "error");
+ if(error_json.IsString()) {
+ err_msg = error_json.GetString();
return PluginResult::ERR;
}
- const Json::Value &event_id_json = json_root["event_id"];
- if(!event_id_json.isString())
+ const rapidjson::Value &event_id_json = GetMember(json_root, "event_id");
+ if(!event_id_json.IsString())
return PluginResult::ERR;
- fprintf(stderr, "Matrix delete message, response event id: %s\n", event_id_json.asCString());
+ fprintf(stderr, "Matrix delete message, response event id: %s\n", event_id_json.GetString());
return PluginResult::OK;
}
@@ -1530,39 +1546,37 @@ namespace QuickMedia {
return PluginResult::ERR;
}
- Json::Value json_root;
- Json::CharReaderBuilder json_builder;
- std::unique_ptr<Json::CharReader> json_reader(json_builder.newCharReader());
- std::string json_errors;
- if(!json_reader->parse(&session_json_content[0], &session_json_content[session_json_content.size()], &json_root, &json_errors)) {
- fprintf(stderr, "Matrix cached session parse error: %s\n", json_errors.c_str());
+ rapidjson::Document json_root;
+ rapidjson::ParseResult parse_result = json_root.Parse(session_json_content.c_str(), session_json_content.size());
+ if(parse_result.IsError()) {
+ fprintf(stderr, "Matrix cached session parse error: %d\n", parse_result.Code());
return PluginResult::ERR;
}
- if(!json_root.isObject())
+ if(!json_root.IsObject())
return PluginResult::ERR;
- const Json::Value &user_id_json = json_root["user_id"];
- if(!user_id_json.isString()) {
+ const rapidjson::Value &user_id_json = GetMember(json_root, "user_id");
+ if(!user_id_json.IsString()) {
fprintf(stderr, "Failed to parse matrix cached session response\n");
return PluginResult::ERR;
}
- const Json::Value &access_token_json = json_root["access_token"];
- if(!access_token_json.isString()) {
+ const rapidjson::Value &access_token_json = GetMember(json_root, "access_token");
+ if(!access_token_json.IsString()) {
fprintf(stderr, "Failed to parse matrix cached session response\n");
return PluginResult::ERR;
}
- const Json::Value &homeserver_json = json_root["homeserver"];
- if(!homeserver_json.isString()) {
+ const rapidjson::Value &homeserver_json = GetMember(json_root, "homeserver");
+ if(!homeserver_json.IsString()) {
fprintf(stderr, "Failed to parse matrix cached session response\n");
return PluginResult::ERR;
}
- std::string user_id = user_id_json.asString();
- std::string access_token = access_token_json.asString();
- std::string homeserver = homeserver_json.asString();
+ std::string user_id = user_id_json.GetString();
+ std::string access_token = access_token_json.GetString();
+ std::string homeserver = homeserver_json.GetString();
std::vector<CommandArg> additional_args = {
{ "-H", "Authorization: Bearer " + access_token }
@@ -1583,18 +1597,18 @@ namespace QuickMedia {
}
PluginResult Matrix::on_start_typing(const std::string &room_id) {
- Json::Value request_data(Json::objectValue);
- request_data["typing"] = true;
- request_data["timeout"] = 30000; // 30 sec timeout
+ rapidjson::Document request_data(rapidjson::kObjectType);
+ request_data.AddMember("typing", true, request_data.GetAllocator());
+ request_data.AddMember("timeout", 30000, request_data.GetAllocator()); // 30 sec timeout
- Json::StreamWriterBuilder builder;
- builder["commentStyle"] = "None";
- builder["indentation"] = "";
+ rapidjson::StringBuffer buffer;
+ rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
+ request_data.Accept(writer);
std::vector<CommandArg> additional_args = {
{ "-X", "PUT" },
{ "-H", "content-type: application/json" },
- { "--data-binary", Json::writeString(builder, std::move(request_data)) },
+ { "--data-binary", buffer.GetString() },
{ "-H", "Authorization: Bearer " + access_token }
};
@@ -1606,17 +1620,17 @@ namespace QuickMedia {
}
PluginResult Matrix::on_stop_typing(const std::string &room_id) {
- Json::Value request_data(Json::objectValue);
- request_data["typing"] = false;
+ rapidjson::Document request_data(rapidjson::kObjectType);
+ request_data.AddMember("typing", false, request_data.GetAllocator());
- Json::StreamWriterBuilder builder;
- builder["commentStyle"] = "None";
- builder["indentation"] = "";
+ rapidjson::StringBuffer buffer;
+ rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
+ request_data.Accept(writer);
std::vector<CommandArg> additional_args = {
{ "-X", "PUT" },
{ "-H", "content-type: application/json" },
- { "--data-binary", Json::writeString(builder, std::move(request_data)) },
+ { "--data-binary", buffer.GetString() },
{ "-H", "Authorization: Bearer " + access_token }
};
@@ -1628,19 +1642,19 @@ namespace QuickMedia {
}
PluginResult Matrix::set_read_marker(const std::string &room_id, const Message *message) {
- Json::Value request_data(Json::objectValue);
- request_data["m.fully_read"] = message->event_id;
- request_data["m.read"] = message->event_id;
- request_data["m.hidden"] = false; // What is this for? element sends it but its not part of the documentation. Is it for hiding read receipt from other users? in that case, TODO: make it configurable
+ rapidjson::Document request_data(rapidjson::kObjectType);
+ request_data.AddMember("m.fully_read", rapidjson::StringRef(message->event_id.c_str()), request_data.GetAllocator());
+ request_data.AddMember("m.read", rapidjson::StringRef(message->event_id.c_str()), request_data.GetAllocator());
+ request_data.AddMember("m.hidden", false, request_data.GetAllocator()); // What is this for? element sends it but its not part of the documentation. Is it for hiding read receipt from other users? in that case, TODO: make it configurable
- Json::StreamWriterBuilder builder;
- builder["commentStyle"] = "None";
- builder["indentation"] = "";
+ rapidjson::StringBuffer buffer;
+ rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
+ request_data.Accept(writer);
std::vector<CommandArg> additional_args = {
{ "-X", "POST" },
{ "-H", "content-type: application/json" },
- { "--data-binary", Json::writeString(builder, std::move(request_data)) },
+ { "--data-binary", buffer.GetString() },
{ "-H", "Authorization: Bearer " + access_token }
};
@@ -1677,18 +1691,18 @@ namespace QuickMedia {
char url[512];
snprintf(url, sizeof(url), "%s/_matrix/media/r0/config", homeserver.c_str());
- Json::Value json_root;
+ rapidjson::Document json_root;
DownloadResult download_result = download_json(json_root, url, std::move(additional_args), true);
if(download_result != DownloadResult::OK) return download_result_to_plugin_result(download_result);
- if(!json_root.isObject())
+ if(!json_root.IsObject())
return PluginResult::ERR;
- const Json::Value &upload_size_json = json_root["m.upload.size"];
- if(!upload_size_json.isNumeric())
+ const rapidjson::Value &upload_size_json = GetMember(json_root, "m.upload.size");
+ if(!upload_size_json.IsNumber())
return PluginResult::ERR;
- upload_limit = upload_size_json.asInt();
+ upload_limit = upload_size_json.GetInt();
*upload_size = upload_limit.value();
return PluginResult::OK;
}
@@ -1715,7 +1729,7 @@ namespace QuickMedia {
room_data_by_id.insert(std::make_pair(room->id, room));
}
- DownloadResult Matrix::download_json(Json::Value &result, const std::string &url, std::vector<CommandArg> additional_args, bool use_browser_useragent, std::string *err_msg) const {
+ DownloadResult Matrix::download_json(rapidjson::Document &result, const std::string &url, std::vector<CommandArg> additional_args, bool use_browser_useragent, std::string *err_msg) const {
std::string server_response;
if(download_to_string(url, server_response, std::move(additional_args), use_tor, use_browser_useragent, err_msg == nullptr) != DownloadResult::OK) {
if(err_msg)
@@ -1723,16 +1737,12 @@ namespace QuickMedia {
return DownloadResult::NET_ERR;
}
- if(server_response.empty())
- return DownloadResult::OK;
-
- Json::CharReaderBuilder json_builder;
- std::unique_ptr<Json::CharReader> json_reader(json_builder.newCharReader());
- std::string json_errors;
- if(!json_reader->parse(&server_response[0], &server_response[server_response.size()], &result, &json_errors)) {
- fprintf(stderr, "download_json error: %s\n", json_errors.c_str());
+ rapidjson::ParseResult parse_result = result.Parse(server_response.c_str(), server_response.size());
+ if(parse_result.IsError()) {
+ std::string error_code_str = std::to_string(parse_result.Code());
+ fprintf(stderr, "download_json error: %s\n", error_code_str.c_str());
if(err_msg)
- *err_msg = std::move(json_errors);
+ *err_msg = "Json parse error: " + std::move(error_code_str);
return DownloadResult::ERR;
}