202 lines
6.5 KiB
C++
202 lines
6.5 KiB
C++
#include "install-i2p.h"
|
|
#include "fs-tools.h"
|
|
#include "network-downloader.h"
|
|
#include "prog-constains.h"
|
|
|
|
void addI2PDconfig (QString i2pdConf, QString tunnelsConf) {
|
|
#if defined(Q_OS_WIN)
|
|
#elif defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
|
|
#else
|
|
#endif
|
|
}
|
|
|
|
void configCheckAndMake () {
|
|
QString configsFolder = QDir(I2P_INSTALL_PATH).filePath("configs");
|
|
|
|
QString i2pdConf = QDir(configsFolder).filePath("i2pd.confconf");
|
|
QString tunnelsConf = QDir(configsFolder).filePath("tunnels.conf");
|
|
if (
|
|
!QFile(i2pdConf).exists() ||
|
|
!QFile(tunnelsConf).exists()
|
|
) {
|
|
qDebug() << "Configs not found. Creating new";
|
|
emptyFolder(configsFolder);
|
|
addI2PDconfig(i2pdConf, tunnelsConf);
|
|
}
|
|
}
|
|
|
|
bool checkI2P () {
|
|
QString I2P_VERSION = "i2pd version 2.59.0 (0.9.68)";
|
|
|
|
QProcess p;
|
|
p.start(QDir(I2P_INSTALL_PATH).filePath("i2pd"), {"--version"});
|
|
p.waitForFinished();
|
|
|
|
QString version = p.readAllStandardOutput();
|
|
bool isNeededVersion = version.contains(I2P_VERSION);
|
|
|
|
if (!isNeededVersion)
|
|
qDebug() << "current i2pd version:" << version;
|
|
return isNeededVersion;
|
|
}
|
|
|
|
bool installI2P(std::function<void(QString, unsigned int, unsigned int)> logCallback = nullptr) {
|
|
// Detect OS and architecture
|
|
QString i2pUrl; // https://github.com/PurpleI2P/i2pd/releases/tag/2.59.0
|
|
QString archiveType = "zip";
|
|
|
|
#if defined(Q_OS_WIN)
|
|
i2pUrl = "https://github.com/PurpleI2P/i2pd/releases/download/2.59.0/i2pd_2.59.0_win64_mingw.zip";
|
|
archiveType = "zip";
|
|
#elif defined(Q_OS_LINUX)
|
|
i2pUrl = "https://github.com/PurpleI2P/i2pd/archive/refs/tags/2.59.0.tar.gz";
|
|
archiveType = "tar.gz";
|
|
#elif defined(Q_OS_MACOS)
|
|
i2pUrl = "https://github.com/PurpleI2P/i2pd/releases/download/2.59.0/i2pd_2.59.0_osx.tar.gz";
|
|
archiveType = "tar.gz";
|
|
#endif
|
|
|
|
if (logCallback) logCallback("Creating directories...", 0, 0);
|
|
QDir tempDir(TEMP_PATH);
|
|
if (!tempDir.exists()) tempDir.mkpath(".");
|
|
QDir i2pDir(I2P_INSTALL_PATH);
|
|
if (!i2pDir.exists()) i2pDir.mkpath(".");
|
|
QString archivePath = tempDir.filePath(QFileInfo(QUrl(i2pUrl).path()).fileName());
|
|
|
|
// Download archive
|
|
bool isDownloaded = downloadFromUrl(i2pUrl, archivePath, logCallback);
|
|
if (!isDownloaded) return false;
|
|
|
|
// Extract archive
|
|
if (logCallback) logCallback("Extracting I2P archive...", 0, 0);
|
|
|
|
#if defined(Q_OS_WIN)
|
|
// TODO: Make it later
|
|
#elif defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
|
|
// Extract to temp folder first
|
|
QString tempExtractDir = QDir(TEMP_PATH).filePath("i2p_extract");
|
|
QDir().mkpath(tempExtractDir);
|
|
QProcess proc;
|
|
|
|
if (archiveType == "tar.gz") {
|
|
proc.start("tar", {"-xzf", archivePath, "-C", tempExtractDir});
|
|
} else if (archiveType == "zip") {
|
|
proc.start("unzip", {archivePath, "-d", tempExtractDir});
|
|
} else {
|
|
if (logCallback) logCallback("Unknown archive format", 0, 0);
|
|
return false;
|
|
}
|
|
proc.waitForFinished(-1);
|
|
|
|
// ### Build i2pd
|
|
if (logCallback) logCallback("Searching source directory...", 0, 4);
|
|
|
|
// Find extracted source dir (archive contains nested folder with Makefile)
|
|
QDir extractDir(tempExtractDir);
|
|
QString sourceDir;
|
|
|
|
for (const QFileInfo &entry : extractDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot)) {
|
|
QDir sub(entry.absoluteFilePath());
|
|
if (sub.exists("Makefile")) {
|
|
sourceDir = entry.absoluteFilePath();
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (sourceDir.isEmpty()) {
|
|
if (logCallback) logCallback("Failed to find source directory (Makefile missing)", 0, 0);
|
|
return false;
|
|
}
|
|
|
|
// ---- BUILD ----
|
|
if (logCallback) logCallback("Building i2pd...", 1, 4);
|
|
|
|
QProcess procBuild;
|
|
procBuild.setWorkingDirectory(sourceDir);
|
|
procBuild.setProcessChannelMode(QProcess::MergedChannels);
|
|
|
|
int cpuCount = QThread::idealThreadCount();
|
|
|
|
procBuild.start("bash", {"-c", QString("make -j%1").arg(cpuCount)});
|
|
|
|
if (!procBuild.waitForStarted()) {
|
|
if (logCallback) logCallback("Failed to start make", 0, 0);
|
|
return false;
|
|
}
|
|
|
|
while (procBuild.state() == QProcess::Running) {
|
|
procBuild.waitForReadyRead(100);
|
|
|
|
QByteArray out = procBuild.readAll();
|
|
if (!out.isEmpty() && logCallback) {
|
|
QString text = QString::fromLocal8Bit(out).trimmed();
|
|
if (!text.isEmpty())
|
|
logCallback(text, 1, 4);
|
|
}
|
|
}
|
|
|
|
procBuild.waitForFinished(-1);
|
|
|
|
if (procBuild.exitStatus() != QProcess::NormalExit || procBuild.exitCode() != 0) {
|
|
QString err = QString::fromLocal8Bit(procBuild.readAll());
|
|
if (logCallback) logCallback("Build failed: " + err + ", visit: " + WIKI_URL + "Build-I2P-on-Linux", 0, 0);
|
|
return false;
|
|
}
|
|
|
|
// ---- FIND BINARY ----
|
|
if (logCallback) logCallback("Locating built binary...", 2, 4);
|
|
|
|
QString binaryPath;
|
|
|
|
QDirIterator it(sourceDir, QDirIterator::Subdirectories);
|
|
while (it.hasNext()) {
|
|
QString path = it.next();
|
|
QFileInfo fi(path);
|
|
|
|
if (fi.isFile() && fi.fileName() == "i2pd") {
|
|
binaryPath = fi.absoluteFilePath();
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (binaryPath.isEmpty()) {
|
|
if (logCallback) logCallback("Built binary not found", 0, 0);
|
|
return false;
|
|
}
|
|
|
|
// ---- MOVE BINARY ----
|
|
if (logCallback) logCallback("Installing binary...", 3, 4);
|
|
|
|
QString destPath = QDir(I2P_INSTALL_PATH).filePath("i2pd");
|
|
|
|
QFile::remove(destPath);
|
|
|
|
if (!QFile::copy(binaryPath, destPath)) {
|
|
if (logCallback) logCallback("Failed to copy binary", 0, 0);
|
|
return false;
|
|
}
|
|
|
|
QFile::setPermissions(destPath,
|
|
QFile::permissions(destPath) |
|
|
QFileDevice::ExeOwner |
|
|
QFileDevice::ExeGroup |
|
|
QFileDevice::ExeOther);
|
|
|
|
if (logCallback) logCallback("I2P installation complete", 4, 4);
|
|
#endif
|
|
|
|
// ---- ADD CONFIGS ----
|
|
QString i2pdConfigsFolder = QDir(I2P_INSTALL_PATH).filePath("configs");
|
|
|
|
emptyFolder(QDir(I2P_INSTALL_PATH).filePath("data"));
|
|
emptyFolder(QDir(I2P_INSTALL_PATH).filePath("logs"));
|
|
emptyFolder(i2pdConfigsFolder);
|
|
|
|
addI2PDconfig(QDir(i2pdConfigsFolder).filePath("i2pd.conf"), QDir(i2pdConfigsFolder).filePath("tunnels.conf"));
|
|
|
|
// Check hash
|
|
QString hash = checkFileHash(QDir(I2P_INSTALL_PATH).filePath("i2pd"));
|
|
if (logCallback) logCallback("Total I2P installation hash: " + hash, 0, 0);
|
|
return true;
|
|
}
|