Network: Use QFile::encodeName for POSIX paths instead of toLatin1

POSIX API doesn't really have defined encoding and kernel works with
null-terminated byte strings (char *) without any knowledge about
encodings.

But usually applications use LANG (and LC_*) as encoding making it
possible to use any encoding user wishes, including full Unicode
support when UTF-8 is used.

This allows to create and listen to sockets with paths containing
non-latin characters.
eg. listen(QString("/run/υποδοχή"));

Change-Id: I022ac6a8a4575103125c48768a66bef88a232a2a
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Dāvis Mosāns <davispuh@gmail.com>
This commit is contained in:
Dāvis Mosāns 2015-08-27 00:50:11 +03:00
parent bb281eea17
commit e18554d4f7
2 changed files with 15 additions and 14 deletions

View File

@ -85,7 +85,8 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName)
} }
serverName = requestedServerName; serverName = requestedServerName;
QString tempPath; QByteArray encodedTempPath;
const QByteArray encodedFullServerName = QFile::encodeName(fullServerName);
QScopedPointer<QTemporaryDir> tempDir; QScopedPointer<QTemporaryDir> tempDir;
// Check any of the flags // Check any of the flags
@ -96,8 +97,7 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName)
setError(QLatin1String("QLocalServer::listen")); setError(QLatin1String("QLocalServer::listen"));
return false; return false;
} }
tempPath = tempDir->path(); encodedTempPath = QFile::encodeName(tempDir->path() + QLatin1String("/s"));
tempPath += QLatin1String("/s");
} }
// create the unix socket // create the unix socket
@ -111,23 +111,23 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName)
// Construct the unix address // Construct the unix address
struct ::sockaddr_un addr; struct ::sockaddr_un addr;
addr.sun_family = PF_UNIX; addr.sun_family = PF_UNIX;
if (sizeof(addr.sun_path) < (uint)fullServerName.toLatin1().size() + 1) { if (sizeof(addr.sun_path) < (uint)encodedFullServerName.size() + 1) {
setError(QLatin1String("QLocalServer::listen")); setError(QLatin1String("QLocalServer::listen"));
closeServer(); closeServer();
return false; return false;
} }
if (socketOptions & QLocalServer::WorldAccessOption) { if (socketOptions & QLocalServer::WorldAccessOption) {
if (sizeof(addr.sun_path) < (uint)tempPath.toLatin1().size() + 1) { if (sizeof(addr.sun_path) < (uint)encodedTempPath.size() + 1) {
setError(QLatin1String("QLocalServer::listen")); setError(QLatin1String("QLocalServer::listen"));
closeServer(); closeServer();
return false; return false;
} }
::memcpy(addr.sun_path, tempPath.toLatin1().data(), ::memcpy(addr.sun_path, encodedTempPath.constData(),
tempPath.toLatin1().size() + 1); encodedTempPath.size() + 1);
} else { } else {
::memcpy(addr.sun_path, fullServerName.toLatin1().data(), ::memcpy(addr.sun_path, encodedFullServerName.constData(),
fullServerName.toLatin1().size() + 1); encodedFullServerName.size() + 1);
} }
// bind // bind
@ -165,13 +165,13 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName)
if (socketOptions & QLocalServer::OtherAccessOption) if (socketOptions & QLocalServer::OtherAccessOption)
mode |= S_IRWXO; mode |= S_IRWXO;
if (::chmod(tempPath.toLatin1(), mode) == -1) { if (::chmod(encodedTempPath.constData(), mode) == -1) {
setError(QLatin1String("QLocalServer::listen")); setError(QLatin1String("QLocalServer::listen"));
closeServer(); closeServer();
return false; return false;
} }
if (::rename(tempPath.toLatin1(), fullServerName.toLatin1()) == -1) { if (::rename(encodedTempPath.constData(), encodedFullServerName.constData()) == -1) {
setError(QLatin1String("QLocalServer::listen")); setError(QLatin1String("QLocalServer::listen"));
closeServer(); closeServer();
return false; return false;

View File

@ -268,15 +268,16 @@ void QLocalSocketPrivate::_q_connectToSocket()
connectingPathName += QLatin1Char('/') + connectingName; connectingPathName += QLatin1Char('/') + connectingName;
} }
const QByteArray encodedConnectingPathName = QFile::encodeName(connectingPathName);
struct sockaddr_un name; struct sockaddr_un name;
name.sun_family = PF_UNIX; name.sun_family = PF_UNIX;
if (sizeof(name.sun_path) < (uint)connectingPathName.toLatin1().size() + 1) { if (sizeof(name.sun_path) < (uint)encodedConnectingPathName.size() + 1) {
QString function = QLatin1String("QLocalSocket::connectToServer"); QString function = QLatin1String("QLocalSocket::connectToServer");
errorOccurred(QLocalSocket::ServerNotFoundError, function); errorOccurred(QLocalSocket::ServerNotFoundError, function);
return; return;
} }
::memcpy(name.sun_path, connectingPathName.toLatin1().data(), ::memcpy(name.sun_path, encodedConnectingPathName.constData(),
connectingPathName.toLatin1().size() + 1); encodedConnectingPathName.size() + 1);
if (-1 == qt_safe_connect(connectingSocket, (struct sockaddr *)&name, sizeof(name))) { if (-1 == qt_safe_connect(connectingSocket, (struct sockaddr *)&name, sizeof(name))) {
QString function = QLatin1String("QLocalSocket::connectToServer"); QString function = QLatin1String("QLocalSocket::connectToServer");
switch (errno) switch (errno)