Allow building log_json against yyjson.

This is the default if available. RapidJSON has not had a release
in years and has known security vulnerabilities so we should really
not be using it.
This commit is contained in:
Sadie Powell 2024-08-23 18:38:03 +01:00
parent 5399861e1e
commit 448c3342d9
7 changed files with 67 additions and 21 deletions

View File

@ -35,9 +35,9 @@ jobs:
pcre2-dev \
perl \
pkgconf \
rapidjson-dev \
re2-dev \
sqlite-dev
sqlite-dev \
yyjson-dev
- name: Run configure
run: |

View File

@ -25,7 +25,7 @@ jobs:
- name: Install dependencies
run: |
brew update || true
for PACKAGE in pkg-config argon2 gnutls libmaxminddb libpq libpsl mysql-client openssl openldap pcre2 re2 rapidjson sqlite
for PACKAGE in pkg-config argon2 gnutls libmaxminddb libpq libpsl mysql-client openssl openldap pcre2 re2 sqlite yyjson
do
brew install $PACKAGE || brew upgrade $PACKAGE

2
configure vendored
View File

@ -393,7 +393,7 @@ if (prompt_bool $interactive, $question, 0) {
'mysql' => 'mysql_config --version',
'pgsql' => 'pg_config --version',
'ldap' => "pkg-config --exists lber && pkg-config --exists ldap",
'log_json' => 'pkg-config --exists RapidJSON',
'log_json' => 'pkg-config --exists yyjson',
'log_syslog' => undef,
'regex_pcre2' => 'pkg-config --exists libpcre2-8',
'regex_posix' => undef,

View File

@ -1536,9 +1536,10 @@
#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#
# JSON logging module: Allows writing messages to a JSON file. #
# #
# This module depends on a third-party library (RapidJSON) and may #
# need to be manually enabled at build time. If you are building from #
# source you can do this by installing this dependency and running: #
# This module depends on a third-party library (yyjson or RapidJSON) #
# and may need to be manually enabled at build time. If you are #
# building from source you can do this by installing this dependency #
# and running: #
# #
# ./configure --enable-extras log_json #
# make install #

View File

@ -16,20 +16,32 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/// $CompilerFlags: find_compiler_flags("RapidJSON")
/// $CompilerFlags: require_library("yyjson") find_compiler_flags("yyjson") -DHAS_YYJSON
/// $CompilerFlags: require_library("!yyjson") find_compiler_flags("RapidJSON") warning("Building log_json against RapidJSON is deprecated. Please build against yyjson instead.")
/// $PackageInfo: require_system("alpine") rapidjson-dev pkgconf
/// $PackageInfo: require_system("arch") rapidjson pkgconf
/// $PackageInfo: require_system("darwin") rapidjson pkg-config
/// $LinkerFlags: require_library("yyjson") find_linker_flags("yyjson")
/// $PackageInfo: require_system("alpine") pkgconf yyjson-dev
/// $PackageInfo: require_system("arch") pkgconf yyjson
/// $PackageInfo: require_system("darwin") pkg-config yyjson
/// $PackageInfo: require_system("debian~") rapidjson-dev pkg-config
#ifdef _WIN32
# define HAS_YYJSON
# pragma comment(lib, "yyjson.lib")
#endif
#include <rapidjson/ostreamwrapper.h>
#include <rapidjson/writer.h>
#ifdef HAS_YYJSON
# include <yyjson.h>
#else
# include <rapidjson/ostreamwrapper.h>
# include <rapidjson/writer.h>
#endif
#include "inspircd.h"
#include "timeutils.h"
#include <iostream>
class JSONMethod final
: public Log::Method
, public Timer
@ -71,8 +83,10 @@ public:
fclose(file);
}
#ifndef HAS_YYJSON
// RapidJSON API: We implement our own flushing in OnLog.
void Flush() { }
#endif
void OnLog(time_t time, Log::Level level, const std::string& type, const std::string& message) override
{
@ -84,6 +98,28 @@ public:
timestr = Time::ToString(prevtime, "%Y-%m-%dT%H:%M:%S%z");
}
const auto* levelstr = Log::LevelToString(level);
#ifdef HAS_YYJSON
auto* doc = yyjson_mut_doc_new(nullptr);
auto* root = yyjson_mut_obj(doc);
yyjson_mut_doc_set_root(doc, root);
auto error = false;
error |= yyjson_mut_obj_add_strn(doc, root, "time", timestr.c_str(), timestr.length());
error |= yyjson_mut_obj_add_strn(doc, root, "type", type.c_str(), type.length());
error |= yyjson_mut_obj_add_strn(doc, root, "level", levelstr, strlen(levelstr));
error |= yyjson_mut_obj_add_strn(doc, root, "message", message.c_str(), message.length());
yyjson_write_err errmsg;
error |= yyjson_mut_write_fp(file, doc, YYJSON_WRITE_ALLOW_INVALID_UNICODE | YYJSON_WRITE_NEWLINE_AT_END, nullptr, &errmsg);
yyjson_mut_doc_free(doc);
if (error)
throw CoreException(INSP_FORMAT("Unable to generate JSON for {}: {}", name, errmsg.msg ? errmsg.msg : "unknown error"));
#else
rapidjson::Writer writer(*this);
writer.StartObject();
{
@ -94,18 +130,18 @@ public:
writer.String(type.c_str(), static_cast<rapidjson::SizeType>(type.size()));
writer.Key("level", 5);
const std::string levelstr = Log::LevelToString(level);
writer.String(levelstr.c_str(), static_cast<rapidjson::SizeType>(levelstr.size()));
writer.String(levelstr, static_cast<rapidjson::SizeType>(strlen(levelstr)));
writer.Key("message", 7);
writer.Key(message.c_str(), static_cast<rapidjson::SizeType>(message.size()));
}
writer.EndObject();
#ifdef _WIN32
# ifdef _WIN32
fputs("\r\n", file);
#else
# else
fputs("\n", file);
# endif
#endif
if (!(++lines % flush))
@ -115,11 +151,13 @@ public:
throw CoreException(INSP_FORMAT("Unable to write to {}: {}", name, strerror(errno)));
}
#ifndef HAS_YYJSON
// RapidJSON API: Write a character to the file.
void Put(Ch c)
{
fputc(c, file);
}
#endif
bool Tick() override
{
@ -194,8 +232,14 @@ public:
void init() override
{
#ifdef HAS_YYJSON
const auto yyversion = yyjson_version();
ServerInstance->Logs.Normal(MODNAME, "Module was compiled against yyjson version {} and is running against version {}.{}.{}",
YYJSON_VERSION_STRING, (yyversion >> 16) & 0xFF, (yyversion >> 8) & 0xFF, yyversion & 0xFF);
#else
ServerInstance->Logs.Normal(MODNAME, "Module was compiled against RapidJSON version {}",
RAPIDJSON_VERSION_STRING);
#endif
}
};

View File

@ -12,9 +12,9 @@ libpq/15.5
libpsl/0.21.1
## openssl/3.2.2
pcre2/10.44
rapidjson/cci.20230929
re2/20240702
sqlite3/3.46.0
yyjson/0.10.0
[options]
argon2:shared=True
@ -26,6 +26,7 @@ openssl:shared=True
pcre2:shared=True
re2:shared=True
sqlite3:shared=True
yyjson:shared=True
[imports]
., *.dll -> extradll @ keep_path=False

View File

@ -43,7 +43,7 @@ if(EXISTS "${CMAKE_BINARY_DIR}/conanbuildinfo.cmake")
enable_extra("argon2" "ARGON2")
enable_extra("geo_maxmind" "LIBMAXMINDDB")
enable_extra("log_json" "RAPIDJSON")
enable_extra("log_json" "YYJSON")
enable_extra("mysql" "LIBMYSQLCLIENT")
enable_extra("pgsql" "LIBPQ")
enable_extra("regex_pcre2" "PCRE2")