continue on switching QString and QByteArray

This commit is contained in:
csoler 2021-11-29 22:59:46 +01:00
parent e4ce32bef8
commit 6a4cdcc471
28 changed files with 525 additions and 397 deletions

View File

@ -744,7 +744,6 @@ HEADERS += tor/AddOnionCommand.h \
tor/TorManager.h \
tor/TorProcess.h \
tor/TorProcess_p.h \
tor/TorSocket.h \
tor/Useful.h
SOURCES += tor/AddOnionCommand.cpp \
@ -758,7 +757,6 @@ SOURCES += tor/AddOnionCommand.cpp \
tor/TorControlSocket.cpp \
tor/TorManager.cpp \
tor/TorProcess.cpp \
tor/TorSocket.cpp \
tor/CryptoKey.cpp \
tor/PendingOperation.cpp \
tor/SecureRNG.cpp \

View File

@ -45,12 +45,12 @@ AddOnionCommand::AddOnionCommand(HiddenService *service)
bool AddOnionCommand::isSuccessful() const
{
return statusCode() == 250 && m_errorMessage.isEmpty();
return statusCode() == 250 && m_errorMessage.empty();
}
QByteArray AddOnionCommand::build()
ByteArray AddOnionCommand::build()
{
QByteArray out("ADD_ONION");
ByteArray out("ADD_ONION");
if (m_service->privateKey().isLoaded()) {
out += " ";
@ -74,11 +74,11 @@ QByteArray AddOnionCommand::build()
return out;
}
void AddOnionCommand::onReply(int statusCode, const QByteArray &data)
void AddOnionCommand::onReply(int statusCode, const ByteArray &data)
{
TorControlCommand::onReply(statusCode, data);
if (statusCode != 250) {
m_errorMessage = QString::fromLatin1(data);
m_errorMessage = data.toString();
return;
}
@ -86,17 +86,17 @@ void AddOnionCommand::onReply(int statusCode, const QByteArray &data)
const QByteArray sidPrefix("ServiceID=");
if(data.startsWith("ServiceID=")){
QByteArray service_id = data.mid(sidPrefix.size());
ByteArray service_id = data.mid(sidPrefix.size());
m_service->setServiceId(service_id);
}
if (data.startsWith(keyPrefix)) {
QByteArray keyData(data.mid(keyPrefix.size()));
ByteArray keyData(data.mid(keyPrefix.size()));
CryptoKey key;
if (!key.loadFromTorMessage(keyData)) {
m_errorMessage = QStringLiteral("Key structure check failed");
m_errorMessage = "Key structure check failed";
return;
}

View File

@ -48,15 +48,15 @@ class AddOnionCommand : public TorControlCommand
Q_OBJECT
Q_DISABLE_COPY(AddOnionCommand)
Q_PROPERTY(QString errorMessage READ errorMessage CONSTANT)
Q_PROPERTY(std::string errorMessage READ errorMessage CONSTANT)
Q_PROPERTY(bool successful READ isSuccessful CONSTANT)
public:
AddOnionCommand(HiddenService *service);
QByteArray build();
ByteArray build();
QString errorMessage() const { return m_errorMessage; }
std::string errorMessage() const { return m_errorMessage; }
bool isSuccessful() const;
signals:
@ -65,9 +65,9 @@ signals:
protected:
HiddenService *m_service;
QString m_errorMessage;
std::string m_errorMessage;
virtual void onReply(int statusCode, const QByteArray &data);
virtual void onReply(int statusCode, const ByteArray &data);
virtual void onFinished(int statusCode);
};

View File

@ -41,12 +41,12 @@ GetConfCommand::GetConfCommand(Type t)
{
}
ByteArray GetConfCommand::build(const ByteArray &key)
ByteArray GetConfCommand::build(const std::string &key)
{
return build(QList<ByteArray>() << key);
return build(std::list<std::string> { key } );
}
ByteArray GetConfCommand::build(const QList<ByteArray> &keys)
ByteArray GetConfCommand::build(const std::list<std::string> &keys)
{
ByteArray out;
if (type == GetConf) {
@ -97,9 +97,9 @@ void GetConfCommand::onDataFinished()
m_lastKey.clear();
}
std::list<std::string> GetConfCommand::get(const ByteArray& key) const
std::list<std::string> GetConfCommand::get(const std::string& key) const
{
auto it = m_results.find(key.toString());
auto it = m_results.find(key);
if(it != m_results.end())
return it->second;

View File

@ -56,11 +56,11 @@ public:
GetConfCommand(Type type);
ByteArray build(const ByteArray &key);
ByteArray build(const QList<ByteArray> &keys);
ByteArray build(const std::string &key);
ByteArray build(const std::list<std::string> &keys);
const std::map<std::string,std::list<std::string> > &results() const { return m_results; }
std::list<std::string> get(const ByteArray &key) const;
std::list<std::string> get(const std::string &key) const;
protected:
virtual void onReply(int statusCode, const ByteArray &data);

View File

@ -34,9 +34,7 @@
#include "TorControl.h"
#include "CryptoKey.h"
#include "Useful.h"
#include <QDir>
#include <QTimer>
#include <QDebug>
#include "util/rsdir.h"
using namespace Tor;
@ -49,9 +47,10 @@ HiddenService::HiddenService(HiddenServiceClient *client,const std::string& path
: m_dataPath(path), m_status(NotCreated), m_client(client)
{
/* Set the initial status and, if possible, load the hostname */
if (QDir(m_dataPath).exists(QLatin1String("private_key"))) {
if(RsDirUtil::fileExists(m_dataPath + "/private_key"))
{
loadPrivateKey();
if (!m_hostname.isEmpty())
if (!m_hostname.empty())
m_status = Offline;
}
}
@ -81,19 +80,19 @@ void HiddenService::setStatus(Status newStatus)
void HiddenService::addTarget(const Target &target)
{
m_targets.append(target);
m_targets.push_back(target);
}
void HiddenService::addTarget(quint16 servicePort, QHostAddress targetAddress, quint16 targetPort)
{
Target t = { targetAddress, servicePort, targetPort };
m_targets.append(t);
m_targets.push_back(t);
}
void HiddenService::setServiceId(const ByteArray& sid)
{
m_service_id = sid;
m_hostname = sid + ".onion";
m_hostname = sid.toString() + ".onion";
if(m_client)
m_client->hiddenServiceHostnameChanged(); // emit hostnameChanged();
@ -105,13 +104,6 @@ void HiddenService::setPrivateKey(const CryptoKey &key)
return;
}
#ifdef TO_REMOVE
if (!key.isPrivate()) {
BUG() << "Cannot create a hidden service with a public key";
return;
}
#endif
m_privateKey = key;
if(m_client)
@ -120,13 +112,13 @@ void HiddenService::setPrivateKey(const CryptoKey &key)
void HiddenService::loadPrivateKey()
{
if (m_privateKey.isLoaded() || m_dataPath.isEmpty())
if (m_privateKey.isLoaded() || m_dataPath.empty())
return;
bool ok = m_privateKey.loadFromFile(m_dataPath + QLatin1String("/private_key"));
bool ok = m_privateKey.loadFromFile(m_dataPath + "/private_key");
if (!ok) {
qWarning() << "Failed to load hidden service key";
RsWarn() << "Failed to load hidden service key";
return;
}
@ -138,7 +130,7 @@ void HiddenService::servicePublished()
{
loadPrivateKey();
if (m_hostname.isEmpty()) {
if (m_hostname.empty()) {
std::cerr << "Failed to read hidden service hostname" << std::endl;
return;
}

View File

@ -35,9 +35,7 @@
#include <QObject>
#include <QHostAddress>
#include <QList>
#include "CryptoKey.h"
#include "bytearray.h"
namespace Tor
@ -78,7 +76,7 @@ public:
HiddenService(HiddenServiceClient *client);
HiddenService(HiddenServiceClient *client, const std::string &dataPath);
HiddenService(HiddenServiceClient *client, const CryptoKey &privateKey, const std::string &dataPath = QString());
HiddenService(HiddenServiceClient *client, const CryptoKey &privateKey, const std::string &dataPath = std::string());
Status status() const { return m_status; }

View File

@ -44,23 +44,23 @@ bool PendingOperation::isFinished() const
bool PendingOperation::isSuccess() const
{
return m_finished && m_errorMessage.isNull();
return m_finished && m_errorMessage.empty();
}
bool PendingOperation::isError() const
{
return m_finished && !m_errorMessage.isNull();
return m_finished && !m_errorMessage.empty();
}
QString PendingOperation::errorMessage() const
std::string PendingOperation::errorMessage() const
{
return m_errorMessage;
}
void PendingOperation::finishWithError(const QString &message)
void PendingOperation::finishWithError(const std::string &message)
{
if (message.isEmpty())
m_errorMessage = QStringLiteral("Unknown Error");
if (message.empty())
m_errorMessage = "Unknown Error";
m_errorMessage = message;
if (!m_finished) {
@ -72,7 +72,7 @@ void PendingOperation::finishWithError(const QString &message)
void PendingOperation::finishWithSuccess()
{
Q_ASSERT(m_errorMessage.isNull());
Q_ASSERT(m_errorMessage.empty());
if (!m_finished) {
m_finished = true;

View File

@ -55,7 +55,7 @@ class PendingOperation : public QObject
Q_PROPERTY(bool isFinished READ isFinished NOTIFY finished FINAL)
Q_PROPERTY(bool isSuccess READ isSuccess NOTIFY success FINAL)
Q_PROPERTY(bool isError READ isError NOTIFY error FINAL)
Q_PROPERTY(QString errorMessage READ errorMessage NOTIFY finished FINAL)
Q_PROPERTY(std::string errorMessage READ errorMessage NOTIFY finished FINAL)
public:
PendingOperation(QObject *parent = 0);
@ -63,23 +63,23 @@ public:
bool isFinished() const;
bool isSuccess() const;
bool isError() const;
QString errorMessage() const;
std::string errorMessage() const;
signals:
// Always emitted once when finished, regardless of status
void finished();
// One of error() or success() is emitted once
void error(const QString &errorMessage);
void error(const std::string &errorMessage);
void success();
protected slots:
void finishWithError(const QString &errorMessage);
void finishWithError(const std::string &errorMessage);
void finishWithSuccess();
private:
bool m_finished;
QString m_errorMessage;
std::string m_errorMessage;
};
Q_DECLARE_METATYPE(PendingOperation*)

View File

@ -33,7 +33,6 @@
#include "ProtocolInfoCommand.h"
#include "TorControl.h"
#include "StrUtil.h"
#include <QList>
using namespace Tor;
@ -55,14 +54,15 @@ void ProtocolInfoCommand::onReply(int statusCode, const ByteArray &data)
if (data.startsWith("AUTH "))
{
QList<ByteArray> tokens = splitQuotedStrings(data.mid(5), ' ');
std::list<ByteArray> tokens = splitQuotedStrings(data.mid(5), ' ');
foreach (ByteArray token, tokens)
{
if (token.startsWith("METHODS="))
{
QList<ByteArray> textMethods = unquotedString(token.mid(8)).split(',');
for (QList<ByteArray>::Iterator it = textMethods.begin(); it != textMethods.end(); ++it)
std::list<ByteArray> textMethods = unquotedString(token.mid(8)).split(',');
for (std::list<ByteArray>::iterator it = textMethods.begin(); it != textMethods.end(); ++it)
{
if (*it == "NULL")
m_authMethods |= AuthNull;
@ -74,12 +74,12 @@ void ProtocolInfoCommand::onReply(int statusCode, const ByteArray &data)
}
else if (token.startsWith("COOKIEFILE="))
{
m_cookieFile = QString::fromLatin1(unquotedString(token.mid(11)));
m_cookieFile = unquotedString(token.mid(11)).toString();
}
}
}
else if (data.startsWith("VERSION Tor="))
{
m_torVersion = std::string(unquotedString(data.mid(12, data.indexOf(' ', 12))));
m_torVersion = unquotedString(data.mid(12, data.indexOf(' ', 12))).toString();
}
}

View File

@ -34,7 +34,6 @@
#define PROTOCOLINFOCOMMAND_H
#include "TorControlCommand.h"
#include <QFlags>
namespace Tor
{
@ -60,8 +59,8 @@ public:
ByteArray build();
AuthMethods authMethods() const { return m_authMethods; }
QString torVersion() const { return m_torVersion; }
QString cookieFile() const { return m_cookieFile; }
std::string torVersion() const { return m_torVersion; }
std::string cookieFile() const { return m_cookieFile; }
protected:
virtual void onReply(int statusCode, const ByteArray &data);
@ -69,8 +68,8 @@ protected:
private:
TorControl *manager;
AuthMethods m_authMethods;
QString m_torVersion;
QString m_cookieFile;
std::string m_torVersion;
std::string m_cookieFile;
};
}

View File

@ -50,9 +50,9 @@ bool SetConfCommand::isSuccessful() const
return statusCode() == 250;
}
ByteArray SetConfCommand::build(const ByteArray &key, const ByteArray &value)
ByteArray SetConfCommand::build(const std::string &key, const std::string &value)
{
return build(std::list<std::pair<ByteArray, ByteArray> > { std::make_pair(key, value) } );
return build(std::list<std::pair<std::string, std::string> > { std::make_pair(key, value) } );
}
// ByteArray SetConfCommand::build(const std::list<std::pair<ByteArray,ByteArray> > &data)
@ -74,7 +74,7 @@ ByteArray SetConfCommand::build(const ByteArray &key, const ByteArray &value)
// return build(out);
// }
ByteArray SetConfCommand::build(const std::list<std::pair<ByteArray, ByteArray> >& data)
ByteArray SetConfCommand::build(const std::list<std::pair<std::string, std::string> >& data)
{
ByteArray out(m_resetMode ? "RESETCONF" : "SETCONF");

View File

@ -54,8 +54,8 @@ public:
void setResetMode(bool resetMode);
ByteArray build(const ByteArray &key, const ByteArray &value);
ByteArray build(const std::list<std::pair<ByteArray, ByteArray> > &data);
ByteArray build(const std::string &key, const std::string &value);
ByteArray build(const std::list<std::pair<std::string, std::string> > &data);
std::string errorMessage() const { return m_errorMessage; }
bool isSuccessful() const;

View File

@ -115,7 +115,7 @@ QString SettingsFile::filePath() const
return d->filePath;
}
bool SettingsFile::setFilePath(const QString &filePath)
bool SettingsFile::setFilePath(const std::string& filePath)
{
if (d->filePath == filePath)
return hasError();
@ -125,8 +125,8 @@ bool SettingsFile::setFilePath(const QString &filePath)
QFileInfo fileInfo(filePath);
QDir dir(fileInfo.path());
if (!dir.exists() && !dir.mkpath(QStringLiteral("."))) {
d->setError(QStringLiteral("Cannot create directory: %1").arg(dir.path()));
if (!dir.exists() && !dir.mkpath(".")) {
d->setError("Cannot create directory: " + dir.path()));
return false;
}
d->checkDirPermissions(fileInfo.path());
@ -137,7 +137,7 @@ bool SettingsFile::setFilePath(const QString &filePath)
return true;
}
QString SettingsFile::errorMessage() const
std::string SettingsFile::errorMessage() const
{
return d->errorMessage;
}

View File

@ -66,9 +66,9 @@ public:
virtual ~SettingsFile();
QString filePath() const;
bool setFilePath(const QString &filePath);
bool setFilePath(const std::string &filePath);
QString errorMessage() const;
std::string errorMessage() const;
bool hasError() const;
SettingsObject *root();
@ -136,38 +136,38 @@ public:
static SettingsFile *defaultFile();
static void setDefaultFile(SettingsFile *file);
QString path() const;
void setPath(const QString &path);
std::string path() const;
void setPath(const std::string &path);
QJsonObject data() const;
void setData(const QJsonObject &data);
Q_INVOKABLE QJsonValue read(const QString &key, const QJsonValue &defaultValue = QJsonValue::Undefined) const;
template<typename T> T read(const QString &key) const;
Q_INVOKABLE void write(const QString &key, const QJsonValue &value);
template<typename T> void write(const QString &key, const T &value);
Q_INVOKABLE void unset(const QString &key);
Q_INVOKABLE QJsonValue read(const std::string &key, const QJsonValue &defaultValue = QJsonValue::Undefined) const;
template<typename T> T read(const std::string &key) const;
Q_INVOKABLE void write(const std::string &key, const QJsonValue &value);
template<typename T> void write(const std::string &key, const T &value);
Q_INVOKABLE void unset(const std::string &key);
// const char* key overloads
QJsonValue read(const char *key, const QJsonValue &defaultValue = QJsonValue::Undefined) const
{
return read(QString::fromLatin1(key), defaultValue);
return read(std::string(key), defaultValue);
}
template<typename T> T read(const char *key) const
{
return read<T>(QString::fromLatin1(key));
return read<T>(std::string(key));
}
void write(const char *key, const QJsonValue &value)
{
write(QString::fromLatin1(key), value);
write(std::string(key), value);
}
template<typename T> void write(const char *key, const T &value)
{
write<T>(QString::fromLatin1(key), value);
write<T>(std::string(key), value);
}
void unset(const char *key)
{
unset(QString::fromLatin1(key));
unset(std::string(key));
}
Q_INVOKABLE void undefine();
@ -176,56 +176,56 @@ signals:
void pathChanged();
void dataChanged();
void modified(const QString &path, const QJsonValue &value);
void modified(const std::string &path, const QJsonValue &value);
private:
SettingsObjectPrivate *d;
};
template<typename T> inline void SettingsObject::write(const QString &key, const T &value)
template<typename T> inline void SettingsObject::write(const std::string &key, const T &value)
{
write(key, QJsonValue(value));
}
template<> inline QString SettingsObject::read<QString>(const QString &key) const
template<> inline std::string SettingsObject::read<std::string>(const std::string &key) const
{
return read(key).toString();
}
template<> inline QJsonArray SettingsObject::read<QJsonArray>(const QString &key) const
template<> inline QJsonArray SettingsObject::read<QJsonArray>(const std::string &key) const
{
return read(key).toArray();
}
template<> inline QJsonObject SettingsObject::read<QJsonObject>(const QString &key) const
template<> inline QJsonObject SettingsObject::read<QJsonObject>(const std::string &key) const
{
return read(key).toObject();
}
template<> inline double SettingsObject::read<double>(const QString &key) const
template<> inline double SettingsObject::read<double>(const std::string &key) const
{
return read(key).toDouble();
}
template<> inline int SettingsObject::read<int>(const QString &key) const
template<> inline int SettingsObject::read<int>(const std::string &key) const
{
return read(key).toInt();
}
template<> inline bool SettingsObject::read<bool>(const QString &key) const
template<> inline bool SettingsObject::read<bool>(const std::string &key) const
{
return read(key).toBool();
}
template<> inline QDateTime SettingsObject::read<QDateTime>(const QString &key) const
template<> inline QDateTime SettingsObject::read<QDateTime>(const std::string &key) const
{
QString value = read(key).toString();
std::string value = read(key).toString();
if (value.isEmpty())
return QDateTime();
return QDateTime::fromString(value, Qt::ISODate).toLocalTime();
}
template<> inline void SettingsObject::write<QDateTime>(const QString &key, const QDateTime &value)
template<> inline void SettingsObject::write<QDateTime>(const std::string &key, const QDateTime &value)
{
write(key, QJsonValue(value.toUTC().toString(Qt::ISODate)));
}
@ -242,14 +242,14 @@ private:
QByteArray d;
};
template<> inline Base64Encode SettingsObject::read<Base64Encode>(const QString &key) const
template<> inline Base64Encode SettingsObject::read<Base64Encode>(const std::string &key) const
{
return Base64Encode(QByteArray::fromBase64(read(key).toString().toLatin1()));
}
template<> inline void SettingsObject::write<Base64Encode>(const QString &key, const Base64Encode &value)
template<> inline void SettingsObject::write<Base64Encode>(const std::string &key, const Base64Encode &value)
{
write(key, QJsonValue(QString::fromLatin1(value.encoded())));
write(key, QJsonValue(std::string(value.encoded())));
}
#endif

View File

@ -59,7 +59,7 @@ ByteArray quotedString(const ByteArray &string)
return out;
}
ByteArray unquotedString(const ByteArray &string)
ByteArray unquotedString(const ByteArray& string)
{
if (string.size() < 2 || string[0] != '"')
return string;

View File

@ -31,6 +31,8 @@
*/
#include <time.h>
#include <fstream>
#include "util/rsdir.h"
#include "retroshare/rstor.h"
#include "TorControl.h"
@ -83,15 +85,15 @@ public:
TorControlSocket *socket;
QHostAddress torAddress;
QString errorMessage;
QString torVersion;
std::string errorMessage;
std::string torVersion;
ByteArray authPassword;
QHostAddress socksAddress;
QList<HiddenService*> services;
quint16 controlPort, socksPort;
TorControl::Status status;
TorControl::TorStatus torStatus;
QVariantMap bootstrapStatus;
std::map<std::string,std::string> bootstrapStatus;
bool hasOwnership;
TorControlPrivate(TorControl *parent);
@ -110,10 +112,10 @@ public slots:
void authenticateReply();
void protocolInfoReply();
void getTorInfoReply();
void setError(const QString &message);
void setError(const std::string &message);
void statusEvent(int code, const ByteArray &data);
void updateBootstrap(const QList<ByteArray> &data);
void updateBootstrap(const std::list<ByteArray> &data);
};
}
@ -219,12 +221,12 @@ void TorControlPrivate::setTorStatus(TorControl::TorStatus n)
}
}
void TorControlPrivate::setError(const QString &message)
void TorControlPrivate::setError(const std::string &message)
{
errorMessage = message;
setStatus(TorControl::Error);
qWarning() << "torctrl: Error:" << errorMessage;
RsWarn() << "torctrl: Error:" << errorMessage;
socket->abort();
@ -241,12 +243,12 @@ TorControl::TorStatus TorControl::torStatus() const
return d->torStatus;
}
QString TorControl::torVersion() const
std::string TorControl::torVersion() const
{
return d->torVersion;
}
QString TorControl::errorMessage() const
std::string TorControl::errorMessage() const
{
return d->errorMessage;
}
@ -271,7 +273,7 @@ QList<HiddenService*> TorControl::hiddenServices() const
return d->services;
}
QVariantMap TorControl::bootstrapStatus() const
std::map<std::string,std::string> TorControl::bootstrapStatus() const
{
return d->bootstrapStatus;
}
@ -369,7 +371,7 @@ void TorControlPrivate::socketDisconnected()
void TorControlPrivate::socketError()
{
setError(QStringLiteral("Connection failed: %1").arg(socket->errorString()));
setError("Connection failed: " + socket->errorString()));
}
void TorControlPrivate::protocolInfoReply()
@ -393,11 +395,11 @@ void TorControlPrivate::protocolInfoReply()
torCtrlDebug() << "torctrl: Using null authentication" << std::endl;
data = auth->build();
}
else if (methods.testFlag(ProtocolInfoCommand::AuthCookie) && !info->cookieFile().isEmpty())
else if (methods.testFlag(ProtocolInfoCommand::AuthCookie) && !info->cookieFile().empty())
{
QString cookieFile = info->cookieFile();
QString cookieError;
torCtrlDebug() << "torctrl: Using cookie authentication with file" << cookieFile.toStdString() << std::endl;
std::string cookieFile = info->cookieFile();
std::string cookieError;
torCtrlDebug() << "torctrl: Using cookie authentication with file" << cookieFile << std::endl;
QFile file(cookieFile);
if (file.open(QIODevice::ReadOnly))
@ -410,28 +412,28 @@ void TorControlPrivate::protocolInfoReply()
if (cookie.size() == 32)
data = auth->build(cookie);
else
cookieError = QStringLiteral("Unexpected file size");
cookieError = "Unexpected file size";
}
else
cookieError = file.errorString();
if (!cookieError.isNull() || data.isNull())
if (!cookieError.empty() || data.isNull())
{
/* If we know a password and password authentication is allowed, try using that instead.
* This is a strange corner case that will likely never happen in a normal configuration,
* but it has happened. */
if (methods.testFlag(ProtocolInfoCommand::AuthHashedPassword) && !authPassword.isEmpty())
if (methods.testFlag(ProtocolInfoCommand::AuthHashedPassword) && !authPassword.empty())
{
torCtrlDebug() << "torctrl: Unable to read authentication cookie file:" << cookieError.toStdString() << std::endl;
torCtrlDebug() << "torctrl: Unable to read authentication cookie file:" << cookieError << std::endl;
goto usePasswordAuth;
}
setError(QStringLiteral("Unable to read authentication cookie file: %1").arg(cookieError));
setError("Unable to read authentication cookie file: " + cookieError);
delete auth;
return;
}
}
else if (methods.testFlag(ProtocolInfoCommand::AuthHashedPassword) && !authPassword.isEmpty())
else if (methods.testFlag(ProtocolInfoCommand::AuthHashedPassword) && !authPassword.empty())
{
usePasswordAuth:
torCtrlDebug() << "torctrl: Using hashed password authentication" << std::endl;
@ -440,9 +442,9 @@ void TorControlPrivate::protocolInfoReply()
else
{
if (methods.testFlag(ProtocolInfoCommand::AuthHashedPassword))
setError(QStringLiteral("Tor requires a control password to connect, but no password is configured."));
setError("Tor requires a control password to connect, but no password is configured.");
else
setError(QStringLiteral("Tor is not configured to accept any supported authentication methods."));
setError("Tor is not configured to accept any supported authentication methods.");
delete auth;
return;
}
@ -458,11 +460,10 @@ void TorControlPrivate::getTorInfo()
GetConfCommand *command = new GetConfCommand(GetConfCommand::GetInfo);
connect(command, &TorControlCommand::finished, this, &TorControlPrivate::getTorInfoReply);
QList<ByteArray> keys;
keys << ByteArray("status/circuit-established") << ByteArray("status/bootstrap-phase");
std::list<std::string> keys{ "status/circuit-established","status/bootstrap-phase" };
/* If these are set in the config, they override the automatic behavior. */
SettingsObject settings(QStringLiteral("tor"));
SettingsObject settings("tor");
QHostAddress forceAddress(settings.read("socksAddress").toString());
quint16 port = (quint16)settings.read("socksPort").toInt();
@ -478,8 +479,9 @@ void TorControlPrivate::getTorInfo()
ev->mTorManagerEventType = RsTorManagerEventCode::TOR_CONNECTIVITY_CHANGED;
rsEvents->sendEvent(ev);
}
} else
keys << ByteArray("net/listeners/socks");
}
else
keys .push_back("net/listeners/socks");
socket->sendCommand(command, command->build(keys));
}
@ -490,11 +492,12 @@ void TorControlPrivate::getTorInfoReply()
if (!command || !q->isConnected())
return;
QList<ByteArray> listenAddresses = splitQuotedStrings(command->get(ByteArray("net/listeners/socks")).toString().toLatin1(), ' ');
for (QList<ByteArray>::Iterator it = listenAddresses.begin(); it != listenAddresses.end(); ++it) {
ByteArray value = unquotedString(*it);
std::list<ByteArray> listenAddresses = splitQuotedStrings(command->get("net/listeners/socks").front(), ' ');
for (const auto& add:listenAddresses) {
ByteArray value = unquotedString(add);
int sepp = value.indexOf(':');
QHostAddress address(QString::fromLatin1(value.mid(0, sepp)));
QHostAddress address(value.mid(0, sepp));
quint16 port = (quint16)value.mid(sepp+1).toUInt();
/* Use the first address that matches the one used for this control connection. If none do,
@ -523,16 +526,16 @@ void TorControlPrivate::getTorInfoReply()
}
}
if (command->get(ByteArray("status/circuit-established")).toInt() == 1) {
if (command->get("status/circuit-established").toInt() == 1) {
torCtrlDebug() << "torctrl: Tor indicates that circuits have been established; state is TorReady" << std::endl;
setTorStatus(TorControl::TorReady);
} else {
setTorStatus(TorControl::TorOffline);
}
ByteArray bootstrap = command->get(ByteArray("status/bootstrap-phase")).toString().toLatin1();
if (!bootstrap.isEmpty())
updateBootstrap(splitQuotedStrings(bootstrap, ' '));
auto bootstrap = command->get("status/bootstrap-phase");
if (!bootstrap.empty())
updateBootstrap(splitQuotedStrings(bootstrap.front(), ' '));
}
void TorControl::addHiddenService(HiddenService *service)
@ -555,7 +558,7 @@ void TorControlPrivate::publishServices()
}
std::cerr << std::endl;
SettingsObject settings(QStringLiteral("tor"));
SettingsObject settings("tor");
if (settings.read("neverPublishServices").toBool())
{
torCtrlDebug() << "torctrl: Skipping service publication because neverPublishService is enabled" << std::endl;
@ -567,12 +570,12 @@ void TorControlPrivate::publishServices()
return;
}
if (q->torVersionAsNewAs(QStringLiteral("0.2.7"))) {
if (q->torVersionAsNewAs("0.2.7")) {
foreach (HiddenService *service, services) {
if (service->hostname().isEmpty())
if (service->hostname().empty())
torCtrlDebug() << "torctrl: Creating a new hidden service" << std::endl;
else
torCtrlDebug() << "torctrl: Publishing hidden service: " << service->hostname().toStdString() << std::endl;
torCtrlDebug() << "torctrl: Publishing hidden service: " << service->hostname() << std::endl;
AddOnionCommand *onionCommand = new AddOnionCommand(service);
QObject::connect(onionCommand, &AddOnionCommand::succeeded, service, &HiddenService::servicePublished);
socket->sendCommand(onionCommand, onionCommand->build());
@ -580,37 +583,37 @@ void TorControlPrivate::publishServices()
} else {
torCtrlDebug() << "torctrl: Using legacy SETCONF hidden service configuration for tor" << torVersion.toStdString() << std::endl;
SetConfCommand *command = new SetConfCommand;
QList<QPair<ByteArray,ByteArray> > torConfig;
std::list<std::pair<std::string,std::string> > torConfig;
foreach (HiddenService *service, services)
{
if (service->dataPath().isEmpty())
if (service->dataPath().empty())
continue;
if (service->privateKey().isLoaded() && !QFile::exists(service->dataPath() + QStringLiteral("/private_key"))) {
if (service->privateKey().isLoaded() && !RsDirUtil::fileExists(service->dataPath() + "/private_key")) {
// This case can happen if tor is downgraded after the profile is created
qWarning() << "Cannot publish ephemeral hidden services with this version of tor; skipping";
RsWarn() << "Cannot publish ephemeral hidden services with this version of tor; skipping";
continue;
}
torCtrlDebug() << "torctrl: Configuring hidden service at" << service->dataPath().toStdString() << std::endl;
torCtrlDebug() << "torctrl: Configuring hidden service at" << service->dataPath() << std::endl;
QDir dir(service->dataPath());
torConfig.append(qMakePair(ByteArray("HiddenServiceDir"), dir.absolutePath().toLocal8Bit()));
const QList<HiddenService::Target> &targets = service->targets();
for (QList<HiddenService::Target>::ConstIterator tit = targets.begin(); tit != targets.end(); ++tit)
const std::list<HiddenService::Target> &targets = service->targets();
for (auto tit:targets)
{
QString target = QString::fromLatin1("%1 %2:%3").arg(tit->servicePort)
.arg(tit->targetAddress.toString())
.arg(tit->targetPort);
torConfig.append(qMakePair(ByteArray("HiddenServicePort"), target.toLatin1()));
std::string target = RsUtil::NumberToString(tit.servicePort) + " "
+tit.targetAddress + ":"
+RsUtil::NumberToString(tit.targetPort);
torConfig.append(qMakePair(ByteArray("HiddenServicePort"), target));
}
QObject::connect(command, &SetConfCommand::setConfSucceeded, service, &HiddenService::servicePublished);
}
if (!torConfig.isEmpty())
if (!torConfig.empty())
socket->sendCommand(command, command->build(torConfig));
}
}
@ -644,34 +647,41 @@ void TorControlPrivate::statusEvent(int code, const ByteArray &data)
{
Q_UNUSED(code);
QList<ByteArray> tokens = splitQuotedStrings(data.trimmed(), ' ');
std::list<ByteArray> tokens = splitQuotedStrings(data.trimmed(), ' ');
if (tokens.size() < 3)
return;
torCtrlDebug() << "torctrl: status event:" << QString(data.trimmed()).toStdString() << std::endl;
torCtrlDebug() << "torctrl: status event:" << data.trimmed().toString() << std::endl;
const ByteArray& tok2 = *(++tokens.begin());
if (tokens[2] == "CIRCUIT_ESTABLISHED") {
if (tok2 == "CIRCUIT_ESTABLISHED") {
setTorStatus(TorControl::TorReady);
} else if (tokens[2] == "CIRCUIT_NOT_ESTABLISHED") {
} else if (tok2 == "CIRCUIT_NOT_ESTABLISHED") {
setTorStatus(TorControl::TorOffline);
} else if (tokens[2] == "BOOTSTRAP") {
tokens.takeFirst();
} else if (tok2 == "BOOTSTRAP") {
tokens.pop_front();
updateBootstrap(tokens);
}
}
void TorControlPrivate::updateBootstrap(const QList<ByteArray> &data)
void TorControlPrivate::updateBootstrap(const std::list<ByteArray> &data)
{
bootstrapStatus.clear();
// WARN or NOTICE
bootstrapStatus[QStringLiteral("severity")] = data.value(0);
for (int i = 1; i < data.size(); i++) {
int equals = data[i].indexOf('=');
QString key = QString::fromLatin1(data[i].mid(0, equals));
QString value;
bootstrapStatus["severity"] = (*data.begin()).toString();
auto dat = data.begin();
++dat;
for(;dat!=data.end();++dat) { // for(int i = 1; i < data.size(); i++) {
int equals = (*dat).indexOf('=');
ByteArray key = (*dat).mid(0, equals);
ByteArray value;
if (equals >= 0)
value = QString::fromLatin1(unquotedString(data[i].mid(equals + 1)));
bootstrapStatus[key.toLower()] = value;
value = unquotedString((*dat).mid(equals + 1));
bootstrapStatus[key.toLower().toString()] = value.toString();
}
//torCtrlDebug() << bootstrapStatus << std::endl;
@ -685,16 +695,16 @@ void TorControlPrivate::updateBootstrap(const QList<ByteArray> &data)
}
}
QObject *TorControl::getConfiguration(const QString &options)
QObject *TorControl::getConfiguration(const std::string& options)
{
GetConfCommand *command = new GetConfCommand(GetConfCommand::GetConf);
d->socket->sendCommand(command, command->build(options.toLatin1()));
d->socket->sendCommand(command, command->build(options));
//QQmlEngine::setObjectOwnership(command, QQmlEngine::CppOwnership);
return command;
}
QObject *TorControl::setConfiguration(const QVariantMap &options)
QObject *TorControl::setConfiguration(const std::list<std::pair<std::string,std::string> >& options)
{
SetConfCommand *command = new SetConfCommand;
command->setResetMode(true);
@ -721,7 +731,8 @@ public:
Q_ASSERT(!command);
command = new GetConfCommand(GetConfCommand::GetInfo);
QObject::connect(command, &TorControlCommand::finished, this, &SaveConfigOperation::configTextReply);
socket->sendCommand(command, command->build(QList<ByteArray>() << "config-text" << "config-file"));
socket->sendCommand(command, command->build(std::list<std::string> { "config-text" , "config-file" } ));
}
private slots:
@ -731,23 +742,29 @@ private slots:
if (!command)
return;
QString path = QFile::decodeName(command->get("config-file").toByteArray());
if (path.isEmpty()) {
finishWithError(QStringLiteral("Cannot write torrc without knowing its path"));
auto lpath = command->get("config-file");
std::string path = (lpath.empty()?std::string():lpath.front());
if (path.empty()) {
finishWithError("Cannot write torrc without knowing its path");
return;
}
// Out of paranoia, refuse to write any file not named 'torrc', or if the
// file doesn't exist
QFileInfo fileInfo(path);
if (fileInfo.fileName() != QStringLiteral("torrc") || !fileInfo.exists()) {
finishWithError(QStringLiteral("Refusing to write torrc to unacceptable path %1").arg(path));
auto filename = RsDirUtil::getFileName(path);
if(filename != "torrc" || !RsDirUtil::fileExists(path))
{
finishWithError("Refusing to write torrc to unacceptable path " + path);
return;
}
QSaveFile file(path);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
finishWithError(QStringLiteral("Failed opening torrc file for writing: %1").arg(file.errorString()));
std::ofstream file(path);
if (!file.is_open()) {
finishWithError("Failed opening torrc file for writing: permissions error?");
return;
}
@ -761,9 +778,11 @@ private slots:
0
};
QVariantList configText = command->get("config-text").toList();
foreach (const QVariant &value, configText) {
ByteArray line = value.toByteArray();
auto configText = command->get("config-text") ;
for(const auto& value: configText)
{
ByteArray line(value);
bool skip = false;
for (const char **key = bannedKeys; *key; key++) {
@ -775,14 +794,10 @@ private slots:
if (skip)
continue;
file.write(line);
file.write("\n");
file << line.toString() << std::endl;
}
if (!file.commit()) {
finishWithError(QStringLiteral("Failed writing torrc: %1").arg(file.errorString()));
return;
}
file.close();
torCtrlDebug() << "torctrl: Wrote torrc file" << std::endl;
finishWithSuccess();
@ -820,12 +835,12 @@ void TorControl::takeOwnership()
d->socket->sendCommand("TAKEOWNERSHIP\r\n");
// Reset PID-based polling
QVariantMap options;
options[QStringLiteral("__OwningControllerProcess")] = QVariant();
std::list<std::pair<std::string,std::string> > options;
options.push_back(std::make_pair("__OwningControllerProcess",std::string()));
setConfiguration(options);
}
bool TorControl::torVersionAsNewAs(const QString &match) const
bool TorControl::torVersionAsNewAs(const std::string& match) const
{
QRegularExpression r(QStringLiteral("[.-]"));
QStringList split = torVersion().split(r);

View File

@ -38,6 +38,7 @@
#include <QObject>
#include <QHostAddress>
#include "PendingOperation.h"
#include "bytearray.h"
class QNetworkProxy;
@ -86,9 +87,9 @@ public:
/* Information */
Status status() const;
TorStatus torStatus() const;
QString torVersion() const;
bool torVersionAsNewAs(const QString &version) const;
QString errorMessage() const;
std::string torVersion() const;
bool torVersionAsNewAs(const std::string &version) const;
std::string errorMessage() const;
bool hasConnectivity() const;
QHostAddress socksAddress() const;
@ -96,7 +97,7 @@ public:
QNetworkProxy connectionProxy();
/* Authentication */
void setAuthPassword(const QByteArray &password);
void setAuthPassword(const ByteArray& password);
/* Connection */
bool isConnected() const { return status() == Connected; }
@ -111,9 +112,9 @@ public:
QList<HiddenService*> hiddenServices() const;
void addHiddenService(HiddenService *service);
QVariantMap bootstrapStatus() const;
Q_INVOKABLE QObject *getConfiguration(const QString &options);
Q_INVOKABLE QObject *setConfiguration(const QVariantMap &options);
std::map<std::string, std::string> bootstrapStatus() const;
Q_INVOKABLE QObject *getConfiguration(const std::string &options);
Q_INVOKABLE QObject *setConfiguration(const std::list<std::pair<std::string, std::string> > &options);
Q_INVOKABLE PendingOperation *saveConfiguration();
signals:

View File

@ -49,24 +49,27 @@ TorControlSocket::~TorControlSocket()
clear();
}
void TorControlSocket::sendCommand(TorControlCommand *command, const QByteArray &data)
void TorControlSocket::sendCommand(TorControlCommand *command, const ByteArray &data)
{
Q_ASSERT(data.endsWith("\r\n"));
assert(data.endsWith(ByteArray("\r\n")));
commandQueue.push_back(command);
write(data);
std::cerr << "[TOR CTRL] Sent: \"" << QString(data.trimmed()).toStdString() << "\"" << std::endl;
std::cerr << "[TOR CTRL] Sent: \"" << data.trimmed().toString() << "\"" << std::endl;
}
void TorControlSocket::registerEvent(const QByteArray &event, TorControlCommand *command)
void TorControlSocket::registerEvent(const ByteArray &event, TorControlCommand *command)
{
eventCommands.insert(event, command);
eventCommands.insert(std::make_pair(event, command));
QByteArray data("SETEVENTS");
foreach (const QByteArray &key, eventCommands.keys()) {
ByteArray data("SETEVENTS");
for(auto it:eventCommands)
{
//const ByteArray &key, eventCommands.keys()) {
//data += key;
data += ' ';
data += key;
data += it.first;
}
data += "\r\n";
@ -96,9 +99,9 @@ void TorControlSocket::process()
if (!canReadLine())
return;
QByteArray line = readLine(5120);
if (!line.endsWith("\r\n")) {
setError(QStringLiteral("Invalid control message syntax"));
ByteArray line = readLine(5120);
if (!line.endsWith(ByteArray("\r\n"))) {
setError("Invalid control message syntax");
return;
}
line.chop(2);
@ -117,7 +120,7 @@ void TorControlSocket::process()
}
if (line.size() < 4) {
setError(QStringLiteral("Invalid control message syntax"));
setError("Invalid control message syntax");
return;
}
@ -130,7 +133,7 @@ void TorControlSocket::process()
line = line.mid(4);
if (!isFinalReply && !inDataReply && type != '-') {
setError(QStringLiteral("Invalid control message syntax"));
setError("Invalid control message syntax");
return;
}
@ -142,7 +145,7 @@ void TorControlSocket::process()
currentCommand = eventCommands.value(line.mid(0, space));
if (!currentCommand) {
qWarning() << "torctrl: Ignoring unknown event";
RsWarn() << "torctrl: Ignoring unknown event";
continue;
}
}
@ -155,19 +158,19 @@ void TorControlSocket::process()
continue;
}
if (commandQueue.isEmpty()) {
qWarning() << "torctrl: Received unexpected data";
if (commandQueue.empty()) {
RsWarn() << "torctrl: Received unexpected data";
continue;
}
TorControlCommand *command = commandQueue.first();
TorControlCommand *command = commandQueue.front();
if (command)
command->onReply(statusCode, line);
if (inDataReply) {
currentCommand = command;
} else if (isFinalReply) {
commandQueue.takeFirst();
commandQueue.pop_front();
if (command) {
command->onFinished(statusCode);
command->deleteLater();

View File

@ -33,6 +33,7 @@
#pragma once
#include "pqi/rstcpsocket.h"
#include "bytearray.h"
namespace Tor
{
@ -47,10 +48,10 @@ public:
std::string errorMessage() const { return m_errorMessage; }
void registerEvent(const QByteArray &event, TorControlCommand *handler);
void registerEvent(const ByteArray &event, TorControlCommand *handler);
void sendCommand(const std::string& data) { sendCommand(0, data); }
void sendCommand(TorControlCommand *command, const QByteArray &data);
void sendCommand(TorControlCommand *command, const ByteArray &data);
signals:
void error(const QString &message);
@ -61,7 +62,7 @@ private slots:
private:
std::list<TorControlCommand*> commandQueue;
QHash<QByteArray,TorControlCommand*> eventCommands;
std::map<ByteArray,TorControlCommand*> eventCommands;
std::string m_errorMessage;
TorControlCommand *currentCommand;
bool inDataReply;
@ -70,5 +71,3 @@ private:
};
}
#endif // TORCONTROLSOCKET_H

View File

@ -31,6 +31,7 @@
*/
#include <iostream>
#include <fstream>
// This works on linux only. I have no clue how to do that on windows. Anyway, this
// is only needed for an assert that should normaly never be triggered.
@ -67,25 +68,25 @@ public:
TorManager *q;
TorProcess *process;
TorControl *control;
QString dataDir;
QString hiddenServiceDir;
QStringList logMessages;
QString errorMessage;
std::string dataDir;
std::string hiddenServiceDir;
std::list<std::string> logMessages;
std::string errorMessage;
bool configNeeded;
HiddenService *hiddenService ;
explicit TorManagerPrivate(TorManager *parent = 0);
QString torExecutablePath() const;
bool createDataDir(const QString &path);
bool createDefaultTorrc(const QString &path);
std::string torExecutablePath() const;
bool createDataDir(const std::string &path);
bool createDefaultTorrc(const std::string &path);
void setError(const QString &errorMessage);
void setError(const std::string &errorMessage);
virtual void processStateChanged(int state) override;
virtual void processErrorChanged(const QString &errorMessage) override;
virtual void processLogMessage(const QString &message) override;
virtual void processErrorChanged(const std::string &errorMessage) override;
virtual void processLogMessage(const std::string &message) override;
public slots:
void controlStatusChanged(int status);
@ -128,12 +129,12 @@ TorProcess *TorManager::process()
return d->process;
}
QString TorManager::torDataDirectory() const
std::string TorManager::torDataDirectory() const
{
return d->dataDir;
}
void TorManager::setTorDataDirectory(const QString &path)
void TorManager::setTorDataDirectory(const std::string &path)
{
d->dataDir = QDir::fromNativeSeparators(path);
@ -141,16 +142,16 @@ void TorManager::setTorDataDirectory(const QString &path)
d->dataDir.append(QLatin1Char('/'));
}
QString TorManager::hiddenServiceDirectory() const
std::string TorManager::hiddenServiceDirectory() const
{
return d->hiddenServiceDir;
}
void TorManager::setHiddenServiceDirectory(const QString &path)
void TorManager::setHiddenServiceDirectory(const std::string &path)
{
d->hiddenServiceDir = QDir::fromNativeSeparators(path);
if (!d->hiddenServiceDir.isEmpty() && !d->hiddenServiceDir.endsWith(QLatin1Char('/')))
d->hiddenServiceDir.append(QLatin1Char('/'));
if (!d->hiddenServiceDir.empty() && !(d->hiddenServiceDir.back() == '/'))
d->hiddenServiceDir += '/';
}
bool TorManager::setupHiddenService()
@ -161,34 +162,34 @@ bool TorManager::setupHiddenService()
return true ;
}
QString keyData ;//= m_settings->read("serviceKey").toString();
QString legacyDir = d->hiddenServiceDir;
std::string keyData ;//= m_settings->read("serviceKey").toString();
std::string legacyDir = d->hiddenServiceDir;
std::cerr << "TorManager: setting up hidden service." << std::endl;
if(legacyDir.isNull())
if(legacyDir.empty())
{
std::cerr << "legacy dir not set! Cannot proceed." << std::endl;
return false ;
}
std::cerr << "Using legacy dir: " << legacyDir.toStdString() << std::endl;
std::cerr << "Using legacy dir: " << legacyDir << std::endl;
if (!legacyDir.isEmpty() && QFile::exists(legacyDir + QLatin1String("/private_key")))
if (!legacyDir.empty() && QFile::exists(legacyDir.c_str() + QLatin1String("/private_key")))
{
std::cerr << "Attempting to load key from legacy filesystem format in " << legacyDir.toStdString() << std::endl;
std::cerr << "Attempting to load key from legacy filesystem format in " << legacyDir << std::endl;
CryptoKey key;
if (!key.loadFromFile(legacyDir + QLatin1String("/private_key")))
if (!key.loadFromFile(legacyDir + "/private_key"))
{
qWarning() << "Cannot load legacy format key from" << legacyDir << "for conversion";
RsWarn() << "Cannot load legacy format key from" << legacyDir << "for conversion";
return false;
}
d->hiddenService = new Tor::HiddenService(this,key, legacyDir);
std::cerr << "Got key from legacy dir: " << std::endl;
std::cerr << key.bytes().toStdString() << std::endl;
std::cerr << key.bytes().toHex().toString() << std::endl;
}
else
{
@ -239,11 +240,9 @@ void TorManager::hiddenServicePrivateKeyChanged()
if(!d->hiddenService)
return ;
QString key = QString::fromLatin1(d->hiddenService->privateKey().bytes());
std::string key = d->hiddenService->privateKey().bytes().toString();
QFile outfile(d->hiddenServiceDir + QLatin1String("/private_key")) ;
outfile.open( QIODevice::WriteOnly | QIODevice::Text );
QTextStream s(&outfile);
std::ofstream s(d->hiddenServiceDir + "/private_key");
#ifdef TO_REMOVE
s << "-----BEGIN RSA PRIVATE KEY-----" << endl;
@ -255,10 +254,10 @@ void TorManager::hiddenServicePrivateKeyChanged()
#endif
s << key ;
outfile.close();
s.close();
std::cerr << "Hidden service private key changed!" << std::endl;
std::cerr << key.toStdString() << std::endl;
std::cerr << key << std::endl;
}
void TorManager::hiddenServiceHostnameChanged()
@ -270,7 +269,7 @@ void TorManager::hiddenServiceHostnameChanged()
outfile2.open( QIODevice::WriteOnly | QIODevice::Text );
QTextStream t(&outfile2);
QString hostname(d->hiddenService->hostname());
std::string hostname(d->hiddenService->hostname());
t << hostname << endl;
outfile2.close();
@ -283,7 +282,7 @@ bool TorManager::configurationNeeded() const
return d->configNeeded;
}
QStringList TorManager::logMessages() const
std::string TorManager::logMessages() const
{
return d->logMessages;
}
@ -293,7 +292,7 @@ bool TorManager::hasError() const
return !d->errorMessage.isEmpty();
}
QString TorManager::errorMessage() const
std::string TorManager::errorMessage() const
{
return d->errorMessage;
}
@ -306,7 +305,7 @@ bool TorManager::start()
//emit errorChanged(); // not needed because there's no error to handle
}
SettingsObject settings(QStringLiteral("tor"));
SettingsObject settings("tor");
// If a control port is defined by config or environment, skip launching tor
if (!settings.read("controlPort").isUndefined() ||
@ -317,7 +316,7 @@ bool TorManager::start()
QByteArray password = settings.read("controlPassword").toString().toLatin1();
if (!qEnvironmentVariableIsEmpty("TOR_CONTROL_HOST"))
address = QHostAddress(QString::fromLatin1(qgetenv("TOR_CONTROL_HOST")));
address = QHostAddress(qgetenv("TOR_CONTROL_HOST"));
if (!qEnvironmentVariableIsEmpty("TOR_CONTROL_PORT")) {
bool ok = false;
@ -330,7 +329,7 @@ bool TorManager::start()
password = qgetenv("TOR_CONTROL_PASSWD");
if (!port) {
d->setError(QStringLiteral("Invalid control port settings from environment or configuration"));
d->setError("Invalid control port settings from environment or configuration");
return false;
}
@ -341,12 +340,12 @@ bool TorManager::start()
d->control->connect(address, port);
} else {
// Launch a bundled Tor instance
QString executable = d->torExecutablePath();
std::string executable = d->torExecutablePath();
std::cerr << "Executable path: " << executable.toStdString() << std::endl;
if (executable.isEmpty()) {
d->setError(QStringLiteral("Cannot find tor executable"));
d->setError("Cannot find tor executable");
return false;
}
@ -354,22 +353,23 @@ bool TorManager::start()
d->process = new TorProcess(d);
// QObject::connect(d->process, SIGNAL(stateChanged(int)), d, SLOT(processStateChanged(int)));
// QObject::connect(d->process, SIGNAL(errorMessageChanged(QString)), d, SLOT(processErrorChanged(QString)));
// QObject::connect(d->process, SIGNAL(logMessage(QString)), d, SLOT(processLogMessage(QString)));
// QObject::connect(d->process, SIGNAL(errorMessageChanged(std::string)), d, SLOT(processErrorChanged(std::string)));
// QObject::connect(d->process, SIGNAL(logMessage(std::string)), d, SLOT(processLogMessage(std::string)));
}
if (!QFile::exists(d->dataDir) && !d->createDataDir(d->dataDir)) {
d->setError(QStringLiteral("Cannot write data location: %1").arg(d->dataDir));
d->setError(std::string("Cannot write data location: ") + d->dataDir);
return false;
}
QString defaultTorrc = d->dataDir + QStringLiteral("default_torrc");
if (!QFile::exists(defaultTorrc) && !d->createDefaultTorrc(defaultTorrc)) {
d->setError(QStringLiteral("Cannot write data files: %1").arg(defaultTorrc));
std::string defaultTorrc = d->dataDir + "default_torrc";
if (!QFile::exists(defaultTorrc) && !d->createDefaultTorrc(defaultTorrc))
{
d->setError("Cannot write data files: ")+defaultTorrc);
return false;
}
QFile torrc(d->dataDir + QStringLiteral("torrc"));
QFile torrc(d->dataDir + "torrc");
if (!torrc.exists() || torrc.size() == 0) {
d->configNeeded = true;
@ -403,7 +403,7 @@ bool TorManager::getProxyServerInfo(QHostAddress& proxy_server_adress,uint16_t&
return proxy_server_port > 1023 ;
}
bool TorManager::getHiddenServiceInfo(QString& service_id,QString& service_onion_address,uint16_t& service_port, QHostAddress& service_target_address,uint16_t& target_port)
bool TorManager::getHiddenServiceInfo(std::string& service_id,std::string& service_onion_address,uint16_t& service_port, QHostAddress& service_target_address,uint16_t& target_port)
{
QList<Tor::HiddenService*> hidden_services = control()->hiddenServices();
@ -431,7 +431,7 @@ bool TorManager::getHiddenServiceInfo(QString& service_id,QString& service_onion
void TorManagerPrivate::processStateChanged(int state)
{
std::cerr << Q_FUNC_INFO << "state: " << state << " passwd=\"" << QString(process->controlPassword()).toStdString() << "\" " << process->controlHost().toString().toStdString()
std::cerr << Q_FUNC_INFO << "state: " << state << " passwd=\"" << std::string(process->controlPassword()).toStdString() << "\" " << process->controlHost().toString().toStdString()
<< ":" << process->controlPort() << std::endl;
if (state == TorProcess::Ready) {
control->setAuthPassword(process->controlPassword());
@ -439,18 +439,18 @@ void TorManagerPrivate::processStateChanged(int state)
}
}
void TorManagerPrivate::processErrorChanged(const QString &errorMessage)
void TorManagerPrivate::processErrorChanged(const std::string &errorMessage)
{
std::cerr << "tor error:" << errorMessage.toStdString() << std::endl;
std::cerr << "tor error:" << errorMessage << std::endl;
setError(errorMessage);
}
void TorManagerPrivate::processLogMessage(const QString &message)
void TorManagerPrivate::processLogMessage(const std::string &message)
{
std::cerr << "tor:" << message.toStdString() << std::endl;
std::cerr << "tor:" << message << std::endl;
if (logMessages.size() >= 50)
logMessages.takeFirst();
logMessages.append(message);
logMessages.pop_front();
logMessages.push_back(message);
}
void TorManagerPrivate::controlStatusChanged(int status)
@ -458,7 +458,7 @@ void TorManagerPrivate::controlStatusChanged(int status)
if (status == TorControl::Connected) {
if (!configNeeded) {
// If DisableNetwork is 1, trigger configurationNeeded
connect(control->getConfiguration(QStringLiteral("DisableNetwork")),
connect(control->getConfiguration("DisableNetwork"),
SIGNAL(finished()), SLOT(getConfFinished()));
}
@ -488,18 +488,18 @@ void TorManagerPrivate::getConfFinished()
}
}
QString TorManagerPrivate::torExecutablePath() const
std::string TorManagerPrivate::torExecutablePath() const
{
SettingsObject settings(QStringLiteral("tor"));
QString path = settings.read("executablePath").toString();
SettingsObject settings("tor");
std::string path = settings.read("executablePath").toString();
if (!path.isEmpty() && QFile::exists(path))
return path;
#ifdef Q_OS_WIN
QString filename(QStringLiteral("/tor/tor.exe"));
std::string filename("/tor/tor.exe");
#else
QString filename(QStringLiteral("/tor"));
std::string filename("/tor");
#endif
path = qApp->applicationDirPath();
@ -508,7 +508,7 @@ QString TorManagerPrivate::torExecutablePath() const
return path + filename;
#ifdef BUNDLED_TOR_PATH
path = QStringLiteral(BUNDLED_TOR_PATH);
path = BUNDLED_TOR_PATH;
if (QFile::exists(path + filename))
return path + filename;
#endif
@ -516,7 +516,7 @@ QString TorManagerPrivate::torExecutablePath() const
#ifdef __APPLE__
// on MacOS, try traditional brew installation path
path = QStringLiteral("/usr/local/opt/tor/bin") ;
path = "/usr/local/opt/tor/bin" ;
if (QFile::exists(path + filename))
return path + filename;
@ -526,13 +526,13 @@ QString TorManagerPrivate::torExecutablePath() const
return filename.mid(1);
}
bool TorManagerPrivate::createDataDir(const QString &path)
bool TorManagerPrivate::createDataDir(const std::string &path)
{
QDir dir(path);
return dir.mkpath(QStringLiteral("."));
return dir.mkpath(".");
}
bool TorManagerPrivate::createDefaultTorrc(const QString &path)
bool TorManagerPrivate::createDefaultTorrc(const std::string &path)
{
static const char defaultTorrcContent[] =
"SocksPort auto\n"
@ -548,7 +548,7 @@ bool TorManagerPrivate::createDefaultTorrc(const QString &path)
return true;
}
void TorManagerPrivate::setError(const QString &message)
void TorManagerPrivate::setError(const std::string &message)
{
errorMessage = message;
@ -557,7 +557,7 @@ void TorManagerPrivate::setError(const QString &message)
auto ev = std::make_shared<RsTorManagerEvent>();
ev->mTorManagerEventType = RsTorManagerEventCode::TOR_MANAGER_ERROR;
ev->mErrorMessage = message.toStdString();
ev->mErrorMessage = message;
rsEvents->sendEvent(ev);
}
//emit q->errorChanged();
@ -567,7 +567,7 @@ void TorManagerPrivate::setError(const QString &message)
bool RsTor::isTorAvailable()
{
return !instance()->d->torExecutablePath().isNull();
return !instance()->d->torExecutablePath().empty();
}
bool RsTor::getHiddenServiceInfo(std::string& service_id,
@ -576,15 +576,15 @@ bool RsTor::getHiddenServiceInfo(std::string& service_id,
std::string& service_target_address,
uint16_t& target_port)
{
QString sid;
QString soa;
std::string sid;
std::string soa;
QHostAddress sta;
if(!instance()->getHiddenServiceInfo(sid,soa,service_port,sta,target_port))
return false;
service_id = sid.toStdString();
service_onion_address = soa.toStdString();
service_id = sid;
service_onion_address = soa;
service_target_address = sta.toString().toStdString();
return true;
@ -592,13 +592,7 @@ bool RsTor::getHiddenServiceInfo(std::string& service_id,
std::list<std::string> RsTor::logMessages()
{
QStringList qs = instance()->logMessages();
std::list<std::string> s;
for(auto& ss:qs)
s.push_back(ss.toStdString());
return s;
return instance()->logMessages();
}
std::string RsTor::socksAddress()
@ -652,7 +646,7 @@ RsTorHiddenServiceStatus RsTor::getHiddenServiceStatus(std::string& service_id)
if(list.empty())
return RsTorHiddenServiceStatus::NOT_CREATED;
service_id = (*list.begin())->serviceId().toStdString();
service_id = (*list.begin())->serviceId();
switch((*list.begin())->status())
{
@ -680,7 +674,7 @@ bool RsTor::hasError()
}
std::string RsTor::errorMessage()
{
return instance()->errorMessage().toStdString();
return instance()->errorMessage();
}
void RsTor::getProxyServerInfo(std::string& server_address, uint16_t& server_port)
@ -698,11 +692,11 @@ bool RsTor::start()
void RsTor::setTorDataDirectory(const std::string& dir)
{
instance()->setTorDataDirectory(QString::fromStdString(dir));
instance()->setTorDataDirectory(dir);
}
void RsTor::setHiddenServiceDirectory(const std::string& dir)
{
instance()->setHiddenServiceDirectory(QString::fromStdString(dir));
instance()->setHiddenServiceDirectory(dir);
}
TorManager *RsTor::instance()

View File

@ -38,7 +38,6 @@
#include "retroshare/rstor.h"
#include "HiddenService.h"
#include <QStringList>
#include <QHostAddress>
namespace Tor
@ -70,11 +69,11 @@ public:
TorControl *control();
QString torDataDirectory() const;
void setTorDataDirectory(const QString &path);
std::string torDataDirectory() const;
void setTorDataDirectory(const std::string &path);
QString hiddenServiceDirectory() const;
void setHiddenServiceDirectory(const QString &path);
std::string hiddenServiceDirectory() const;
void setHiddenServiceDirectory(const std::string &path);
// Starts a hidden service, loading it from the config directory that has been set earlier.
bool setupHiddenService() ;
@ -82,12 +81,12 @@ public:
// True on first run or when the Tor configuration wizard needs to be shown
bool configurationNeeded() const;
QStringList logMessages() const;
std::list<std::string> logMessages() const;
bool hasError() const;
QString errorMessage() const;
std::string errorMessage() const;
bool getHiddenServiceInfo(QString& service_id,QString& service_onion_address,uint16_t& service_port, QHostAddress& service_target_address,uint16_t& target_port);
bool getHiddenServiceInfo(std::string& service_id,std::string& service_onion_address,uint16_t& service_port, QHostAddress& service_target_address,uint16_t& target_port);
bool getProxyServerInfo(QHostAddress& proxy_server_adress,uint16_t& proxy_server_port);
//public slots:

View File

@ -30,6 +30,12 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include "util/rsdir.h"
#include "TorProcess_p.h"
#include "CryptoKey.h"
#include "SecureRNG.h"
@ -64,42 +70,42 @@ TorProcessPrivate::TorProcessPrivate(TorProcess *q)
connect(&controlPortTimer, &QTimer::timeout, this, &TorProcessPrivate::tryReadControlPort);
}
QString TorProcess::executable() const
std::string TorProcess::executable() const
{
return d->executable;
}
void TorProcess::setExecutable(const QString &path)
void TorProcess::setExecutable(const std::string &path)
{
d->executable = path;
}
QString TorProcess::dataDir() const
std::string TorProcess::dataDir() const
{
return d->dataDir;
}
void TorProcess::setDataDir(const QString &path)
void TorProcess::setDataDir(const std::string &path)
{
d->dataDir = path;
}
QString TorProcess::defaultTorrc() const
std::string TorProcess::defaultTorrc() const
{
return d->defaultTorrc;
}
void TorProcess::setDefaultTorrc(const QString &path)
void TorProcess::setDefaultTorrc(const std::string &path)
{
d->defaultTorrc = path;
}
QStringList TorProcess::extraSettings() const
std::list<std::string> TorProcess::extraSettings() const
{
return d->extraSettings;
}
void TorProcess::setExtraSettings(const QStringList &settings)
void TorProcess::setExtraSettings(const std::list<std::string> &settings)
{
d->extraSettings = settings;
}
@ -109,7 +115,7 @@ TorProcess::State TorProcess::state() const
return d->state;
}
QString TorProcess::errorMessage() const
std::string TorProcess::errorMessage() const
{
return d->errorMessage;
}
@ -121,8 +127,8 @@ void TorProcess::start()
d->errorMessage.clear();
if (d->executable.isEmpty() || d->dataDir.isEmpty()) {
d->errorMessage = QStringLiteral("Tor executable and data directory not specified");
if (d->executable.empty() || d->dataDir.empty()) {
d->errorMessage = "Tor executable and data directory not specified";
d->state = Failed;
if(m_client) m_client->processStateChanged(d->state); // emit stateChanged(d->state);
@ -137,32 +143,50 @@ void TorProcess::start()
return;
}
QByteArray password = controlPassword();
QByteArray hashedPassword = torControlHashedPassword(password);
if (password.isEmpty() || hashedPassword.isEmpty()) {
d->errorMessage = QStringLiteral("Random password generation failed");
ByteArray password = controlPassword();
ByteArray hashedPassword = torControlHashedPassword(password);
if (password.empty() || hashedPassword.empty()) {
d->errorMessage = "Random password generation failed";
d->state = Failed;
if(m_client) m_client->processErrorChanged(d->errorMessage);// emit errorMessageChanged(d->errorMessage);
if(m_client) m_client->processStateChanged(d->state); // emit stateChanged(d->state);
}
QStringList args;
if (!d->defaultTorrc.isEmpty())
args << QStringLiteral("--defaults-torrc") << d->defaultTorrc;
args << QStringLiteral("-f") << d->torrcPath();
args << QStringLiteral("DataDirectory") << d->dataDir;
args << QStringLiteral("HashedControlPassword") << QString::fromLatin1(hashedPassword);
args << QStringLiteral("ControlPort") << QStringLiteral("auto");
args << QStringLiteral("ControlPortWriteToFile") << d->controlPortFilePath();
args << QStringLiteral("__OwningControllerProcess") << QString::number(qApp->applicationPid());
args << d->extraSettings;
std::list<std::string> args;
if (!d->defaultTorrc.empty())
{
args.push_back("--defaults-torrc");
args.push_back(d->defaultTorrc);
}
args.push_back("-f");
args.push_back(d->torrcPath());
args.push_back("DataDirectory") ;
args.push_back(d->dataDir);
args.push_back("HashedControlPassword") ;
args.push_back(hashedPassword.toString());
args.push_back("ControlPort") ;
args.push_back("auto");
args.push_back("ControlPortWriteToFile");
args.push_back(d->controlPortFilePath());
args.push_back("__OwningControllerProcess") ;
args.push_back(RsUtil::NumberToString(getpid()));
for(auto s:d->extraSettings)
args.push_back(s);
d->state = Starting;
if(m_client) m_client->processStateChanged(d->state);// emit stateChanged(d->state);
if (QFile::exists(d->controlPortFilePath()))
QFile::remove(d->controlPortFilePath());
if (RsDirUtil::fileExists(d->controlPortFilePath()))
RsDirUtil::removeFile(d->controlPortFilePath());
d->controlPort = 0;
d->controlHost.clear();
@ -204,21 +228,22 @@ void TorProcess::stateChanged(int newState)
if(m_client)
m_client->processStateChanged(newState);
}
void TorProcess::errorMessageChanged(const QString &errorMessage)
void TorProcess::errorMessageChanged(const std::string& errorMessage)
{
if(m_client)
m_client->processErrorChanged(errorMessage);
}
void TorProcess::logMessage(const QString &message)
void TorProcess::logMessage(const std::string& message)
{
if(m_client)
m_client->processLogMessage(message);
}
QByteArray TorProcess::controlPassword()
ByteArray TorProcess::controlPassword()
{
if (d->controlPassword.isEmpty())
d->controlPassword = SecureRNG::randomPrintable(16);
if (d->controlPassword.empty())
d->controlPassword = RsRandom::printable(16);
return d->controlPassword;
}
@ -234,29 +259,34 @@ quint16 TorProcess::controlPort()
bool TorProcessPrivate::ensureFilesExist()
{
QFile torrc(torrcPath());
if (!torrc.exists()) {
QDir dir(dataDir);
if (!dir.exists() && !dir.mkpath(QStringLiteral("."))) {
errorMessage = QStringLiteral("Cannot create Tor data directory: %1").arg(dataDir);
return false;
}
if(!RsDirUtil::checkCreateDirectory(dataDir))
{
errorMessage = "Cannot create Tor data directory: " + dataDir;
return false;
}
if (!torrc.open(QIODevice::ReadWrite)) {
errorMessage = QStringLiteral("Cannot create Tor configuration file: %1").arg(torrcPath());
if (!RsDirUtil::fileExists(torrcPath()))
{
FILE *f = RsDirUtil::rs_fopen(torrcPath().c_str(),"w");
if(!f)
{
errorMessage = "Cannot create Tor configuration file: " + torrcPath();
return false;
}
else
fclose(f);
}
return true;
}
QString TorProcessPrivate::torrcPath() const
std::string TorProcessPrivate::torrcPath() const
{
return QDir::toNativeSeparators(dataDir) + QDir::separator() + QStringLiteral("torrc");
}
QString TorProcessPrivate::controlPortFilePath() const
std::string TorProcessPrivate::controlPortFilePath() const
{
return QDir::toNativeSeparators(dataDir) + QDir::separator() + QStringLiteral("control-port");
}
@ -278,9 +308,11 @@ void TorProcessPrivate::processFinished()
return;
controlPortTimer.stop();
errorMessage = process.errorString();
if (errorMessage.isEmpty())
errorMessage = QStringLiteral("Process exited unexpectedly (code %1)").arg(process.exitCode());
errorMessage = process.errorString().toStdString();
if (errorMessage.empty())
errorMessage = "Process exited unexpectedly (code " + RsUtil::NumberToString(process.exitCode()) + ")";
state = TorProcess::Failed;
/*emit*/ q->errorMessageChanged(errorMessage);
/*emit*/ q->stateChanged(state);
@ -294,22 +326,30 @@ void TorProcessPrivate::processError(QProcess::ProcessError error)
void TorProcessPrivate::processReadable()
{
while (process.bytesAvailable() > 0) {
QByteArray line = process.readLine(2048).trimmed();
if (!line.isEmpty())
/*emit*/ q->logMessage(QString::fromLatin1(line));
while (process.bytesAvailable() > 0)
{
ByteArray line = process.readLine(2048).trimmed();
if (!line.empty())
/*emit*/ q->logMessage(line.toString()));
}
}
void TorProcessPrivate::tryReadControlPort()
{
QFile file(controlPortFilePath());
if (file.open(QIODevice::ReadOnly)) {
QByteArray data = file.readLine().trimmed();
FILE *file = RsDirUtil::rs_fopen(controlPortFilePath().c_str(),"r");
if(file)
{
char *line = nullptr;
size_t size = getline(&line,0,file);
ByteArray data = ByteArray((unsigned char*)line,size).trimmed();
free(line);
int p;
if (data.startsWith("PORT=") && (p = data.lastIndexOf(':')) > 0) {
controlHost = QHostAddress(QString::fromLatin1(data.mid(5, p - 5)));
controlHost = QHostAddress(data.mid(5, p - 5));
controlPort = data.mid(p+1).toUShort();
if (!controlHost.isNull() && controlPort > 0) {
@ -322,7 +362,7 @@ void TorProcessPrivate::tryReadControlPort()
}
if (++controlPortAttempts * controlPortTimer.interval() > 10000) {
errorMessage = QStringLiteral("No control port available after launching process");
errorMessage = "No control port available after launching process";
state = TorProcess::Failed;
/*emit*/ q->errorMessageChanged(errorMessage);
/*emit*/ q->stateChanged(state);

View File

@ -36,6 +36,8 @@
#include <QObject>
#include <QHostAddress>
#include "bytearray.h"
namespace Tor
{
@ -47,8 +49,8 @@ class TorProcessClient
{
public:
virtual void processStateChanged(int) = 0;
virtual void processErrorChanged(const QString&) = 0;
virtual void processLogMessage(const QString&) = 0;
virtual void processErrorChanged(const std::string&) = 0;
virtual void processLogMessage(const std::string&) = 0;
};
/* Launches and controls a Tor instance with behavior suitable for bundling
@ -59,7 +61,7 @@ class TorProcess
//Q_ENUMS(State)
//Q_PROPERTY(State state READ state NOTIFY stateChanged)
//Q_PROPERTY(QString errorMessage READ errorMessage NOTIFY errorMessageChanged)
//Q_PROPERTY(std::string errorMessage READ errorMessage NOTIFY errorMessageChanged)
public:
enum State {
@ -73,28 +75,28 @@ public:
explicit TorProcess(TorProcessClient *client,QObject *parent = 0);
virtual ~TorProcess();
QString executable() const;
void setExecutable(const QString &path);
std::string executable() const;
void setExecutable(const std::string &path);
QString dataDir() const;
void setDataDir(const QString &path);
std::string dataDir() const;
void setDataDir(const std::string &path);
QString defaultTorrc() const;
void setDefaultTorrc(const QString &path);
std::string defaultTorrc() const;
void setDefaultTorrc(const std::string &path);
QStringList extraSettings() const;
void setExtraSettings(const QStringList &settings);
std::list<std::string> extraSettings() const;
void setExtraSettings(const std::list<std::string> &settings);
State state() const;
QString errorMessage() const;
std::string errorMessage() const;
QHostAddress controlHost();
quint16 controlPort();
QByteArray controlPassword();
ByteArray controlPassword();
//signals:
void stateChanged(int newState);
void errorMessageChanged(const QString &errorMessage);
void logMessage(const QString &message);
void errorMessageChanged(const std::string &errorMessage);
void logMessage(const std::string &message);
//public slots:
void start();

View File

@ -46,23 +46,23 @@ class TorProcessPrivate : public QObject
public:
TorProcess *q;
QProcess process;
QString executable;
QString dataDir;
QString defaultTorrc;
QStringList extraSettings;
std::string executable;
std::string dataDir;
std::string defaultTorrc;
std::list<std::string> extraSettings;
TorProcess::State state;
QString errorMessage;
std::string errorMessage;
QHostAddress controlHost;
quint16 controlPort;
QByteArray controlPassword;
ByteArray controlPassword;
QTimer controlPortTimer;
int controlPortAttempts;
TorProcessPrivate(TorProcess *q);
QString torrcPath() const;
QString controlPortFilePath() const;
std::string torrcPath() const;
std::string controlPortFilePath() const;
bool ensureFilesExist();
public slots:

View File

@ -1,8 +1,11 @@
#pragma once
#include <stdlib.h>
#include <string.h>
#include <string>
#include <vector>
#include <list>
#include "util/rsprint.h"
#include "util/rsdebug.h"
@ -32,8 +35,10 @@ public:
ByteArray& operator+=(const char *b) { for(uint32_t n=0;b[n]!=0;++n) push_back(b[n]); return *this;}
ByteArray left(uint32_t l) const { auto res = *this; res.resize(std::min((uint32_t)size(),l)); return res; }
ByteArray toUpper() const { auto res = *this; for(uint32_t i=0;i<size();++i) if( res[i]<='z' && res[i]>='a') res[i] += 'A'-'a'; return res; }
ByteArray toUpper() const { auto res = *this; for(uint32_t i=0;i<size();++i) if( res[i]<='z' && res[i]>='a') res[i] += int('A')-int('a'); return res; }
ByteArray toLower() const { auto res = *this; for(uint32_t i=0;i<size();++i) if( res[i]<='Z' && res[i]>='A') res[i] += int('a')-int('A'); return res; }
bool endsWidth(const ByteArray& b) const { return size() >= b.size() && !memcmp(&data()[size()-b.size()],b.data(),b.size()); }
bool startsWith(const char *b) const
{
for(uint32_t n=0;b[n]!=0;++n)
@ -88,4 +93,59 @@ public:
return res;
}
std::list<ByteArray> split(unsigned char sep)
{
std::list<ByteArray> res;
ByteArray current_block;
for(uint32_t i=0;i<size();++i)
if(operator[](i) == sep)
{
res.push_back(current_block);
current_block.clear();
}
else
current_block += operator[](i);
return res;
}
// Removes the following characters from the beginning and from the end of the array:
// '\t', '\n', '\v', '\f', '\r', and ' '.
ByteArray trimmed() const
{
auto res(*this);
while(!res.empty() && ( res.back() == '\t' || res.back() == '\n' || res.back() == '\v'
|| res.back() == '\f' || res.back() == '\r' || res.back() == ' ' ) )
res.pop_back();
uint32_t i=0;
for(;i<res.size();++i)
if(res[i] != '\t' && res[i] != '\n' && res[i] != '\v' && res[i] != '\f' && res[i] != '\r' && res[i] != ' ')
break;
return res.mid(i);
}
// Removes n bytes from the end of the array
void chop(uint32_t n)
{
resize(std::max(0,(int)size() - (int)n));
}
// Returns the last index of a given byte, -1 if not found.
int lastIndexOf(unsigned char s)
{
for(int i=size()-1;i>=0;--i)
if(operator[](i) == s)
return i;
return -1;
}
};

View File

@ -84,6 +84,25 @@ bool std::filesystem::create_directories(const std::string& path)
# include <filesystem>
#endif // __cplusplus < 201703L
bool RsDirUtil::fileExists(const std::string& file_path)
{
FILE *f = fopen(file_path.c_str(),"r");
if(!f)
return false;
fclose(f);
return true;
}
std::string RsDirUtil::getFileName(const std::string& full_file_path)
{
size_t n = full_file_path.find_last_of('/');
if(n == std::string::npos)
return full_file_path;
else
return full_file_path.substr(n+1);
}
std::string RsDirUtil::getTopDir(const std::string& dir)
{
std::string top;

View File

@ -63,12 +63,15 @@ std::string getRootDir(const std::string&);
std::string removeRootDir(const std::string& path);
void removeTopDir(const std::string& dir, std::string &path);
std::string removeRootDirs(const std::string& path, const std::string& root);
std::string getFileName(const std::string& full_file_path);
// Renames file from to file to. Files should be on the same file system.
// returns true if succeed, false otherwise.
bool renameFile(const std::string& from,const std::string& to) ;
//bool createBackup (const std::string& sFilename, unsigned int nCount = 5);
bool fileExists(const std::string& file_path);
// returns the CRC32 of the data of length len
//
uint32_t rs_CRC32(const unsigned char *data,uint32_t len) ;
@ -107,6 +110,12 @@ rstime_t lastWriteTime(
std::error_condition& errc = RS_DEFAULT_STORAGE_PARAM(std::error_condition) );
bool checkDirectory(const std::string& dir);
/*!
* \brief checkCreateDirectory
* \param dir
* \return false when the directory does not exist and could not be created.
*/
bool checkCreateDirectory(const std::string& dir);
// Removes all symbolic links along the path and computes the actual location of the file/dir passed as argument.