From 7271bcaf05fdd409c6ea24d74df76961aff8d196 Mon Sep 17 00:00:00 2001 From: Robert Adam Date: Sat, 11 Jan 2025 17:56:39 +0100 Subject: [PATCH] FIX(server): Respect Qt's desired initialization order In a Qt application, the QApplication object should be the first QObject that is created. However, the `Meta` class used to have a static member called `mp`, which means that this member gets initialized _before_ main() runs and therefore before the QApplication is created. This has caused an "Invalid nullptr in QObject::connect" warning somewhere in Qt's internals (since the move to Qt 6). The impact of this warning is unclear at this point. This commit makes the mp parameter a std::unique_ptr that gets explicitly initialized in the main function (more or less right after the QApplication object is created). This guarantees that the MetaParams object does not get created before the QApplication object, fixing the observed warning. It is worth noting that we do have a couple of other static QObject variables in the main translation unit, but these seem to be inconsequential (at least they don't seem to trigger a similar warning). Fixes #6669 --- scripts/generateIceWrapper.py | 14 +- src/PacketDataStream.cpp | 353 +++++++++++++++++++++++++++++++++ src/backup | 187 +++++++++++++++++ src/murmur/Cert.cpp | 16 +- src/murmur/Messages.cpp | 25 +-- src/murmur/Meta.cpp | 14 +- src/murmur/Meta.h | 4 +- src/murmur/MumbleServerIce.cpp | 19 +- src/murmur/Register.cpp | 6 +- src/murmur/Server.cpp | 156 +++++++-------- src/murmur/ServerDB.cpp | 174 ++++++++-------- src/murmur/UnixMurmur.cpp | 34 ++-- src/murmur/main.cpp | 41 ++-- 13 files changed, 795 insertions(+), 248 deletions(-) create mode 100644 src/PacketDataStream.cpp create mode 100644 src/backup diff --git a/scripts/generateIceWrapper.py b/scripts/generateIceWrapper.py index 2a6eac385..eaf208983 100755 --- a/scripts/generateIceWrapper.py +++ b/scripts/generateIceWrapper.py @@ -37,23 +37,23 @@ def create_disclaimerComment(): def generateFunction(className, functionName, wrapArgs, callArgs): function = "void ::MumbleServer::" + className + "I::" + functionName + "_async(" + (", ".join(wrapArgs)) + ") {\n" - function += "\t// qWarning() << \"" + functionName + "\" << meta->mp.qsIceSecretRead.isNull() << meta->mp.qsIceSecretRead.isEmpty();\n" + function += "\t// qWarning() << \"" + functionName + "\" << ::Meta::mp->qsIceSecretRead.isNull() << ::Meta::mp->qsIceSecretRead.isEmpty();\n" function += "#ifndef ACCESS_" + className + "_" + functionName + "_ALL\n" function += "#\tifdef ACCESS_" + className + "_" + functionName + "_READ\n" - function += "\tif (!meta->mp.qsIceSecretRead.isNull()) {\n" - function += "\t\tbool ok = !meta->mp.qsIceSecretRead.isEmpty();\n" + function += "\tif (!::Meta::mp->qsIceSecretRead.isNull()) {\n" + function += "\t\tbool ok = !::Meta::mp->qsIceSecretRead.isEmpty();\n" function += "#\telse\n" - function += "\tif (!meta->mp.qsIceSecretRead.isNull() || !meta->mp.qsIceSecretWrite.isNull()) {\n" - function += "\t\tbool ok = !meta->mp.qsIceSecretWrite.isEmpty();\n" + function += "\tif (!::Meta::mp->qsIceSecretRead.isNull() || !::Meta::mp->qsIceSecretWrite.isNull()) {\n" + function += "\t\tbool ok = !::Meta::mp->qsIceSecretWrite.isEmpty();\n" function += "#\tendif // ACCESS_" + className + "_" + functionName + "_READ\n" function += "\t\t::Ice::Context::const_iterator i = current.ctx.find(\"secret\");\n" function += "\t\tok = ok && (i != current.ctx.end());\n" function += "\t\tif (ok) {\n" function += "\t\t\tconst QString &secret = u8((*i).second);\n" function += "#\tifdef ACCESS_" + className + "_" + functionName + "_READ\n" - function += "\t\t\tok = ((secret == meta->mp.qsIceSecretRead) || (secret == meta->mp.qsIceSecretWrite));\n" + function += "\t\t\tok = ((secret == ::Meta::mp->qsIceSecretRead) || (secret == ::Meta::mp->qsIceSecretWrite));\n" function += "#\telse\n" - function += "\t\t\tok = (secret == meta->mp.qsIceSecretWrite);\n" + function += "\t\t\tok = (secret == ::Meta::mp->qsIceSecretWrite);\n" function += "#\tendif // ACCESS_" + className + "_" + functionName + "_READ\n" function += "\t\t}\n" function += "\n" diff --git a/src/PacketDataStream.cpp b/src/PacketDataStream.cpp new file mode 100644 index 000000000..56a6d0451 --- /dev/null +++ b/src/PacketDataStream.cpp @@ -0,0 +1,353 @@ +// Copyright The Mumble Developers. All rights reserved. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file at the root of the +// Mumble source tree or at . + +#include "PacketDataStream.h" + +quint32 PacketDataStream::size() const { + return offset; +} + +quint32 PacketDataStream::capacity() const { + return maxsize; +} + +bool PacketDataStream::isValid() const { + return ok; +} + +quint32 PacketDataStream::left() const { + return maxsize - offset; +} + +quint32 PacketDataStream::undersize() const { + return overshoot; +} + +void PacketDataStream::append(const quint64 v) { +#ifndef QT_NO_DEBUG + Q_ASSERT(v <= 0xff); +#endif + if (offset < maxsize) + data[offset++] = static_cast< unsigned char >(v); + else { + ok = false; + overshoot++; + } +}; + +void PacketDataStream::append(const char *d, quint32 len) { + if (left() >= len) { + memcpy(&data[offset], d, len); + offset += len; + } else { + unsigned int l = left(); + memset(&data[offset], 0, l); + offset += l; + overshoot += len - l; + ok = false; + } +} + +void PacketDataStream::skip(quint32 len) { + if (left() >= len) + offset += len; + else + ok = false; +} + +quint64 PacketDataStream::next() { + if (offset < maxsize) + return data[offset++]; + else { + ok = false; + return 0; + } +}; + +quint8 PacketDataStream::next8() { + if (offset < maxsize) + return data[offset++]; + else { + ok = false; + return 0; + } +} + +void PacketDataStream::rewind() { + offset = 0; +} + +void PacketDataStream::truncate() { + maxsize = offset; +} + +const unsigned char *PacketDataStream::dataPtr() const { + return reinterpret_cast< const unsigned char * >(&data[offset]); +} + +unsigned char *PacketDataStream::dataPtr() { + return reinterpret_cast< unsigned char * >(&data[offset]); +} + +const char *PacketDataStream::charPtr() const { + return reinterpret_cast< const char * >(&data[offset]); +} + +QByteArray PacketDataStream::dataBlock(quint32 len) { + if (len <= left()) { + QByteArray a(charPtr(), static_cast< int >(len)); + offset += len; + return a; + } else { + ok = false; + return QByteArray(); + } +} + +void PacketDataStream::setup(unsigned char *d, unsigned int msize) { + data = d; + offset = 0; + overshoot = 0; + maxsize = msize; + ok = true; +} + +PacketDataStream::PacketDataStream(const unsigned char *d, unsigned int msize) { + setup(const_cast< unsigned char * >(d), msize); +}; + +PacketDataStream::PacketDataStream(const char *d, unsigned int msize) { + setup(const_cast< unsigned char * >(reinterpret_cast< const unsigned char * >(d)), msize); +}; + +PacketDataStream::PacketDataStream(char *d, unsigned int msize) { + setup(reinterpret_cast< unsigned char * >(d), msize); +}; + +PacketDataStream::PacketDataStream(unsigned char *d, unsigned int msize) { + setup(d, msize); +}; + +PacketDataStream::PacketDataStream(const QByteArray &qba) { + setup(const_cast< unsigned char * >(reinterpret_cast< const unsigned char * >(qba.constData())), + static_cast< unsigned int >(qba.size())); +} + +PacketDataStream::PacketDataStream(QByteArray &qba) { + unsigned char *ptr = reinterpret_cast< unsigned char * >(qba.data()); + setup(ptr, static_cast< unsigned int >(qba.capacity())); +} + +PacketDataStream &PacketDataStream::operator<<(const quint64 value) { + quint64 i = value; + + if ((i & 0x8000000000000000LL) && (~i < 0x100000000LL)) { + // Signed number. + i = ~i; + if (i <= 0x3) { + // Special case for -1 to -4. The most significant bits of the first byte must be (in binary) 111111 + // followed by the 2 bits representing the absolute value of the encoded number. Shortcase for -1 to -4 + append(0xFC | i); + return *this; + } else { + // Add flag byte, whose most significant bits are (in binary) 111110 that indicates + // that what follows is the varint encoding of the absolute value of i, but that the + // value itself is supposed to be negative. + append(0xF8); + } + } + if (i < 0x80) { + // Encode as 7-bit, positive number -> most significant bit of first byte must be zero + append(i); + } else if (i < 0x4000) { + // Encode as 14-bit, positive number -> most significant bits of first byte must be (in binary) 10 + append((i >> 8) | 0x80); + append(i & 0xFF); + } else if (i < 0x200000) { + // Encode as 21-bit, positive number -> most significant bits of first byte must be (in binary) 110 + append((i >> 16) | 0xC0); + append((i >> 8) & 0xFF); + append(i & 0xFF); + } else if (i < 0x10000000) { + // Encode as 28-bit, positive number -> most significant bits of first byte must be (in binary) 1110 + append((i >> 24) | 0xE0); + append((i >> 16) & 0xFF); + append((i >> 8) & 0xFF); + append(i & 0xFF); + } else if (i < 0x100000000LL) { + // Encode as 32-bit, positive number -> most significant bits of first byte must be (in binary) 111100 + // Remaining bits in first byte remain unused + append(0xF0); + append((i >> 24) & 0xFF); + append((i >> 16) & 0xFF); + append((i >> 8) & 0xFF); + append(i & 0xFF); + } else { + // Encode as 64-bit, positive number -> most significant bits of first byte must be (in binary) 111101 + // Remaining bits in first byte remain unused + append(0xF4); + append((i >> 56) & 0xFF); + append((i >> 48) & 0xFF); + append((i >> 40) & 0xFF); + append((i >> 32) & 0xFF); + append((i >> 24) & 0xFF); + append((i >> 16) & 0xFF); + append((i >> 8) & 0xFF); + append(i & 0xFF); + } + return *this; +} + +PacketDataStream &PacketDataStream::operator>>(quint64 &i) { + quint64 v = next(); + + if ((v & 0x80) == 0x00) { + i = (v & 0x7F); + } else if ((v & 0xC0) == 0x80) { + i = (v & 0x3F) << 8 | next(); + } else if ((v & 0xF0) == 0xF0) { + switch (v & 0xFC) { + case 0xF0: + i = next() << 24 | next() << 16 | next() << 8 | next(); + break; + case 0xF4: + i = next() << 56 | next() << 48 | next() << 40 | next() << 32 | next() << 24 | next() << 16 + | next() << 8 | next(); + break; + case 0xF8: + *this >> i; + i = ~i; + break; + case 0xFC: + i = v & 0x03; + i = ~i; + break; + default: + ok = false; + i = 0; + break; + } + } else if ((v & 0xF0) == 0xE0) { + i = (v & 0x0F) << 24 | next() << 16 | next() << 8 | next(); + } else if ((v & 0xE0) == 0xC0) { + i = (v & 0x1F) << 16 | next() << 8 | next(); + } + return *this; +} + +PacketDataStream &PacketDataStream::operator<<(const QByteArray &a) { + *this << a.size(); + append(a.constData(), static_cast< unsigned int >(a.size())); + return *this; +} + +PacketDataStream &PacketDataStream::operator>>(QByteArray &a) { + quint32 len; + *this >> len; + if (len > left()) { + len = left(); + ok = false; + } + a = QByteArray(reinterpret_cast< const char * >(&data[offset]), static_cast< int >(len)); + offset += len; + return *this; +} + +PacketDataStream &PacketDataStream::operator<<(const QString &s) { + return *this << s.toUtf8(); +} + +// Using the data directly instead of through qbuff avoids a copy. +PacketDataStream &PacketDataStream::operator>>(QString &s) { + quint32 len; + *this >> len; + if (len > left()) { + len = left(); + ok = false; + } + s = QString::fromUtf8(reinterpret_cast< const char * >(&data[offset]), static_cast< int >(len)); + offset += len; + return *this; +} + +PacketDataStream &PacketDataStream::operator<<(const bool b) { + quint32 v = b ? 1 : 0; + return *this << v; +} + +PacketDataStream &PacketDataStream::operator>>(bool &b) { + quint32 v; + *this >> v; + b = v ? true : false; + return *this; +} + +union double64u { + quint64 ui; + double d; +}; + +PacketDataStream &PacketDataStream::operator<<(const double v) { + double64u u; + u.d = v; + return *this << u.ui; +} + +PacketDataStream &PacketDataStream::operator>>(double &v) { + double64u u; + *this >> u.ui; + v = u.d; + return *this; +} + +union float32u { + quint8 ui[4]; + float f; +}; + +PacketDataStream &PacketDataStream::operator<<(const float v) { + float32u u; + u.f = v; + append(u.ui[0]); + append(u.ui[1]); + append(u.ui[2]); + append(u.ui[3]); + return *this; +} + +PacketDataStream &PacketDataStream::operator>>(float &v) { + float32u u; + if (left() < 4) { + ok = false; + v = 0; + } + u.ui[0] = next8(); + u.ui[1] = next8(); + u.ui[2] = next8(); + u.ui[3] = next8(); + v = u.f; + return *this; +} + +#define INTMAPOPERATOR(type) \ + template<> PacketDataStream &PacketDataStream::operator<<< type >(const type v) { \ + return *this << static_cast< quint64 >(v); \ + } \ + template<> PacketDataStream &PacketDataStream::operator>>< type >(type &v) { \ + quint64 vv; \ + *this >> vv; \ + v = static_cast< type >(vv); \ + return *this; \ + } + +// INTMAPOPERATOR(qsizetype); +INTMAPOPERATOR(int); +INTMAPOPERATOR(unsigned int); +INTMAPOPERATOR(short); +INTMAPOPERATOR(unsigned short); +INTMAPOPERATOR(char); +INTMAPOPERATOR(unsigned char); + +#undef INTMAPOPERATOR diff --git a/src/backup b/src/backup new file mode 100644 index 000000000..6edac69a2 --- /dev/null +++ b/src/backup @@ -0,0 +1,187 @@ +// Copyright The Mumble Developers. All rights reserved. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file at the root of the +// Mumble source tree or at . + +#ifndef MUMBLE_PACKETDATASTREAM_H_ +#define MUMBLE_PACKETDATASTREAM_H_ + +#include +#include +#include + +#include +#include +#include + +class PacketDataStream { +private: + Q_DISABLE_COPY(PacketDataStream) +private: + unsigned char *data; + quint32 maxsize; + quint32 offset; + quint32 overshoot; + bool ok; + +public: + quint32 size() const; + + quint32 capacity() const; + + bool isValid() const; + + quint32 left() const; + + quint32 undersize() const; + + void append(const quint64 v); + + void append(const char *d, quint32 len); + + void skip(quint32 len); + + quint64 next(); + quint8 next8(); + void rewind(); + + void truncate(); + + const unsigned char *dataPtr() const; + + unsigned char *dataPtr(); + + const char *charPtr() const; + + QByteArray dataBlock(quint32 len); + +protected: + void setup(unsigned char *d, unsigned int msize); + +public: + PacketDataStream(const unsigned char *d, unsigned int msize); + + PacketDataStream(const char *d, unsigned int msize); + + PacketDataStream(char *d, unsigned int msize); + + PacketDataStream(unsigned char *d, unsigned int msize); + + PacketDataStream(const QByteArray &qba); + + PacketDataStream(QByteArray &qba); + + PacketDataStream &operator<<(const quint64 value); + + PacketDataStream &operator>>(quint64 &i); + + PacketDataStream &operator<<(const QByteArray &a); + + PacketDataStream &operator>>(QByteArray &a); + + PacketDataStream &operator<<(const QString &s); + + // Using the data directly instead of through qbuff avoids a copy. + PacketDataStream &operator>>(QString &s); + + PacketDataStream &operator<<(const bool b); + + PacketDataStream &operator>>(bool &b); + + template< typename Integer, typename = std::enable_if_t< std::is_integral_v< Integer > > > + PacketDataStream &operator<<(const Integer v); + template< typename Integer, typename = std::enable_if_t< std::is_integral_v< Integer > > > + PacketDataStream &operator>>(Integer &v); + + PacketDataStream &operator<<(const double v); + + PacketDataStream &operator>>(double &v); + + PacketDataStream &operator<<(const float v); + + PacketDataStream &operator>>(float &v); + + template< typename T > PacketDataStream &operator<<(const QList< T > &l) { + *this << l.size(); + for (int i = 0; i < l.size(); i++) + *this << l.at(i); + return *this; + } + + template< typename T > PacketDataStream &operator>>(QList< T > &l) { + l.clear(); + quint32 len; + *this >> len; + if (len > left()) { + len = left(); + ok = false; + } + for (quint32 i = 0; i < len; i++) { + if (left() == 0) { + ok = false; + break; + } + + T t; + *this >> t; + l.append(t); + } + return *this; + } + + + template< typename T > PacketDataStream &operator<<(const QSet< T > &s) { + *this << s.size(); + for (typename QSet< T >::const_iterator i = s.constBegin(); i != s.constEnd(); ++i) + *this << *i; + return *this; + } + + template< typename T > PacketDataStream &operator>>(QSet< T > &s) { + s.clear(); + quint32 len; + *this >> len; + if (len > left()) { + len = left(); + ok = false; + } + for (quint32 i = 0; i < len; i++) { + if (left() == 0) { + ok = false; + break; + } + + T t; + *this >> t; + s.insert(t); + } + return *this; + } + + template< typename T, typename U > PacketDataStream &operator<<(const QPair< T, U > &p) { + return *this << p.first << p.second; + } + + template< typename T, typename U > PacketDataStream &operator>>(QPair< T, U > &p) { + return *this >> p.first >> p.second; + } +}; + +#define INTMAPOPERATOR_DECLARE(type) \ + template<> PacketDataStream &PacketDataStream::operator<<< type >(const type v); \ + template<> PacketDataStream &PacketDataStream::operator>>< type >(type &v); + +//INTMAPOPERATOR_DECLARE(qsizetype) +INTMAPOPERATOR_DECLARE(std::int8_t) +INTMAPOPERATOR_DECLARE(std::uint8_t) +INTMAPOPERATOR_DECLARE(std::int16_t) +INTMAPOPERATOR_DECLARE(std::uint16_t) +INTMAPOPERATOR_DECLARE(std::int32_t) +INTMAPOPERATOR_DECLARE(std::uint32_t) +INTMAPOPERATOR_DECLARE(std::int64_t) +INTMAPOPERATOR_DECLARE(std::uint64_t) + +#undef INTMAPOPERATOR_DECLARE + + +#endif diff --git a/src/murmur/Cert.cpp b/src/murmur/Cert.cpp index afbf00f09..71ec363df 100644 --- a/src/murmur/Cert.cpp +++ b/src/murmur/Cert.cpp @@ -81,7 +81,7 @@ void Server::initializeCert() { crt = getConf("certificate", QString()).toByteArray(); key = getConf("key", QString()).toByteArray(); pass = getConf("passphrase", QByteArray()).toByteArray(); - dhparams = getConf("sslDHParams", Meta::mp.qbaDHParams).toByteArray(); + dhparams = getConf("sslDHParams", Meta::mp->qbaDHParams).toByteArray(); QList< QSslCertificate > ql; @@ -148,10 +148,10 @@ void Server::initializeCert() { // This allows a self-signed certificate generated by Murmur to be // replaced by a CA-signed certificate in the .ini file. if (!qscCert.isNull() && issuer.startsWith(QString::fromUtf8("Murmur Autogenerated Certificate")) - && !Meta::mp.qscCert.isNull() && !Meta::mp.qskKey.isNull() && (Meta::mp.qlBind == qlBind)) { - qscCert = Meta::mp.qscCert; - qskKey = Meta::mp.qskKey; - qlIntermediates = Meta::mp.qlIntermediates; + && !Meta::mp->qscCert.isNull() && !Meta::mp->qskKey.isNull() && (Meta::mp->qlBind == qlBind)) { + qscCert = Meta::mp->qscCert; + qskKey = Meta::mp->qskKey; + qlIntermediates = Meta::mp->qlIntermediates; if (!qscCert.isNull() && !qskKey.isNull()) { bUsingMetaCert = true; @@ -164,9 +164,9 @@ void Server::initializeCert() { log("Certificate specified, but failed to load."); } - qskKey = Meta::mp.qskKey; - qscCert = Meta::mp.qscCert; - qlIntermediates = Meta::mp.qlIntermediates; + qskKey = Meta::mp->qskKey; + qscCert = Meta::mp->qscCert; + qlIntermediates = Meta::mp->qlIntermediates; if (!qscCert.isNull() && !qskKey.isNull()) { bUsingMetaCert = true; diff --git a/src/murmur/Messages.cpp b/src/murmur/Messages.cpp index ae4f7eb64..afb96c4b7 100644 --- a/src/murmur/Messages.cpp +++ b/src/murmur/Messages.cpp @@ -610,14 +610,14 @@ void Server::msgAuthenticate(ServerUser *uSource, MumbleProto::Authenticate &msg sendMessage(uSource, mpsug); } - if (uSource->m_version < Version::fromComponents(1, 4, 0) && Meta::mp.iMaxListenersPerChannel != 0 - && Meta::mp.iMaxListenerProxiesPerUser != 0) { + if (uSource->m_version < Version::fromComponents(1, 4, 0) && Meta::mp->iMaxListenersPerChannel != 0 + && Meta::mp->iMaxListenerProxiesPerUser != 0) { // The server has the ChannelListener feature enabled but the client that connects doesn't have version 1.4.0 or // newer meaning that this client doesn't know what ChannelListeners are. Thus we'll send that user a // text-message informing about this. MumbleProto::TextMessage mptm; - if (Meta::mp.bAllowHTML) { + if (Meta::mp->bAllowHTML) { mptm.set_message("[WARNING]: This server has the ChannelListener feature enabled but your " "client version does not support it. " "This means that users might be listening to what you are saying in your channel " @@ -797,16 +797,17 @@ void Server::msgUserState(ServerUser *uSource, MumbleProto::UserState &msg) { continue; } - if (Meta::mp.iMaxListenersPerChannel >= 0 - && Meta::mp.iMaxListenersPerChannel - m_channelListenerManager.getListenerCountForChannel(c->iId) - 1 < 0) { + if (Meta::mp->iMaxListenersPerChannel >= 0 + && Meta::mp->iMaxListenersPerChannel - m_channelListenerManager.getListenerCountForChannel(c->iId) - 1 + < 0) { // A limit for the amount of listener proxies per channel is set and it has been reached already PERM_DENIED_FALLBACK(ChannelListenerLimit, Version::fromComponents(1, 4, 0), QLatin1String("No more listeners allowed in this channel")); continue; } - if (Meta::mp.iMaxListenerProxiesPerUser >= 0 - && Meta::mp.iMaxListenerProxiesPerUser + if (Meta::mp->iMaxListenerProxiesPerUser >= 0 + && Meta::mp->iMaxListenerProxiesPerUser - m_channelListenerManager.getListenedChannelCountForUser(uSource->uiSession) - passedChannelListener - 1 < 0) { @@ -1856,11 +1857,11 @@ void Server::msgACL(ServerUser *uSource, MumbleProto::ACL &msg) { QHash< QString, QSet< int > > hOldTemp; - if (Meta::mp.bLogGroupChanges || Meta::mp.bLogACLChanges) { + if (Meta::mp->bLogGroupChanges || Meta::mp->bLogACLChanges) { log(uSource, QString::fromLatin1("Updating ACL in channel %1").arg(*c)); } - if (Meta::mp.bLogGroupChanges) { + if (Meta::mp->bLogGroupChanges) { logGroups(this, c, QLatin1String("These are the groups before applying the change:")); } @@ -1869,7 +1870,7 @@ void Server::msgACL(ServerUser *uSource, MumbleProto::ACL &msg) { delete g; } - if (Meta::mp.bLogACLChanges) { + if (Meta::mp->bLogACLChanges) { logACLs(this, c, QLatin1String("These are the ACLs before applying the changed:")); } @@ -1897,7 +1898,7 @@ void Server::msgACL(ServerUser *uSource, MumbleProto::ACL &msg) { g->qsTemporary = hOldTemp.value(g->qsName); } - if (Meta::mp.bLogGroupChanges) { + if (Meta::mp->bLogGroupChanges) { logGroups(this, c, QLatin1String("And these are the new groups:")); } @@ -1918,7 +1919,7 @@ void Server::msgACL(ServerUser *uSource, MumbleProto::ACL &msg) { a->pAllow = static_cast< ChanACL::Permissions >(mpacl.grant()) & ChanACL::All; } - if (Meta::mp.bLogACLChanges) { + if (Meta::mp->bLogACLChanges) { logACLs(this, c, QLatin1String("And these are the new ACLs:")); } } diff --git a/src/murmur/Meta.cpp b/src/murmur/Meta.cpp index ef750b547..c0971149a 100644 --- a/src/murmur/Meta.cpp +++ b/src/murmur/Meta.cpp @@ -37,7 +37,7 @@ #include -MetaParams Meta::mp; +std::unique_ptr< MetaParams > Meta::mp; #ifdef Q_OS_WIN HANDLE Meta::hQoS = nullptr; @@ -651,7 +651,7 @@ Meta::~Meta() { bool Meta::reloadSSLSettings() { // Reload SSL settings. - if (!Meta::mp.loadSSLSettings()) { + if (!Meta::mp->loadSSLSettings()) { return false; } @@ -744,7 +744,7 @@ void Meta::killAll() { } void Meta::successfulConnectionFrom(const QHostAddress &addr) { - if (!mp.bBanSuccessful) { + if (!mp->bBanSuccessful) { QList< Timer > &ql = qhAttempts[addr]; // Seems like this is the most efficient way to clear the list, given: // 1. ql.clear() allocates a new array @@ -757,12 +757,12 @@ void Meta::successfulConnectionFrom(const QHostAddress &addr) { } bool Meta::banCheck(const QHostAddress &addr) { - if ((mp.iBanTries <= 0) || (mp.iBanTimeframe <= 0)) + if ((mp->iBanTries <= 0) || (mp->iBanTimeframe <= 0)) return false; if (qhBans.contains(addr)) { Timer t = qhBans.value(addr); - if (t.elapsed() < (1000000ULL * static_cast< unsigned long long >(mp.iBanTime))) + if (t.elapsed() < (1000000ULL * static_cast< unsigned long long >(mp->iBanTime))) return true; qhBans.remove(addr); } @@ -770,10 +770,10 @@ bool Meta::banCheck(const QHostAddress &addr) { QList< Timer > &ql = qhAttempts[addr]; ql.append(Timer()); - while (!ql.isEmpty() && (ql.at(0).elapsed() > (1000000ULL * static_cast< unsigned long long >(mp.iBanTimeframe)))) + while (!ql.isEmpty() && (ql.at(0).elapsed() > (1000000ULL * static_cast< unsigned long long >(mp->iBanTimeframe)))) ql.removeFirst(); - if (ql.count() > mp.iBanTries) { + if (ql.count() > mp->iBanTries) { qhBans.insert(addr, Timer()); return true; } diff --git a/src/murmur/Meta.h b/src/murmur/Meta.h index 4a151506e..c409da67b 100644 --- a/src/murmur/Meta.h +++ b/src/murmur/Meta.h @@ -24,6 +24,8 @@ #include #include +#include + class Server; class QSettings; @@ -177,7 +179,7 @@ private: Q_DISABLE_COPY(Meta) public: - static MetaParams mp; + static std::unique_ptr< MetaParams > mp; QHash< int, Server * > qhServers; QHash< QHostAddress, QList< Timer > > qhAttempts; QHash< QHostAddress, Timer > qhBans; diff --git a/src/murmur/MumbleServerIce.cpp b/src/murmur/MumbleServerIce.cpp index cb6477eb4..11a6ff82d 100644 --- a/src/murmur/MumbleServerIce.cpp +++ b/src/murmur/MumbleServerIce.cpp @@ -231,16 +231,16 @@ public: MumbleServerIce::MumbleServerIce() { count = 0; - if (meta->mp.qsIceEndpoint.isEmpty()) + if (::Meta::mp->qsIceEndpoint.isEmpty()) return; Ice::PropertiesPtr ipp = Ice::createProperties(); - ::Meta::mp.qsSettings->beginGroup("Ice"); - foreach (const QString &v, ::Meta::mp.qsSettings->childKeys()) { - ipp->setProperty(iceString(v), iceString(::Meta::mp.qsSettings->value(v).toString())); + ::Meta::mp->qsSettings->beginGroup("Ice"); + foreach (const QString &v, ::Meta::mp->qsSettings->childKeys()) { + ipp->setProperty(iceString(v), iceString(::Meta::mp->qsSettings->value(v).toString())); } - ::Meta::mp.qsSettings->endGroup(); + ::Meta::mp->qsSettings->endGroup(); Ice::PropertyDict props = ippProperties->getPropertiesForPrefix(""); Ice::PropertyDict::iterator i; @@ -254,12 +254,13 @@ MumbleServerIce::MumbleServerIce() { try { communicator = Ice::initialize(idd); - if (!meta->mp.qsIceSecretWrite.isEmpty()) { + if (!::Meta::mp->qsIceSecretWrite.isEmpty()) { ::Ice::ImplicitContextPtr impl = communicator->getImplicitContext(); if (impl) - impl->put("secret", iceString(meta->mp.qsIceSecretWrite)); + impl->put("secret", iceString(::Meta::mp->qsIceSecretWrite)); } - adapter = communicator->createObjectAdapterWithEndpoints("Mumble Server", qPrintable(meta->mp.qsIceEndpoint)); + adapter = + communicator->createObjectAdapterWithEndpoints("Mumble Server", qPrintable(::Meta::mp->qsIceEndpoint)); MetaPtr m = new MetaI; #if ICE_INT_VERSION >= 30700 MetaPrx mprx = MetaPrx::uncheckedCast(adapter->add(m, Ice::stringToIdentity("Meta"))); @@ -1933,7 +1934,7 @@ static void impl_Meta_getAllServers(const ::MumbleServer::AMD_Meta_getAllServers static void impl_Meta_getDefaultConf(const ::MumbleServer::AMD_Meta_getDefaultConfPtr cb, const Ice::ObjectAdapterPtr) { ::MumbleServer::ConfigMap cm; QMap< QString, QString >::const_iterator i; - for (i = meta->mp.qmConfig.constBegin(); i != meta->mp.qmConfig.constEnd(); ++i) { + for (i = ::Meta::mp->qmConfig.constBegin(); i != ::Meta::mp->qmConfig.constEnd(); ++i) { if (i.key() == "key" || i.key() == "passphrase") continue; cm[iceString(i.key())] = iceString(i.value()); diff --git a/src/murmur/Register.cpp b/src/murmur/Register.cpp index b9f2de027..2af433fe4 100644 --- a/src/murmur/Register.cpp +++ b/src/murmur/Register.cpp @@ -105,12 +105,12 @@ void Server::update() { /* Work around bug in QSslConfiguration */ QList< QSslCertificate > calist = ssl.caCertificates(); calist << QSslConfiguration::defaultConfiguration().caCertificates(); - calist << Meta::mp.qlCA; - calist << Meta::mp.qlIntermediates; + calist << Meta::mp->qlCA; + calist << Meta::mp->qlIntermediates; calist << qscCert; ssl.setCaCertificates(calist); - ssl.setCiphers(Meta::mp.qlCiphers); + ssl.setCiphers(Meta::mp->qlCiphers); qnr.setSslConfiguration(ssl); diff --git a/src/murmur/Server.cpp b/src/murmur/Server.cpp index 17800b3c6..983247f82 100644 --- a/src/murmur/Server.cpp +++ b/src/murmur/Server.cpp @@ -323,44 +323,44 @@ Server::~Server() { } void Server::readParams() { - qsPassword = Meta::mp.qsPassword; - usPort = static_cast< unsigned short >(Meta::mp.usPort + iServerNum - 1); - iTimeout = Meta::mp.iTimeout; - iMaxBandwidth = Meta::mp.iMaxBandwidth; - iMaxUsers = Meta::mp.iMaxUsers; - iMaxUsersPerChannel = Meta::mp.iMaxUsersPerChannel; - iMaxTextMessageLength = Meta::mp.iMaxTextMessageLength; - iMaxImageMessageLength = Meta::mp.iMaxImageMessageLength; - bAllowHTML = Meta::mp.bAllowHTML; - iDefaultChan = Meta::mp.iDefaultChan; - bRememberChan = Meta::mp.bRememberChan; - iRememberChanDuration = Meta::mp.iRememberChanDuration; - qsWelcomeText = Meta::mp.qsWelcomeText; - qsWelcomeTextFile = Meta::mp.qsWelcomeTextFile; - qlBind = Meta::mp.qlBind; - qsRegName = Meta::mp.qsRegName; - qsRegPassword = Meta::mp.qsRegPassword; - qsRegHost = Meta::mp.qsRegHost; - qsRegLocation = Meta::mp.qsRegLocation; - qurlRegWeb = Meta::mp.qurlRegWeb; - bBonjour = Meta::mp.bBonjour; - bAllowPing = Meta::mp.bAllowPing; - allowRecording = Meta::mp.allowRecording; - bCertRequired = Meta::mp.bCertRequired; - bForceExternalAuth = Meta::mp.bForceExternalAuth; - qrUserName = Meta::mp.qrUserName; - qrChannelName = Meta::mp.qrChannelName; - iMessageLimit = Meta::mp.iMessageLimit; - iMessageBurst = Meta::mp.iMessageBurst; - iPluginMessageLimit = Meta::mp.iPluginMessageLimit; - iPluginMessageBurst = Meta::mp.iPluginMessageBurst; - broadcastListenerVolumeAdjustments = Meta::mp.broadcastListenerVolumeAdjustments; - m_suggestVersion = Meta::mp.m_suggestVersion; - qvSuggestPositional = Meta::mp.qvSuggestPositional; - qvSuggestPushToTalk = Meta::mp.qvSuggestPushToTalk; - iOpusThreshold = Meta::mp.iOpusThreshold; - iChannelNestingLimit = Meta::mp.iChannelNestingLimit; - iChannelCountLimit = Meta::mp.iChannelCountLimit; + qsPassword = Meta::mp->qsPassword; + usPort = static_cast< unsigned short >(Meta::mp->usPort + iServerNum - 1); + iTimeout = Meta::mp->iTimeout; + iMaxBandwidth = Meta::mp->iMaxBandwidth; + iMaxUsers = Meta::mp->iMaxUsers; + iMaxUsersPerChannel = Meta::mp->iMaxUsersPerChannel; + iMaxTextMessageLength = Meta::mp->iMaxTextMessageLength; + iMaxImageMessageLength = Meta::mp->iMaxImageMessageLength; + bAllowHTML = Meta::mp->bAllowHTML; + iDefaultChan = Meta::mp->iDefaultChan; + bRememberChan = Meta::mp->bRememberChan; + iRememberChanDuration = Meta::mp->iRememberChanDuration; + qsWelcomeText = Meta::mp->qsWelcomeText; + qsWelcomeTextFile = Meta::mp->qsWelcomeTextFile; + qlBind = Meta::mp->qlBind; + qsRegName = Meta::mp->qsRegName; + qsRegPassword = Meta::mp->qsRegPassword; + qsRegHost = Meta::mp->qsRegHost; + qsRegLocation = Meta::mp->qsRegLocation; + qurlRegWeb = Meta::mp->qurlRegWeb; + bBonjour = Meta::mp->bBonjour; + bAllowPing = Meta::mp->bAllowPing; + allowRecording = Meta::mp->allowRecording; + bCertRequired = Meta::mp->bCertRequired; + bForceExternalAuth = Meta::mp->bForceExternalAuth; + qrUserName = Meta::mp->qrUserName; + qrChannelName = Meta::mp->qrChannelName; + iMessageLimit = Meta::mp->iMessageLimit; + iMessageBurst = Meta::mp->iMessageBurst; + iPluginMessageLimit = Meta::mp->iPluginMessageLimit; + iPluginMessageBurst = Meta::mp->iPluginMessageBurst; + broadcastListenerVolumeAdjustments = Meta::mp->broadcastListenerVolumeAdjustments; + m_suggestVersion = Meta::mp->m_suggestVersion; + qvSuggestPositional = Meta::mp->qvSuggestPositional; + qvSuggestPushToTalk = Meta::mp->qvSuggestPushToTalk; + iOpusThreshold = Meta::mp->iOpusThreshold; + iChannelNestingLimit = Meta::mp->iChannelNestingLimit; + iChannelCountLimit = Meta::mp->iChannelCountLimit; QString qsHost = getConf("host", QString()).toString(); if (!qsHost.isEmpty()) { @@ -387,7 +387,7 @@ void Server::readParams() { foreach (const QHostAddress &qha, qlBind) log(QString("Binding to address %1").arg(qha.toString())); if (qlBind.isEmpty()) - qlBind = Meta::mp.qlBind; + qlBind = Meta::mp->qlBind; } qsPassword = getConf("password", qsPassword).toString(); @@ -476,11 +476,11 @@ void Server::setLiveConf(const QString &key, const QString &value) { QString v = value.trimmed().isEmpty() ? QString() : value; int i = v.toInt(); if ((key == "password") || (key == "serverpassword")) - qsPassword = !v.isNull() ? v : Meta::mp.qsPassword; + qsPassword = !v.isNull() ? v : Meta::mp->qsPassword; else if (key == "timeout") - iTimeout = i ? i : Meta::mp.iTimeout; + iTimeout = i ? i : Meta::mp->iTimeout; else if (key == "bandwidth") { - int length = i ? i : Meta::mp.iMaxBandwidth; + int length = i ? i : Meta::mp->iMaxBandwidth; if (length != iMaxBandwidth) { iMaxBandwidth = length; MumbleProto::ServerConfig mpsc; @@ -488,7 +488,7 @@ void Server::setLiveConf(const QString &key, const QString &value) { sendAll(mpsc); } } else if (key == "users") { - unsigned int newmax = i ? static_cast< unsigned int >(i) : Meta::mp.iMaxUsers; + unsigned int newmax = i ? static_cast< unsigned int >(i) : Meta::mp->iMaxUsers; if (iMaxUsers == newmax) return; @@ -502,9 +502,9 @@ void Server::setLiveConf(const QString &key, const QString &value) { mpsc.set_max_users(iMaxUsers); sendAll(mpsc); } else if (key == "usersperchannel") - iMaxUsersPerChannel = i ? static_cast< unsigned int >(i) : Meta::mp.iMaxUsersPerChannel; + iMaxUsersPerChannel = i ? static_cast< unsigned int >(i) : Meta::mp->iMaxUsersPerChannel; else if (key == "textmessagelength") { - int length = i ? i : Meta::mp.iMaxTextMessageLength; + int length = i ? i : Meta::mp->iMaxTextMessageLength; if (length != iMaxTextMessageLength) { iMaxTextMessageLength = length; MumbleProto::ServerConfig mpsc; @@ -512,7 +512,7 @@ void Server::setLiveConf(const QString &key, const QString &value) { sendAll(mpsc); } } else if (key == "imagemessagelength") { - int length = i ? i : Meta::mp.iMaxImageMessageLength; + int length = i ? i : Meta::mp->iMaxImageMessageLength; if (length != iMaxImageMessageLength) { iMaxImageMessageLength = length; MumbleProto::ServerConfig mpsc; @@ -520,7 +520,7 @@ void Server::setLiveConf(const QString &key, const QString &value) { sendAll(mpsc); } } else if (key == "allowhtml") { - bool allow = !v.isNull() ? QVariant(v).toBool() : Meta::mp.bAllowHTML; + bool allow = !v.isNull() ? QVariant(v).toBool() : Meta::mp->bAllowHTML; if (allow != bAllowHTML) { bAllowHTML = allow; MumbleProto::ServerConfig mpsc; @@ -528,21 +528,21 @@ void Server::setLiveConf(const QString &key, const QString &value) { sendAll(mpsc); } } else if (key == "defaultchannel") - iDefaultChan = i ? static_cast< unsigned int >(i) : Meta::mp.iDefaultChan; + iDefaultChan = i ? static_cast< unsigned int >(i) : Meta::mp->iDefaultChan; else if (key == "rememberchannel") - bRememberChan = !v.isNull() ? QVariant(v).toBool() : Meta::mp.bRememberChan; + bRememberChan = !v.isNull() ? QVariant(v).toBool() : Meta::mp->bRememberChan; else if (key == "rememberchannelduration") { - iRememberChanDuration = !v.isNull() ? v.toInt() : Meta::mp.iRememberChanDuration; + iRememberChanDuration = !v.isNull() ? v.toInt() : Meta::mp->iRememberChanDuration; if (iRememberChanDuration < 0) { iRememberChanDuration = 0; } } else if (key == "welcometext") { - QString text = !v.isNull() ? v : Meta::mp.qsWelcomeText; + QString text = !v.isNull() ? v : Meta::mp->qsWelcomeText; if (text != qsWelcomeText) { qsWelcomeText = text; } } else if (key == "registername") { - QString text = !v.isNull() ? v : Meta::mp.qsRegName; + QString text = !v.isNull() ? v : Meta::mp->qsRegName; if (text != qsRegName) { qsRegName = text; if (!qsRegName.isEmpty()) { @@ -553,19 +553,19 @@ void Server::setLiveConf(const QString &key, const QString &value) { } } } else if (key == "registerpassword") - qsRegPassword = !v.isNull() ? v : Meta::mp.qsRegPassword; + qsRegPassword = !v.isNull() ? v : Meta::mp->qsRegPassword; else if (key == "registerhostname") - qsRegHost = !v.isNull() ? v : Meta::mp.qsRegHost; + qsRegHost = !v.isNull() ? v : Meta::mp->qsRegHost; else if (key == "registerlocation") - qsRegLocation = !v.isNull() ? v : Meta::mp.qsRegLocation; + qsRegLocation = !v.isNull() ? v : Meta::mp->qsRegLocation; else if (key == "registerurl") - qurlRegWeb = !v.isNull() ? v : Meta::mp.qurlRegWeb; + qurlRegWeb = !v.isNull() ? v : Meta::mp->qurlRegWeb; else if (key == "certrequired") - bCertRequired = !v.isNull() ? QVariant(v).toBool() : Meta::mp.bCertRequired; + bCertRequired = !v.isNull() ? QVariant(v).toBool() : Meta::mp->bCertRequired; else if (key == "forceExternalAuth") - bForceExternalAuth = !v.isNull() ? QVariant(v).toBool() : Meta::mp.bForceExternalAuth; + bForceExternalAuth = !v.isNull() ? QVariant(v).toBool() : Meta::mp->bForceExternalAuth; else if (key == "bonjour") { - bBonjour = !v.isNull() ? QVariant(v).toBool() : Meta::mp.bBonjour; + bBonjour = !v.isNull() ? QVariant(v).toBool() : Meta::mp->bBonjour; #ifdef USE_ZEROCONF if (bBonjour && !zeroconf) { initZeroconf(); @@ -574,38 +574,38 @@ void Server::setLiveConf(const QString &key, const QString &value) { } #endif } else if (key == "allowping") - bAllowPing = !v.isNull() ? QVariant(v).toBool() : Meta::mp.bAllowPing; + bAllowPing = !v.isNull() ? QVariant(v).toBool() : Meta::mp->bAllowPing; else if (key == "allowrecording") - allowRecording = !v.isNull() ? QVariant(v).toBool() : Meta::mp.allowRecording; + allowRecording = !v.isNull() ? QVariant(v).toBool() : Meta::mp->allowRecording; else if (key == "username") - qrUserName = !v.isNull() ? QRegularExpression(v) : Meta::mp.qrUserName; + qrUserName = !v.isNull() ? QRegularExpression(v) : Meta::mp->qrUserName; else if (key == "channelname") - qrChannelName = !v.isNull() ? QRegularExpression(v) : Meta::mp.qrChannelName; + qrChannelName = !v.isNull() ? QRegularExpression(v) : Meta::mp->qrChannelName; else if (key == "suggestversion") - m_suggestVersion = !v.isNull() ? Version::fromConfig(v) : Meta::mp.m_suggestVersion; + m_suggestVersion = !v.isNull() ? Version::fromConfig(v) : Meta::mp->m_suggestVersion; else if (key == "suggestpositional") - qvSuggestPositional = !v.isNull() ? (v.isEmpty() ? QVariant() : v) : Meta::mp.qvSuggestPositional; + qvSuggestPositional = !v.isNull() ? (v.isEmpty() ? QVariant() : v) : Meta::mp->qvSuggestPositional; else if (key == "suggestpushtotalk") - qvSuggestPushToTalk = !v.isNull() ? (v.isEmpty() ? QVariant() : v) : Meta::mp.qvSuggestPushToTalk; + qvSuggestPushToTalk = !v.isNull() ? (v.isEmpty() ? QVariant() : v) : Meta::mp->qvSuggestPushToTalk; else if (key == "opusthreshold") - iOpusThreshold = (i >= 0 && !v.isNull()) ? qBound(0, i, 100) : Meta::mp.iOpusThreshold; + iOpusThreshold = (i >= 0 && !v.isNull()) ? qBound(0, i, 100) : Meta::mp->iOpusThreshold; else if (key == "channelnestinglimit") - iChannelNestingLimit = (i >= 0 && !v.isNull()) ? i : Meta::mp.iChannelNestingLimit; + iChannelNestingLimit = (i >= 0 && !v.isNull()) ? i : Meta::mp->iChannelNestingLimit; else if (key == "channelcountlimit") - iChannelCountLimit = (i >= 0 && !v.isNull()) ? i : Meta::mp.iChannelCountLimit; + iChannelCountLimit = (i >= 0 && !v.isNull()) ? i : Meta::mp->iChannelCountLimit; else if (key == "messagelimit") { - iMessageLimit = (!v.isNull()) ? v.toUInt() : Meta::mp.iMessageLimit; + iMessageLimit = (!v.isNull()) ? v.toUInt() : Meta::mp->iMessageLimit; if (iMessageLimit < 1) { iMessageLimit = 1; } } else if (key == "messageburst") { - iMessageBurst = (!v.isNull()) ? v.toUInt() : Meta::mp.iMessageBurst; + iMessageBurst = (!v.isNull()) ? v.toUInt() : Meta::mp->iMessageBurst; if (iMessageBurst < 1) { iMessageBurst = 1; } } else if (key == "broadcastlistenervolumeadjustments") { broadcastListenerVolumeAdjustments = - (!v.isNull() ? QVariant(v).toBool() : Meta::mp.broadcastListenerVolumeAdjustments); + (!v.isNull() ? QVariant(v).toBool() : Meta::mp->broadcastListenerVolumeAdjustments); } } @@ -1414,13 +1414,13 @@ void Server::newClient() { // Add CA certificates specified via // murmur.ini's sslCA option. - config.addCaCertificates(Meta::mp.qlCA); + config.addCaCertificates(Meta::mp->qlCA); // Add intermediate CAs found in the PEM // bundle used for this server's certificate. config.addCaCertificates(qlIntermediates); - config.setCiphers(Meta::mp.qlCiphers); + config.setCiphers(Meta::mp->qlCiphers); #if defined(USE_QSSLDIFFIEHELLMANPARAMETERS) config.setDiffieHellmanParameters(qsdhpDHParams); #endif @@ -1463,7 +1463,7 @@ void Server::encrypted() { MumbleProto::Version mpv; MumbleProto::setVersion(mpv, Version::get()); - if (Meta::mp.bSendVersion) { + if (Meta::mp->bSendVersion) { mpv.set_release(u8(Version::getRelease())); mpv.set_os(u8(meta->qsOS)); mpv.set_os_version(u8(meta->qsOSVersion)); @@ -2109,13 +2109,13 @@ void Server::clearWhisperTargetCache() { QString Server::addressToString(const QHostAddress &adr, unsigned short port) { HostAddress ha(adr); - if ((Meta::mp.iObfuscate != 0)) { + if ((Meta::mp->iObfuscate != 0)) { QCryptographicHash h(QCryptographicHash::Sha1); - QByteArrayView byteView(reinterpret_cast< const char * >(&Meta::mp.iObfuscate), sizeof(Meta::mp.iObfuscate)); + QByteArrayView byteView(reinterpret_cast< const char * >(&Meta::mp->iObfuscate), sizeof(Meta::mp->iObfuscate)); #if QT_VERSION >= QT_VERSION_CHECK(6, 3, 0) h.addData(byteView); #else - h.addData(reinterpret_cast< const char * >(&Meta::mp.iObfuscate), sizeof(Meta::mp.iObfuscate)); + h.addData(reinterpret_cast< const char * >(&Meta::mp->iObfuscate), sizeof(Meta::mp->iObfuscate)); #endif if (adr.protocol() == QAbstractSocket::IPv4Protocol) { quint32 num = adr.toIPv4Address(); diff --git a/src/murmur/ServerDB.cpp b/src/murmur/ServerDB.cpp index 4536641ea..ae0831035 100644 --- a/src/murmur/ServerDB.cpp +++ b/src/murmur/ServerDB.cpp @@ -64,30 +64,30 @@ Timer ServerDB::tLogClean; QString ServerDB::qsUpgradeSuffix; void ServerDB::loadOrSetupMetaPBKDF2IterationCount(QSqlQuery &query) { - if (!Meta::mp.legacyPasswordHash) { - if (Meta::mp.kdfIterations <= 0) { + if (!Meta::mp->legacyPasswordHash) { + if (Meta::mp->kdfIterations <= 0) { // Configuration doesn't specify an override, load from db SQLDO("SELECT `value` FROM `%1meta` WHERE `keystring` = 'pbkdf2_iterations'"); if (query.next()) { - Meta::mp.kdfIterations = query.value(0).toInt(); + Meta::mp->kdfIterations = query.value(0).toInt(); } - if (Meta::mp.kdfIterations <= 0) { + if (Meta::mp->kdfIterations <= 0) { // Didn't get a valid iteration count from DB, overwrite - Meta::mp.kdfIterations = PBKDF2::benchmark(); + Meta::mp->kdfIterations = PBKDF2::benchmark(); - qWarning() << "Performed initial PBKDF2 benchmark. Will use" << Meta::mp.kdfIterations + qWarning() << "Performed initial PBKDF2 benchmark. Will use" << Meta::mp->kdfIterations << "iterations as default"; SQLPREP("INSERT INTO `%1meta` (`keystring`, `value`) VALUES('pbkdf2_iterations',?)"); - query.addBindValue(Meta::mp.kdfIterations); + query.addBindValue(Meta::mp->kdfIterations); SQLEXEC(); } } - if (Meta::mp.kdfIterations < PBKDF2::BENCHMARK_MINIMUM_ITERATION_COUNT) { - qWarning() << "Configured default PBKDF2 iteration count of" << Meta::mp.kdfIterations + if (Meta::mp->kdfIterations < PBKDF2::BENCHMARK_MINIMUM_ITERATION_COUNT) { + qWarning() << "Configured default PBKDF2 iteration count of" << Meta::mp->kdfIterations << "is below minimum recommended value of" << PBKDF2::BENCHMARK_MINIMUM_ITERATION_COUNT << "and could be insecure."; } @@ -95,32 +95,32 @@ void ServerDB::loadOrSetupMetaPBKDF2IterationCount(QSqlQuery &query) { } ServerDB::ServerDB() { - if (Meta::mp.qsDBDriver != QLatin1String("QMYSQL") && Meta::mp.qsDBDriver != QLatin1String("QSQLITE") - && Meta::mp.qsDBDriver != QLatin1String("QPSQL")) { + if (Meta::mp->qsDBDriver != QLatin1String("QMYSQL") && Meta::mp->qsDBDriver != QLatin1String("QSQLITE") + && Meta::mp->qsDBDriver != QLatin1String("QPSQL")) { qFatal("ServerDB: invalid DB driver specified: '%s'. Murmur only supports QSQLITE, QMYSQL, and QPSQL.", - qPrintable(Meta::mp.qsDBDriver)); + qPrintable(Meta::mp->qsDBDriver)); } - if (!QSqlDatabase::isDriverAvailable(Meta::mp.qsDBDriver)) { - qFatal("ServerDB: Database driver %s not available", qPrintable(Meta::mp.qsDBDriver)); + if (!QSqlDatabase::isDriverAvailable(Meta::mp->qsDBDriver)) { + qFatal("ServerDB: Database driver %s not available", qPrintable(Meta::mp->qsDBDriver)); } if (db) { // Don't hide away our previous instance. Fail hard. qFatal("ServerDB has already been instantiated!"); } - db = new QSqlDatabase(QSqlDatabase::addDatabase(Meta::mp.qsDBDriver)); + db = new QSqlDatabase(QSqlDatabase::addDatabase(Meta::mp->qsDBDriver)); qsUpgradeSuffix = QString::fromLatin1("_old_%1").arg(QDateTime::currentDateTime().toSecsSinceEpoch()); bool found = false; - if (Meta::mp.qsDBDriver == "QSQLITE") { - if (!Meta::mp.qsDatabase.isEmpty()) { - db->setDatabaseName(Meta::mp.qsDatabase); + if (Meta::mp->qsDBDriver == "QSQLITE") { + if (!Meta::mp->qsDatabase.isEmpty()) { + db->setDatabaseName(Meta::mp->qsDatabase); found = db->open(); } else { QStringList datapaths; - datapaths << Meta::mp.qdBasePath.absolutePath(); + datapaths << Meta::mp->qdBasePath.absolutePath(); datapaths << QDir::currentPath(); datapaths << QCoreApplication::instance()->applicationDirPath(); datapaths << QDir::homePath(); @@ -154,12 +154,12 @@ ServerDB::ServerDB() { qFatal("ServerDB: Database is not writable"); } } else { - db->setDatabaseName(Meta::mp.qsDatabase); - db->setHostName(Meta::mp.qsDBHostName); - db->setPort(Meta::mp.iDBPort); - db->setUserName(Meta::mp.qsDBUserName); - db->setPassword(Meta::mp.qsDBPassword); - db->setConnectOptions(Meta::mp.qsDBOpts); + db->setDatabaseName(Meta::mp->qsDatabase); + db->setHostName(Meta::mp->qsDBHostName); + db->setPort(Meta::mp->iDBPort); + db->setUserName(Meta::mp->qsDBUserName); + db->setPassword(Meta::mp->qsDBPassword); + db->setConnectOptions(Meta::mp->qsDBOpts); found = db->open(); } @@ -169,10 +169,10 @@ ServerDB::ServerDB() { } // Use SQLite in WAL mode if possible. - if (Meta::mp.qsDBDriver == "QSQLITE") { - if (Meta::mp.iSQLiteWAL == 0) { + if (Meta::mp->qsDBDriver == "QSQLITE") { + if (Meta::mp->iSQLiteWAL == 0) { qWarning("ServerDB: Using SQLite's default rollback journal."); - } else if (Meta::mp.iSQLiteWAL > 0 && Meta::mp.iSQLiteWAL <= 2) { + } else if (Meta::mp->iSQLiteWAL > 0 && Meta::mp->iSQLiteWAL <= 2) { QSqlQuery query; bool hasversion = false; @@ -196,10 +196,10 @@ ServerDB::ServerDB() { if (okversion) { SQLDO("PRAGMA journal_mode=WAL;"); - if (Meta::mp.iSQLiteWAL == 1) { + if (Meta::mp->iSQLiteWAL == 1) { SQLDO("PRAGMA synchronous=NORMAL;"); qWarning("ServerDB: Configured SQLite for journal_mode=WAL, synchronous=NORMAL"); - } else if (Meta::mp.iSQLiteWAL == 2) { + } else if (Meta::mp->iSQLiteWAL == 2) { SQLDO("PRAGMA synchronous=FULL;"); qWarning("ServerDB: Configured SQLite for journal_mode=WAL, synchronous=FULL"); } @@ -213,7 +213,7 @@ ServerDB::ServerDB() { } else { qFatal("ServerDB: Invalid value '%i' for sqlite_wal. Please use 0 (no wal), 1 (wal), 2 (wal with " "synchronous=full)", - Meta::mp.iSQLiteWAL); + Meta::mp->iSQLiteWAL); } } @@ -222,10 +222,10 @@ ServerDB::ServerDB() { QSqlQuery &query = *th.qsqQuery; // Ensure that a proper encoding is used for the DB - if (Meta::mp.qsDBDriver == "QMYSQL") { + if (Meta::mp->qsDBDriver == "QMYSQL") { query.exec(QString::fromLatin1( "SELECT default_character_set_name FROM information_schema.SCHEMATA WHERE schema_name = '%1'") - .arg(Meta::mp.qsDatabase)); + .arg(Meta::mp->qsDatabase)); if (query.next()) { QString encoding = query.value(0).toString(); @@ -238,7 +238,7 @@ ServerDB::ServerDB() { if (!query.exec( QString::fromLatin1("ALTER DATABASE `%1` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci") - .arg(Meta::mp.qsDatabase))) { + .arg(Meta::mp->qsDatabase))) { qFatal("ServerDB: Failed to set default encoding & collation to UTF-8: %s", qPrintable(query.lastError().text())); } @@ -246,7 +246,7 @@ ServerDB::ServerDB() { } else { qFatal("Failed to get character encoding: %s", qPrintable(query.lastError().text())); } - } else if (Meta::mp.qsDBDriver == "QSQLITE") { + } else if (Meta::mp->qsDBDriver == "QSQLITE") { // Verify that the SQLite database has been initialized with UTF-8 or UTF-16 SQLQUERY("PRAGMA ENCODING;"); @@ -286,9 +286,9 @@ ServerDB::ServerDB() { // Make sure a table called "meta" is present // We use the meta table to keep track of various meta information such as the // database structure version this database conforms to. - if (Meta::mp.qsDBDriver == "QSQLITE") + if (Meta::mp->qsDBDriver == "QSQLITE") SQLDO("CREATE TABLE IF NOT EXISTS `%1meta` (`keystring` TEXT PRIMARY KEY, `value` TEXT)"); - else if (Meta::mp.qsDBDriver == "QPSQL") + else if (Meta::mp->qsDBDriver == "QPSQL") SQLQUERY("CREATE TABLE IF NOT EXISTS `%1meta` (`keystring` varchar(255) PRIMARY KEY, `value` varchar(255))"); else // MySQL @@ -341,7 +341,7 @@ ServerDB::ServerDB() { // Now we generate new tables that conform to the state-of-the-art structure qWarning("Generating new tables..."); - if (Meta::mp.qsDBDriver == "QSQLITE") { + if (Meta::mp->qsDBDriver == "QSQLITE") { if (version > 0) { SQLDO("DROP TRIGGER IF EXISTS `%1log_timestamp`"); SQLDO("DROP TRIGGER IF EXISTS `%1log_server_del`"); @@ -475,7 +475,7 @@ ServerDB::ServerDB() { SQLDO("CREATE TRIGGER `%1channel_listeners_del_user` AFTER DELETE ON `%1users` FOR EACH ROW BEGIN " "DELETE FROM `%1channel_listeners` WHERE `server_id` = old.`server_id` AND `user_id` = " "old.`user_id`; END;"); - } else if (Meta::mp.qsDBDriver == "QPSQL") { + } else if (Meta::mp->qsDBDriver == "QPSQL") { if (version > 0) { typedef QPair< QString, QString > qsp; QList< qsp > qlForeignKeys; @@ -483,13 +483,13 @@ ServerDB::ServerDB() { SQLPREP("SELECT TABLE_NAME, CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE " "TABLE_SCHEMA=? AND CONSTRAINT_TYPE='FOREIGN KEY'"); - query.addBindValue(Meta::mp.qsDatabase); + query.addBindValue(Meta::mp->qsDatabase); SQLEXEC(); while (query.next()) qlForeignKeys << qsp(query.value(0).toString(), query.value(1).toString()); foreach (const qsp &key, qlForeignKeys) { - if (key.first.startsWith(Meta::mp.qsDBPrefix)) + if (key.first.startsWith(Meta::mp->qsDBPrefix)) ServerDB::exec(query, QString::fromLatin1("ALTER TABLE `%1` DROP CONSTRAINT FOREIGN KEY `%2`") .arg(key.first) @@ -499,13 +499,13 @@ ServerDB::ServerDB() { SQLPREP("SELECT TABLE_NAME, CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE " "TABLE_SCHEMA=? AND CONSTRAINT_TYPE='PRIMARY KEY'"); - query.addBindValue(Meta::mp.qsDatabase); + query.addBindValue(Meta::mp->qsDatabase); SQLEXEC(); while (query.next()) qlIndexes << qsp(query.value(0).toString(), query.value(1).toString()); foreach (const qsp &key, qlIndexes) { - if (key.first.startsWith(Meta::mp.qsDBPrefix)) + if (key.first.startsWith(Meta::mp->qsDBPrefix)) ServerDB::exec(query, QString::fromLatin1("ALTER TABLE `%1` DROP CONSTRAINT PRIMARY KEY `%2`") .arg(key.first) @@ -627,13 +627,13 @@ ServerDB::ServerDB() { SQLPREP("SELECT TABLE_NAME, CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE " "TABLE_SCHEMA=? AND CONSTRAINT_TYPE='FOREIGN KEY'"); - query.addBindValue(Meta::mp.qsDatabase); + query.addBindValue(Meta::mp->qsDatabase); SQLEXEC(); while (query.next()) qlForeignKeys << qsp(query.value(0).toString(), query.value(1).toString()); foreach (const qsp &key, qlForeignKeys) { - if (key.first.startsWith(Meta::mp.qsDBPrefix)) + if (key.first.startsWith(Meta::mp->qsDBPrefix)) ServerDB::exec(query, QString::fromLatin1("ALTER TABLE `%1` DROP FOREIGN KEY `%2`") .arg(key.first) @@ -741,7 +741,7 @@ ServerDB::ServerDB() { } else { qWarning("Importing old data..."); - if (Meta::mp.qsDBDriver == "QMYSQL") + if (Meta::mp->qsDBDriver == "QMYSQL") SQLDO("SET FOREIGN_KEY_CHECKS = 0;"); SQLDO("INSERT INTO `%1servers` (`server_id`) SELECT `server_id` FROM `%1servers%2`"); SQLDO("INSERT INTO `%1slog` (`server_id`, `msg`, `msgtime`) SELECT `server_id`, `msg`, `msgtime` FROM " @@ -845,7 +845,7 @@ ServerDB::ServerDB() { if (version >= 9) { SQLDO("INSERT INTO `%1channel_listeners` SELECT * FROM `%1channel_listeners%2`"); } - if (Meta::mp.qsDBDriver == "QMYSQL") + if (Meta::mp->qsDBDriver == "QMYSQL") SQLDO("SET FOREIGN_KEY_CHECKS = 1;"); qWarning("Removing old tables..."); @@ -885,14 +885,14 @@ bool ServerDB::prepare(QSqlQuery &query, const QString &str, bool fatal, bool wa QString q; if (str.contains(QLatin1String("%1"))) { if (str.contains(QLatin1String("%2"))) - q = str.arg(Meta::mp.qsDBPrefix, qsUpgradeSuffix); + q = str.arg(Meta::mp->qsDBPrefix, qsUpgradeSuffix); else - q = str.arg(Meta::mp.qsDBPrefix); + q = str.arg(Meta::mp->qsDBPrefix); } else { q = str; } - if (Meta::mp.qsDBDriver == "QPSQL") { + if (Meta::mp->qsDBDriver == "QPSQL") { q.replace("`", "\""); } @@ -928,14 +928,14 @@ bool ServerDB::query(QSqlQuery &query, const QString &str, bool fatal, bool warn QString q; if (str.contains(QLatin1String("%1"))) { if (str.contains(QLatin1String("%2"))) - q = str.arg(Meta::mp.qsDBPrefix, qsUpgradeSuffix); + q = str.arg(Meta::mp->qsDBPrefix, qsUpgradeSuffix); else - q = str.arg(Meta::mp.qsDBPrefix); + q = str.arg(Meta::mp->qsDBPrefix); } else { q = str; } - if (Meta::mp.qsDBDriver == "QPSQL") { + if (Meta::mp->qsDBDriver == "QPSQL") { q.replace("`", "\""); } @@ -1126,7 +1126,7 @@ int Server::registerUser(const QMap< int, QString > &info) { id = res; } - if (Meta::mp.qsDBDriver == "QPSQL") { + if (Meta::mp->qsDBDriver == "QPSQL") { SQLPREP("INSERT INTO `%1users` (`server_id`, `user_id`, `name`) VALUES (:server_id,:user_id,:name) ON " "CONFLICT (`server_id`, `name`) DO UPDATE SET `user_id` = :u_user_id WHERE `%1users`.`server_id` = " ":u_server_id AND `%1users`.`name` = :u_name"); @@ -1317,7 +1317,7 @@ int Server::authenticate(QString &name, const QString &password, int sessionId, if (lchan < 0) lchan = 0; - if (Meta::mp.qsDBDriver == "QPSQL") { + if (Meta::mp->qsDBDriver == "QPSQL") { SQLPREP("INSERT INTO `%1users` (`server_id`, `user_id`, `name`, `lastchannel`) VALUES " "(:server_id,:user_id,:name,:lastchannel) ON CONFLICT (`server_id`, `user_id`) DO UPDATE SET " "`name` = :u_name, `lastchannel` = :u_lastchannel WHERE `%1users`.`server_id` = :u_server_id " @@ -1372,11 +1372,11 @@ int Server::authenticate(QString &name, const QString &password, int sessionId, name = query.value(1).toString(); res = query.value(0).toInt(); - if (!Meta::mp.legacyPasswordHash) { + if (!Meta::mp->legacyPasswordHash) { // Unless disabled upgrade the user password hash QMap< int, QString > info; info.insert(ServerDB::User_Password, password); - info.insert(ServerDB::User_KDFIterations, QString::number(Meta::mp.kdfIterations)); + info.insert(ServerDB::User_KDFIterations, QString::number(Meta::mp->kdfIterations)); if (!setInfo(userId, info)) { qWarning("ServerDB: Failed to upgrade user account to PBKDF2 hash, rejecting login."); @@ -1389,7 +1389,7 @@ int Server::authenticate(QString &name, const QString &password, int sessionId, name = query.value(1).toString(); res = query.value(0).toInt(); - if (Meta::mp.legacyPasswordHash) { + if (Meta::mp->legacyPasswordHash) { // Downgrade the password to the legacy hash QMap< int, QString > info; info.insert(ServerDB::User_Password, password); @@ -1398,15 +1398,15 @@ int Server::authenticate(QString &name, const QString &password, int sessionId, qWarning("ServerDB: Failed to downgrade user account to legacy hash, rejecting login."); return -1; } - } else if (storedKdfIterations != Meta::mp.kdfIterations) { + } else if (storedKdfIterations != Meta::mp->kdfIterations) { // User kdfiterations not equal to the global one. Update it. QMap< int, QString > info; info.insert(ServerDB::User_Password, password); - info.insert(ServerDB::User_KDFIterations, QString::number(Meta::mp.kdfIterations)); + info.insert(ServerDB::User_KDFIterations, QString::number(Meta::mp->kdfIterations)); if (!setInfo(userId, info)) { qWarning() << "ServerDB: Failed to update user PBKDF2 to new iteration count" - << Meta::mp.kdfIterations << ", rejecting login."; + << Meta::mp->kdfIterations << ", rejecting login."; return -1; } } @@ -1458,7 +1458,7 @@ int Server::authenticate(QString &name, const QString &password, int sessionId, } } if (!certhash.isEmpty() && (res > 0)) { - if (Meta::mp.qsDBDriver == "QPSQL") { + if (Meta::mp->qsDBDriver == "QPSQL") { SQLPREP("INSERT INTO `%1user_info` (`server_id`, `user_id`, `key`, `value`) VALUES (:server_id, :user_id, " ":key, :value) ON CONFLICT (`server_id`, `user_id`, `key`) DO UPDATE SET `value` = :u_value WHERE " "`%1user_info`.`server_id` = :u_server_id AND `%1user_info`.`user_id` = :u_user_id AND " @@ -1482,7 +1482,7 @@ int Server::authenticate(QString &name, const QString &password, int sessionId, } if (!emails.isEmpty()) { - if (Meta::mp.qsDBDriver == "QPSQL") { + if (Meta::mp->qsDBDriver == "QPSQL") { query.bindValue(":server_id", iServerNum); query.bindValue(":user_id", res); query.bindValue(":key", ServerDB::User_Email); @@ -1540,10 +1540,10 @@ bool Server::setInfo(int id, const QMap< int, QString > &setinfo) { QString passwordHash, salt; int kdfIterations = -1; - if (Meta::mp.legacyPasswordHash) { + if (Meta::mp->legacyPasswordHash) { passwordHash = ServerDB::getLegacySHA1Hash(password); } else { - kdfIterations = Meta::mp.kdfIterations; + kdfIterations = Meta::mp->kdfIterations; if (info.contains(ServerDB::User_KDFIterations)) { const int targetIterations = info.value(ServerDB::User_KDFIterations).toInt(); if (targetIterations > 0) { @@ -1583,7 +1583,7 @@ bool Server::setInfo(int id, const QMap< int, QString > &setinfo) { keys << i.key(); values << i.value(); } - if (Meta::mp.qsDBDriver == "QPSQL") { + if (Meta::mp->qsDBDriver == "QPSQL") { SQLPREP("INSERT INTO `%1user_info` (`server_id`, `user_id`, `key`, `value`) VALUES (:server_id, :user_id, " ":key, :value) ON CONFLICT (`server_id`, `user_id`, `key`) DO UPDATE SET `value` = :u_value WHERE " "`%1user_info`.`server_id` = :u_server_id AND `%1user_info`.`user_id` = :u_user_id AND " @@ -1671,14 +1671,14 @@ void ServerDB::writeSUPW(int srvnum, const QString &pwHash, const QString &saltH void ServerDB::setSUPW(int srvnum, const QString &pw) { QString pwHash, saltHash; - if (!Meta::mp.legacyPasswordHash) { + if (!Meta::mp->legacyPasswordHash) { saltHash = PBKDF2::getSalt(); - pwHash = PBKDF2::getHash(saltHash, pw, Meta::mp.kdfIterations); + pwHash = PBKDF2::getHash(saltHash, pw, Meta::mp->kdfIterations); } else { pwHash = getLegacySHA1Hash(pw); } - writeSUPW(srvnum, pwHash, saltHash, Meta::mp.kdfIterations); + writeSUPW(srvnum, pwHash, saltHash, Meta::mp->kdfIterations); } void ServerDB::disableSU(int srvnum) { @@ -1900,7 +1900,7 @@ void Server::updateChannel(const Channel *c) { SQLEXEC(); // Update channel description information - if (Meta::mp.qsDBDriver == "QPSQL") { + if (Meta::mp->qsDBDriver == "QPSQL") { SQLPREP("INSERT INTO `%1channel_info` (`server_id`, `channel_id`, `key`, `value`) VALUES (:server_id, " ":channel_id, :key, :value) ON CONFLICT (`server_id`, `channel_id`, `key`) DO UPDATE SET `value` = " ":u_value WHERE `%1channel_info`.`server_id` = :u_server_id AND `%1channel_info`.`channel_id` = " @@ -1923,7 +1923,7 @@ void Server::updateChannel(const Channel *c) { SQLEXEC(); } // Update channel position information - if (Meta::mp.qsDBDriver == "QPSQL") { + if (Meta::mp->qsDBDriver == "QPSQL") { query.bindValue(":server_id", iServerNum); query.bindValue(":channel_id", c->iId); query.bindValue(":key", ServerDB::Channel_Position); @@ -1941,7 +1941,7 @@ void Server::updateChannel(const Channel *c) { SQLEXEC(); } // Update channel maximum channels - if (Meta::mp.qsDBDriver == "QPSQL") { + if (Meta::mp->qsDBDriver == "QPSQL") { query.bindValue(":server_id", iServerNum); query.bindValue(":channel_id", c->iId); query.bindValue(":key", ServerDB::Channel_Max_Users); @@ -1973,7 +1973,7 @@ void Server::updateChannel(const Channel *c) { int id = 0; int pid; - if (Meta::mp.qsDBDriver == "QPSQL") { + if (Meta::mp->qsDBDriver == "QPSQL") { SQLPREP("INSERT INTO `%1groups` (`server_id`, `channel_id`, `name`, `inherit`, `inheritable`) VALUES " "(?,?,?,?,?) RETURNING group_id"); query.addBindValue(iServerNum); @@ -2079,7 +2079,7 @@ void Server::readChannelPrivs(Channel *c) { QSqlQuery mem; mem.prepare(QString::fromLatin1("SELECT user_id, addit FROM %1group_members WHERE group_id = ?") - .arg(Meta::mp.qsDBPrefix)); + .arg(Meta::mp->qsDBPrefix)); mem.addBindValue(gid); mem.exec(); while (mem.next()) { @@ -2179,7 +2179,7 @@ void Server::setLastChannel(const User *p) { TransactionHolder th; QSqlQuery &query = *th.qsqQuery; - if (Meta::mp.qsDBDriver == "QSQLITE") { + if (Meta::mp->qsDBDriver == "QSQLITE") { SQLPREP("UPDATE `%1users` SET `lastchannel`=? WHERE `server_id` = ? AND `user_id` = ?"); } else { SQLPREP("UPDATE `%1users` SET `lastchannel`=?, `last_active` = now() WHERE `server_id` = ? AND `user_id` = ?"); @@ -2194,7 +2194,7 @@ int Server::readLastChannel(int id) { if (id < 0) return -1; - if (!Meta::mp.bRememberChan) + if (!Meta::mp->bRememberChan) return -1; TransactionHolder th; @@ -2213,7 +2213,7 @@ int Server::readLastChannel(int id) { return -1; } - int duration = Meta::mp.iRememberChanDuration; + int duration = Meta::mp->iRememberChanDuration; if (duration <= 0) { return static_cast< int >(cid); @@ -2266,7 +2266,7 @@ void Server::setLastDisconnect(const User *p) { TransactionHolder th; QSqlQuery &query = *th.qsqQuery; - if (Meta::mp.qsDBDriver == "QSQLITE") { + if (Meta::mp->qsDBDriver == "QSQLITE") { SQLPREP("UPDATE `%1users` SET `last_disconnect` = datetime('now') WHERE `server_id` = ? AND `user_id` = ?"); } else { // MySQL or PostgreSQL @@ -2401,19 +2401,19 @@ void Server::dblog(const QString &str) const { QSqlQuery &query = *th.qsqQuery; // Is logging disabled? - if (Meta::mp.iLogDays < 0) + if (Meta::mp->iLogDays < 0) return; // Once per hour - if (Meta::mp.iLogDays > 0) { + if (Meta::mp->iLogDays > 0) { if (ServerDB::tLogClean.isElapsed(3600ULL * 1000000ULL)) { QString qstr; - if (Meta::mp.qsDBDriver == "QSQLITE") { - qstr = QString::fromLatin1("msgtime < datetime('now','-%1 days')").arg(Meta::mp.iLogDays); - } else if (Meta::mp.qsDBDriver == "QPSQL") { - qstr = QString::fromLatin1("msgtime < now() - INTERVAL '%1 day'").arg(Meta::mp.iLogDays); + if (Meta::mp->qsDBDriver == "QSQLITE") { + qstr = QString::fromLatin1("msgtime < datetime('now','-%1 days')").arg(Meta::mp->iLogDays); + } else if (Meta::mp->qsDBDriver == "QPSQL") { + qstr = QString::fromLatin1("msgtime < now() - INTERVAL '%1 day'").arg(Meta::mp->iLogDays); } else { - qstr = QString::fromLatin1("msgtime < now() - INTERVAL %1 day").arg(Meta::mp.iLogDays); + qstr = QString::fromLatin1("msgtime < now() - INTERVAL %1 day").arg(Meta::mp->iLogDays); } ServerDB::prepare(query, QString::fromLatin1("DELETE FROM %1slog WHERE ") + qstr); SQLEXEC(); @@ -2560,7 +2560,7 @@ QList< ServerDB::LogRecord > ServerDB::getLog(int server_id, unsigned int offs_m TransactionHolder th; QSqlQuery &query = *th.qsqQuery; - if (Meta::mp.qsDBDriver == "QPSQL") { + if (Meta::mp->qsDBDriver == "QPSQL") { SQLPREP("SELECT `msgtime`, `msg` FROM `%1slog` WHERE `server_id` = ? ORDER BY `msgtime` DESC LIMIT ? OFFSET ?"); query.addBindValue(server_id); query.addBindValue(offs_max); @@ -2609,7 +2609,7 @@ void ServerDB::setConf(int server_id, const QString &k, const QVariant &value) { query.addBindValue(server_id); query.addBindValue(key); } else { - if (Meta::mp.qsDBDriver == "QPSQL") { + if (Meta::mp->qsDBDriver == "QPSQL") { SQLPREP("INSERT INTO `%1config` (`server_id`, `key`, `value`) VALUES (:server_id, :key, :value) ON " "CONFLICT (`server_id`, `key`) DO UPDATE SET `value` = :u_value WHERE `%1config`.`server_id` = " ":u_server_id AND `%1config`.`key` = :u_key"); diff --git a/src/murmur/UnixMurmur.cpp b/src/murmur/UnixMurmur.cpp index 3c9330542..95927a59b 100644 --- a/src/murmur/UnixMurmur.cpp +++ b/src/murmur/UnixMurmur.cpp @@ -209,9 +209,9 @@ void UnixMurmur::handleSigHup() { qWarning("Caught SIGHUP, but logfile not in use -- interpreting as hint to quit"); QCoreApplication::instance()->quit(); } else { - qWarning("Caught SIGHUP, will reopen %s", qPrintable(Meta::mp.qsLogfile)); + qWarning("Caught SIGHUP, will reopen %s", qPrintable(Meta::mp->qsLogfile)); - QFile *newlog = new QFile(Meta::mp.qsLogfile); + QFile *newlog = new QFile(Meta::mp->qsLogfile); bool result = newlog->open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text); if (!result) { delete newlog; @@ -263,38 +263,38 @@ void UnixMurmur::handleSigUsr1() { } void UnixMurmur::setuid() { - if (Meta::mp.uiUid != 0) { + if (Meta::mp->uiUid != 0) { #ifdef Q_OS_DARWIN qCritical("WARNING: You are launching murmurd as root on Mac OS X or Darwin. Murmur does not need " "special privileges to set itself up on these systems, so this behavior is highly discouraged."); - if (::setgid(Meta::mp.uiGid) != 0) - qFatal("Failed to switch to gid %d", Meta::mp.uiGid); - if (::setuid(Meta::mp.uiUid) != 0) - qFatal("Failed to switch to uid %d", Meta::mp.uiUid); + if (::setgid(Meta::mp->uiGid) != 0) + qFatal("Failed to switch to gid %d", Meta::mp->uiGid); + if (::setuid(Meta::mp->uiUid) != 0) + qFatal("Failed to switch to uid %d", Meta::mp->uiUid); uid_t uid = getuid(), euid = geteuid(); gid_t gid = getgid(), egid = getegid(); - if (uid == Meta::mp.uiUid && euid == Meta::mp.uiUid && gid == Meta::mp.uiGid && egid == Meta::mp.uiGid) { - qCritical("Successfully switched to uid %d", Meta::mp.uiUid); + if (uid == Meta::mp->uiUid && euid == Meta::mp->uiUid && gid == Meta::mp->uiGid && egid == Meta::mp->uiGid) { + qCritical("Successfully switched to uid %d", Meta::mp->uiUid); } else qFatal("Couldn't switch uid/gid."); #else - if (::initgroups(qPrintable(Meta::mp.qsName), Meta::mp.uiGid) != 0) + if (::initgroups(qPrintable(Meta::mp->qsName), Meta::mp->uiGid) != 0) qCritical("Can't initialize supplementary groups"); - if (::setgid(Meta::mp.uiGid) != 0) - qCritical("Failed to switch to gid %d", Meta::mp.uiGid); - if (::setuid(Meta::mp.uiUid) != 0) { - qFatal("Failed to become uid %d", Meta::mp.uiUid); + if (::setgid(Meta::mp->uiGid) != 0) + qCritical("Failed to switch to gid %d", Meta::mp->uiGid); + if (::setuid(Meta::mp->uiUid) != 0) { + qFatal("Failed to become uid %d", Meta::mp->uiUid); } else { - qCritical("Successfully switched to uid %d", Meta::mp.uiUid); + qCritical("Successfully switched to uid %d", Meta::mp->uiUid); initialcap(); } - if (!Meta::mp.qsHome.isEmpty()) { + if (!Meta::mp->qsHome.isEmpty()) { // QDir::homePath is broken. It only looks at $HOME // instead of getpwuid() so we have to set our home // ourselves - EnvUtils::setenv(QLatin1String("HOME"), Meta::mp.qsHome); + EnvUtils::setenv(QLatin1String("HOME"), Meta::mp->qsHome); } #endif } else if (bRoot) { diff --git a/src/murmur/main.cpp b/src/murmur/main.cpp index b75c4d58b..0c3c37957 100644 --- a/src/murmur/main.cpp +++ b/src/murmur/main.cpp @@ -176,8 +176,8 @@ void cleanup(int signum) { qInstallMessageHandler(nullptr); #ifdef Q_OS_UNIX - if (!Meta::mp.qsPid.isEmpty()) { - QFile pid(Meta::mp.qsPid); + if (!Meta::mp->qsPid.isEmpty()) { + QFile pid(Meta::mp->qsPid); pid.remove(); } #endif @@ -228,6 +228,9 @@ int main(int argc, char **argv) { a.setOrganizationName("Mumble"); a.setOrganizationDomain("mumble.sourceforge.net"); + // Initialize meta parameter + Meta::mp = std::make_unique< MetaParams >(); + MumbleSSL::initialize(); QString inifile; @@ -374,7 +377,7 @@ int main(int argc, char **argv) { #ifdef Q_OS_UNIX } else if (arg == "-limits") { detach = false; - Meta::mp.read(inifile); + Meta::mp->read(inifile); unixhandler.setuid(); unixhandler.finalcap(); LimitTest::testLimits(a); @@ -403,42 +406,42 @@ int main(int argc, char **argv) { inifile = unixhandler.trySystemIniFiles(inifile); #endif - Meta::mp.read(inifile); + Meta::mp->read(inifile); // Activating the logging of ACLs and groups via commandLine overwrites whatever is set in the ini file if (logGroups) { - Meta::mp.bLogGroupChanges = logGroups; + Meta::mp->bLogGroupChanges = logGroups; } if (logACL) { - Meta::mp.bLogACLChanges = logACL; + Meta::mp->bLogACLChanges = logACL; } // need to open log file early so log dir can be root owned: // http://article.gmane.org/gmane.comp.security.oss.general/4404 #ifdef Q_OS_UNIX - unixhandler.logToSyslog = Meta::mp.qsLogfile == QLatin1String("syslog"); - if (detach && !Meta::mp.qsLogfile.isEmpty() && !unixhandler.logToSyslog) { + unixhandler.logToSyslog = Meta::mp->qsLogfile == QLatin1String("syslog"); + if (detach && !Meta::mp->qsLogfile.isEmpty() && !unixhandler.logToSyslog) { #else - if (detach && !Meta::mp.qsLogfile.isEmpty()) { + if (detach && !Meta::mp->qsLogfile.isEmpty()) { #endif - qfLog = new QFile(Meta::mp.qsLogfile); + qfLog = new QFile(Meta::mp->qsLogfile); if (!qfLog->open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) { delete qfLog; qfLog = nullptr; #ifdef Q_OS_UNIX fprintf(stderr, "murmurd: failed to open logfile %s: no logging will be done\n", - qPrintable(Meta::mp.qsLogfile)); + qPrintable(Meta::mp->qsLogfile)); #else - qWarning("Failed to open logfile %s. No logging will be performed.", qPrintable(Meta::mp.qsLogfile)); + qWarning("Failed to open logfile %s. No logging will be performed.", qPrintable(Meta::mp->qsLogfile)); #endif } else { qfLog->setTextModeEnabled(true); QFileInfo qfi(*qfLog); - Meta::mp.qsLogfile = qfi.absoluteFilePath(); + Meta::mp->qsLogfile = qfi.absoluteFilePath(); #ifdef Q_OS_UNIX - if (Meta::mp.uiUid != 0 && fchown(qfLog->handle(), Meta::mp.uiUid, Meta::mp.uiGid) == -1) { - qFatal("can't change log file owner to %d %d:%d - %s", qfLog->handle(), Meta::mp.uiUid, Meta::mp.uiGid, - strerror(errno)); + if (Meta::mp->uiUid != 0 && fchown(qfLog->handle(), Meta::mp->uiUid, Meta::mp->uiGid) == -1) { + qFatal("can't change log file owner to %d %d:%d - %s", qfLog->handle(), Meta::mp->uiUid, + Meta::mp->uiGid, strerror(errno)); } #endif } @@ -477,11 +480,11 @@ int main(int argc, char **argv) { _exit(0); } - if (!Meta::mp.qsPid.isEmpty()) { - QFile pid(Meta::mp.qsPid); + if (!Meta::mp->qsPid.isEmpty()) { + QFile pid(Meta::mp->qsPid); if (pid.open(QIODevice::WriteOnly)) { QFileInfo fi(pid); - Meta::mp.qsPid = fi.absoluteFilePath(); + Meta::mp->qsPid = fi.absoluteFilePath(); QTextStream out(&pid); out << getpid();