mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-21 04:45:31 +08:00
Fix dbus assert when hostname contains non-Latin characters
This commit is contained in:
@@ -21,27 +21,25 @@ BLACK_DEFINE_VALUEOBJECT_MIXINS(BlackMisc, CIdentifier)
|
|||||||
//! \private Escape characters not allowed in dbus paths
|
//! \private Escape characters not allowed in dbus paths
|
||||||
QString toDBusPath(const QString &s)
|
QString toDBusPath(const QString &s)
|
||||||
{
|
{
|
||||||
Q_ASSERT_X(!BlackMisc::containsChar(s, [](QChar c) { return c.unicode() > 0x7f; }), Q_FUNC_INFO, "7-bit ASCII only");
|
return BlackMisc::utfToPercentEncoding(s, "/", '_');
|
||||||
return s.toLatin1().toPercentEncoding("/", "-._~", '_');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \private Escape characters not allowed in dbus path elements
|
//! \private Escape characters not allowed in dbus path elements
|
||||||
QString toDBusPathElement(const QString &s)
|
QString toDBusPathElement(const QString &s)
|
||||||
{
|
{
|
||||||
Q_ASSERT_X(!BlackMisc::containsChar(s, [](QChar c) { return c.unicode() > 0x7f; }), Q_FUNC_INFO, "7-bit ASCII only");
|
return BlackMisc::utfToPercentEncoding(s, {}, '_');
|
||||||
return s.toLatin1().toPercentEncoding({}, "-._~", '_');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \private Unescape characters not allowed in dbus paths
|
//! \private Unescape characters not allowed in dbus paths
|
||||||
QString fromDBusPath(const QString &s)
|
QString fromDBusPath(const QString &s)
|
||||||
{
|
{
|
||||||
return QByteArray::fromPercentEncoding(s.toLatin1(), '_');
|
return BlackMisc::utfFromPercentEncoding(s.toLatin1(), '_');
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \private Unescape characters not allowed in dbus path elements
|
//! \private Unescape characters not allowed in dbus path elements
|
||||||
QString fromDBusPathElement(const QString &s)
|
QString fromDBusPathElement(const QString &s)
|
||||||
{
|
{
|
||||||
return QByteArray::fromPercentEncoding(s.toLatin1(), '_');
|
return BlackMisc::utfFromPercentEncoding(s.toLatin1(), '_');
|
||||||
}
|
}
|
||||||
|
|
||||||
//! \private
|
//! \private
|
||||||
|
|||||||
@@ -34,6 +34,69 @@ namespace BlackMisc
|
|||||||
return splitString(s, [](QChar c) { return c == '\n' || c == '\r'; });
|
return splitString(s, [](QChar c) { return c == '\n' || c == '\r'; });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QByteArray utfToPercentEncoding(const QString& s, const QByteArray &allow, char percent)
|
||||||
|
{
|
||||||
|
QByteArray result;
|
||||||
|
for (const QChar &c : s)
|
||||||
|
{
|
||||||
|
if (const char latin = c.toLatin1())
|
||||||
|
{
|
||||||
|
if ((latin >= 'a' && latin <= 'z') || (latin >= 'A' && latin <= 'Z')
|
||||||
|
|| (latin >= '0' && latin <= '9') || allow.contains(latin))
|
||||||
|
{
|
||||||
|
result += c;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result += percent;
|
||||||
|
if (latin < 0x10) { result += '0'; }
|
||||||
|
result += QByteArray::number(static_cast<int>(latin), 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result += percent;
|
||||||
|
result += 'x';
|
||||||
|
const ushort unicode = c.unicode();
|
||||||
|
if (unicode < 0x0010) { result += '0'; }
|
||||||
|
if (unicode < 0x0100) { result += '0'; }
|
||||||
|
if (unicode < 0x1000) { result += '0'; }
|
||||||
|
result += QByteArray::number(unicode, 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString utfFromPercentEncoding(const QByteArray& ba, char percent)
|
||||||
|
{
|
||||||
|
QString result;
|
||||||
|
for (int i = 0; i < ba.size(); ++i)
|
||||||
|
{
|
||||||
|
if (ba[i] == percent)
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
Q_ASSERT(i < ba.size());
|
||||||
|
if (ba[i] == 'x')
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
Q_ASSERT(i < ba.size());
|
||||||
|
result += QChar(ba.mid(i, 4).toInt(nullptr, 16));
|
||||||
|
i += 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result += static_cast<char>(ba.mid(i, 2).toInt(nullptr, 16));
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result += ba[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
const QString &boolToOnOff(bool v)
|
const QString &boolToOnOff(bool v)
|
||||||
{
|
{
|
||||||
static const QString on("on");
|
static const QString on("on");
|
||||||
|
|||||||
@@ -126,6 +126,12 @@ namespace BlackMisc
|
|||||||
//! Split a string into multiple lines. Blank lines are skipped.
|
//! Split a string into multiple lines. Blank lines are skipped.
|
||||||
BLACKMISC_EXPORT QStringList splitLines(const QString &s);
|
BLACKMISC_EXPORT QStringList splitLines(const QString &s);
|
||||||
|
|
||||||
|
//! Extended percent encoding supporting UTF-16
|
||||||
|
BLACKMISC_EXPORT QByteArray utfToPercentEncoding(const QString &s, const QByteArray &allow = {}, char percent = '%');
|
||||||
|
|
||||||
|
//! Reverse utfFromPercentEncoding
|
||||||
|
BLACKMISC_EXPORT QString utfFromPercentEncoding(const QByteArray &ba, char percent = '%');
|
||||||
|
|
||||||
//! A map converted to string
|
//! A map converted to string
|
||||||
template<class K, class V> QString qmapToString(const QMap<K, V> &map)
|
template<class K, class V> QString qmapToString(const QMap<K, V> &map)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ namespace BlackMiscTest
|
|||||||
void CTestIdentifier::dbusObjectPath()
|
void CTestIdentifier::dbusObjectPath()
|
||||||
{
|
{
|
||||||
QObject q;
|
QObject q;
|
||||||
q.setObjectName("!@#$%^&*()_+");
|
q.setObjectName(QString::fromUtf16(u"!@#$%^&*()_+\u263a"));
|
||||||
CTestIdentifiable id(&q);
|
CTestIdentifiable id(&q);
|
||||||
QString s(id.identifier().toDBusObjectPath());
|
QString s(id.identifier().toDBusObjectPath());
|
||||||
QVERIFY2(id.identifier() == CIdentifier::fromDBusObjectPath(s), "Conversion from dbus object path and back compares equal");
|
QVERIFY2(id.identifier() == CIdentifier::fromDBusObjectPath(s), "Conversion from dbus object path and back compares equal");
|
||||||
|
|||||||
@@ -129,12 +129,17 @@ namespace BlackMiscTest
|
|||||||
//! ctor
|
//! ctor
|
||||||
Server()
|
Server()
|
||||||
{
|
{
|
||||||
|
QObject::connect(&m_process, qOverload<int, QProcess::ExitStatus>(&QProcess::finished), [](int code, QProcess::ExitStatus status)
|
||||||
|
{
|
||||||
|
qDebug() << "Server process exited" << (status ? "abnormally" : "normally") << "with exit code" << code;
|
||||||
|
});
|
||||||
m_process.start("sharedstatetestserver", QStringList());
|
m_process.start("sharedstatetestserver", QStringList());
|
||||||
m_process.waitForStarted();
|
m_process.waitForStarted();
|
||||||
}
|
}
|
||||||
//! dtor
|
//! dtor
|
||||||
~Server()
|
~Server()
|
||||||
{
|
{
|
||||||
|
m_process.disconnect();
|
||||||
m_process.kill();
|
m_process.kill();
|
||||||
m_process.waitForFinished();
|
m_process.waitForFinished();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user