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 \ pcre2-dev \
perl \ perl \
pkgconf \ pkgconf \
rapidjson-dev \
re2-dev \ re2-dev \
sqlite-dev sqlite-dev \
yyjson-dev
- name: Run configure - name: Run configure
run: | run: |

View File

@ -25,7 +25,7 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: | run: |
brew update || true 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 do
brew install $PACKAGE || brew upgrade $PACKAGE 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', 'mysql' => 'mysql_config --version',
'pgsql' => 'pg_config --version', 'pgsql' => 'pg_config --version',
'ldap' => "pkg-config --exists lber && pkg-config --exists ldap", 'ldap' => "pkg-config --exists lber && pkg-config --exists ldap",
'log_json' => 'pkg-config --exists RapidJSON', 'log_json' => 'pkg-config --exists yyjson',
'log_syslog' => undef, 'log_syslog' => undef,
'regex_pcre2' => 'pkg-config --exists libpcre2-8', 'regex_pcre2' => 'pkg-config --exists libpcre2-8',
'regex_posix' => undef, 'regex_posix' => undef,

View File

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

View File

@ -16,20 +16,32 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * 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 /// $LinkerFlags: require_library("yyjson") find_linker_flags("yyjson")
/// $PackageInfo: require_system("arch") rapidjson pkgconf
/// $PackageInfo: require_system("darwin") rapidjson pkg-config /// $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 /// $PackageInfo: require_system("debian~") rapidjson-dev pkg-config
#ifdef _WIN32
# define HAS_YYJSON
# pragma comment(lib, "yyjson.lib")
#endif
#ifdef HAS_YYJSON
# include <yyjson.h>
#else
# include <rapidjson/ostreamwrapper.h> # include <rapidjson/ostreamwrapper.h>
# include <rapidjson/writer.h> # include <rapidjson/writer.h>
#endif
#include "inspircd.h" #include "inspircd.h"
#include "timeutils.h" #include "timeutils.h"
#include <iostream>
class JSONMethod final class JSONMethod final
: public Log::Method : public Log::Method
, public Timer , public Timer
@ -71,8 +83,10 @@ public:
fclose(file); fclose(file);
} }
#ifndef HAS_YYJSON
// RapidJSON API: We implement our own flushing in OnLog. // RapidJSON API: We implement our own flushing in OnLog.
void Flush() { } void Flush() { }
#endif
void OnLog(time_t time, Log::Level level, const std::string& type, const std::string& message) override 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"); 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); rapidjson::Writer writer(*this);
writer.StartObject(); writer.StartObject();
{ {
@ -94,8 +130,7 @@ public:
writer.String(type.c_str(), static_cast<rapidjson::SizeType>(type.size())); writer.String(type.c_str(), static_cast<rapidjson::SizeType>(type.size()));
writer.Key("level", 5); writer.Key("level", 5);
const std::string levelstr = Log::LevelToString(level); writer.String(levelstr, static_cast<rapidjson::SizeType>(strlen(levelstr)));
writer.String(levelstr.c_str(), static_cast<rapidjson::SizeType>(levelstr.size()));
writer.Key("message", 7); writer.Key("message", 7);
writer.Key(message.c_str(), static_cast<rapidjson::SizeType>(message.size())); writer.Key(message.c_str(), static_cast<rapidjson::SizeType>(message.size()));
@ -106,6 +141,7 @@ public:
fputs("\r\n", file); fputs("\r\n", file);
# else # else
fputs("\n", file); fputs("\n", file);
# endif
#endif #endif
if (!(++lines % flush)) if (!(++lines % flush))
@ -115,11 +151,13 @@ public:
throw CoreException(INSP_FORMAT("Unable to write to {}: {}", name, strerror(errno))); throw CoreException(INSP_FORMAT("Unable to write to {}: {}", name, strerror(errno)));
} }
#ifndef HAS_YYJSON
// RapidJSON API: Write a character to the file. // RapidJSON API: Write a character to the file.
void Put(Ch c) void Put(Ch c)
{ {
fputc(c, file); fputc(c, file);
} }
#endif
bool Tick() override bool Tick() override
{ {
@ -194,8 +232,14 @@ public:
void init() override 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 {}", ServerInstance->Logs.Normal(MODNAME, "Module was compiled against RapidJSON version {}",
RAPIDJSON_VERSION_STRING); RAPIDJSON_VERSION_STRING);
#endif
} }
}; };

View File

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

View File

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