From dbb26daafaea788d3b246e02c7d1cf8f858da7ab Mon Sep 17 00:00:00 2001 From: Luciano Iam Date: Wed, 22 Apr 2020 18:17:13 +0200 Subject: WebSockets: also json-escape strings in state messages --- libs/surfaces/websockets/json.cc | 39 +++++++++++++++++++++++++++++++++++ libs/surfaces/websockets/json.h | 30 +++++++++++++++++++++++++++ libs/surfaces/websockets/manifest.cc | 9 ++++---- libs/surfaces/websockets/message.cc | 3 ++- libs/surfaces/websockets/resources.cc | 27 +++++------------------- libs/surfaces/websockets/resources.h | 2 -- libs/surfaces/websockets/wscript | 1 + 7 files changed, 82 insertions(+), 29 deletions(-) create mode 100644 libs/surfaces/websockets/json.cc create mode 100644 libs/surfaces/websockets/json.h diff --git a/libs/surfaces/websockets/json.cc b/libs/surfaces/websockets/json.cc new file mode 100644 index 0000000000..b46857721e --- /dev/null +++ b/libs/surfaces/websockets/json.cc @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2020 Luciano Iam + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the/GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include + +#include "json.h" + +/* adapted from https://stackoverflow.com/questions/7724448/simple-json-string-escape-for-c + CC BY-SA 4.0 license */ +std::string +Json::escape (const std::string &s) { + std::ostringstream o; + + for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) { + if (*it == '"' || *it == '\\' || ('\x00' <= *it && *it <= '\x1f')) { + o << "\\u" << std::hex << std::setw (4) << std::setfill ('0') << static_cast(*it); + } else { + o << *it; + } + } + + return o.str (); +} diff --git a/libs/surfaces/websockets/json.h b/libs/surfaces/websockets/json.h new file mode 100644 index 0000000000..ea2b2be361 --- /dev/null +++ b/libs/surfaces/websockets/json.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2020 Luciano Iam + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the/GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef _ardour_surface_json_h_ +#define _ardour_surface_json_h_ + +class Json +{ +public: + + static std::string escape (const std::string&); + +}; + +#endif // _ardour_surface_json_h_ diff --git a/libs/surfaces/websockets/manifest.cc b/libs/surfaces/websockets/manifest.cc index 386f0adcc8..306405fd6a 100644 --- a/libs/surfaces/websockets/manifest.cc +++ b/libs/surfaces/websockets/manifest.cc @@ -26,6 +26,7 @@ #include "manifest.h" #include "resources.h" +#include "json.h" static const char* const manifest_filename = "manifest.xml"; @@ -76,10 +77,10 @@ SurfaceManifest::to_json () std::stringstream ss; ss << "{" - << "\"path\":\"" << ServerResources::escape_json (Glib::path_get_basename (_path)) << "\"" - << ",\"name\":\"" << ServerResources::escape_json (_name) << "\"" - << ",\"description\":\"" << ServerResources::escape_json (_description) << "\"" - << ",\"version\":\"" << ServerResources::escape_json (_version) << "\"" + << "\"path\":\"" << Json::escape (Glib::path_get_basename (_path)) << "\"" + << ",\"name\":\"" << Json::escape (_name) << "\"" + << ",\"description\":\"" << Json::escape (_description) << "\"" + << ",\"version\":\"" << Json::escape (_version) << "\"" << "}"; return ss.str (); diff --git a/libs/surfaces/websockets/message.cc b/libs/surfaces/websockets/message.cc index 54d441db05..ef81f4e7c3 100644 --- a/libs/surfaces/websockets/message.cc +++ b/libs/surfaces/websockets/message.cc @@ -26,6 +26,7 @@ #include #include "message.h" +#include "json.h" // JSON does not support Infinity or NaN #define XSTR(s) STR (s) @@ -166,7 +167,7 @@ NodeStateMessage::serialize (void* buf, size_t len) const break; } case TypedValue::String: - ss << '"' << static_cast (val) << '"'; + ss << '"' << Json::escape (static_cast (val)) << '"'; break; default: break; diff --git a/libs/surfaces/websockets/resources.cc b/libs/surfaces/websockets/resources.cc index 18f41621cc..afad30e887 100644 --- a/libs/surfaces/websockets/resources.cc +++ b/libs/surfaces/websockets/resources.cc @@ -16,7 +16,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include #include #include @@ -27,6 +26,7 @@ #include "pbd/file_utils.h" #include "resources.h" +#include "json.h" static const char* const data_dir_env_var = "ARDOUR_WEBSURFACES_PATH"; static const char* const data_dir_name = "web_surfaces"; @@ -46,23 +46,6 @@ ServerResources::ServerResources () { } -/* adapted from https://stackoverflow.com/questions/7724448/simple-json-string-escape-for-c - CC BY-SA 4.0 license */ -std::string -ServerResources::escape_json (const std::string &s) { - std::ostringstream o; - - for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) { - if (*it == '"' || *it == '\\' || ('\x00' <= *it && *it <= '\x1f')) { - o << "\\u" << std::hex << std::setw (4) << std::setfill ('0') << static_cast(*it); - } else { - o << *it; - } - } - - return o.str (); -} - const std::string& ServerResources::index_dir () { @@ -102,8 +85,8 @@ ServerResources::scan () SurfaceManifestVector builtin = read_manifests (builtin_dir_str); ss << "[{" - << "\"filesystemPath\":\"" << escape_json (builtin_dir_str) << "\"" - << ",\"path\":\"" << escape_json (builtin_dir_name) << "\"" + << "\"filesystemPath\":\"" << Json::escape (builtin_dir_str) << "\"" + << ",\"path\":\"" << Json::escape (builtin_dir_name) << "\"" << ",\"surfaces\":" << "["; @@ -118,8 +101,8 @@ ServerResources::scan () SurfaceManifestVector user = read_manifests (user_dir_str); ss << "]},{" - << "\"filesystemPath\":\"" << escape_json(user_dir_str) << "\"" - << ",\"path\":\"" << escape_json(user_dir_name) << "\"" + << "\"filesystemPath\":\"" << Json::escape (user_dir_str) << "\"" + << ",\"path\":\"" << Json::escape (user_dir_name) << "\"" << ",\"surfaces\":" << "["; diff --git a/libs/surfaces/websockets/resources.h b/libs/surfaces/websockets/resources.h index 9d6f72d280..f942ec1ce7 100644 --- a/libs/surfaces/websockets/resources.h +++ b/libs/surfaces/websockets/resources.h @@ -30,8 +30,6 @@ class ServerResources { public: ServerResources (); - - static std::string escape_json (const std::string&); const std::string& index_dir (); const std::string& builtin_dir (); diff --git a/libs/surfaces/websockets/wscript b/libs/surfaces/websockets/wscript index a98df2a477..cf5e74e149 100644 --- a/libs/surfaces/websockets/wscript +++ b/libs/surfaces/websockets/wscript @@ -29,6 +29,7 @@ def build(bld): dispatcher.cc manifest.cc resources.cc + json.cc ''' obj.export_includes = ['.'] obj.defines = [ 'PACKAGE="ardour_websockets"' ] -- cgit v1.2.3