Allow overriding URL for downloading legacy FML libs (#4862)

This commit is contained in:
Alexandru Ionut Tripon 2026-01-27 16:48:01 +02:00 committed by GitHub
commit 915626de9d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 98 additions and 56 deletions

View file

@ -171,7 +171,7 @@ set(Launcher_NEWS_RSS_URL "https://prismlauncher.org/feed/feed.xml" CACHE STRING
set(Launcher_NEWS_OPEN_URL "https://prismlauncher.org/news" CACHE STRING "URL that gets opened when the user clicks 'More News'")
set(Launcher_HELP_URL "https://prismlauncher.org/wiki/help-pages/%1" CACHE STRING "URL (with arg %1 to be substituted with page-id) that gets opened when the user requests help")
set(Launcher_LOGIN_CALLBACK_URL "https://prismlauncher.org/successful-login" CACHE STRING "URL that gets opened when the user successfully logins.")
set(Launcher_FMLLIBS_BASE_URL "https://files.prismlauncher.org/fmllibs/" CACHE STRING "URL for FML Libraries.")
set(Launcher_LEGACY_FMLLIBS_BASE_URL "https://files.prismlauncher.org/fmllibs/" CACHE STRING "URL for legacy (<=1.5.2) FML Libraries.")
######## Set version numbers ########
set(Launcher_VERSION_MAJOR 10)

View file

@ -111,7 +111,7 @@ Config::Config()
MSA_CLIENT_ID = "@Launcher_MSA_CLIENT_ID@";
FLAME_API_KEY = "@Launcher_CURSEFORGE_API_KEY@";
META_URL = "@Launcher_META_URL@";
FMLLIBS_BASE_URL = "@Launcher_FMLLIBS_BASE_URL@";
LEGACY_FMLLIBS_BASE_URL = "@Launcher_LEGACY_FMLLIBS_BASE_URL@";
GLFW_LIBRARY_NAME = "@Launcher_GLFW_LIBRARY_NAME@";
OPENAL_LIBRARY_NAME = "@Launcher_OPENAL_LIBRARY_NAME@";

View file

@ -169,7 +169,7 @@ class Config {
QString DEFAULT_RESOURCE_BASE = "https://resources.download.minecraft.net/";
QString LIBRARY_BASE = "https://libraries.minecraft.net/";
QString IMGUR_BASE_URL = "https://api.imgur.com/3/";
QString FMLLIBS_BASE_URL;
QString LEGACY_FMLLIBS_BASE_URL;
QString TRANSLATION_FILES_URL;
QString MODPACKSCH_API_BASE_URL = "https://api.modpacks.ch/";

View file

@ -862,23 +862,20 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
}
}
{
auto resetIfInvalid = [this](const Setting* setting) {
if (const QUrl url(setting->get().toString()); !url.isValid() || (url.scheme() != "http" && url.scheme() != "https")) {
m_settings->reset(setting->id());
}
};
// Meta URL
m_settings->registerSetting("MetaURLOverride", "");
QUrl metaUrl(m_settings->get("MetaURLOverride").toString());
// get rid of invalid meta urls
if (!metaUrl.isValid() || (metaUrl.scheme() != "http" && metaUrl.scheme() != "https"))
m_settings->reset("MetaURLOverride");
resetIfInvalid(m_settings->registerSetting("MetaURLOverride", "").get());
// Resource URL
m_settings->registerSetting({ "ResourceURLOverride", "ResourceURL" }, "");
resetIfInvalid(m_settings->registerSetting({ "ResourceURLOverride", "ResourceURL" }, "").get());
QUrl resourceUrl(m_settings->get("ResourceURLOverride").toString());
// get rid of invalid resource urls
if (!resourceUrl.isValid() || (resourceUrl.scheme() != "http" && resourceUrl.scheme() != "https"))
m_settings->reset("ResourceURLOverride");
// Legacy FML libs URL
resetIfInvalid(m_settings->registerSetting("LegacyFMLLibsURLOverride", "").get());
}
m_settings->registerSetting("CloseAfterLaunch", false);

View file

@ -254,8 +254,8 @@ set(MINECRAFT_SOURCES
minecraft/update/AssetUpdateTask.h
minecraft/update/AssetUpdateTask.cpp
minecraft/update/FMLLibrariesTask.cpp
minecraft/update/FMLLibrariesTask.h
minecraft/update/LegacyFMLLibrariesTask.cpp
minecraft/update/LegacyFMLLibrariesTask.h
minecraft/update/FoldersTask.cpp
minecraft/update/FoldersTask.h
minecraft/update/LibrariesTask.cpp

View file

@ -45,7 +45,7 @@
#include "minecraft/launch/ExtractNatives.h"
#include "minecraft/launch/PrintInstanceInfo.h"
#include "minecraft/update/AssetUpdateTask.h"
#include "minecraft/update/FMLLibrariesTask.h"
#include "minecraft/update/LegacyFMLLibrariesTask.h"
#include "minecraft/update/LibrariesTask.h"
#include "settings/Setting.h"
#include "settings/SettingsObject.h"
@ -1113,7 +1113,7 @@ QList<LaunchStep::Ptr> MinecraftInstance::createUpdateTask()
// libraries download
makeShared<LibrariesTask>(this),
// FML libraries download and copy into the instance
makeShared<FMLLibrariesTask>(this),
makeShared<LegacyFMLLibrariesTask>(this),
// assets update
makeShared<AssetUpdateTask>(this),
};

View file

@ -1,4 +1,4 @@
#include "FMLLibrariesTask.h"
#include "LegacyFMLLibrariesTask.h"
#include "FileSystem.h"
#include "minecraft/MinecraftInstance.h"
@ -10,11 +10,11 @@
#include "net/ApiDownload.h"
FMLLibrariesTask::FMLLibrariesTask(MinecraftInstance* inst)
LegacyFMLLibrariesTask::LegacyFMLLibrariesTask(MinecraftInstance* inst)
{
m_inst = inst;
}
void FMLLibrariesTask::executeTask()
void LegacyFMLLibrariesTask::executeTask()
{
// Get the mod list
MinecraftInstance* inst = (MinecraftInstance*)m_inst;
@ -61,27 +61,28 @@ void FMLLibrariesTask::executeTask()
NetJob::Ptr dljob{ new NetJob("FML libraries", APPLICATION->network()) };
auto metacache = APPLICATION->metacache();
Net::Download::Options options = Net::Download::Option::MakeEternal;
const QString base = baseUrl();
for (auto& lib : fmlLibsToProcess) {
auto entry = metacache->resolveEntry("fmllibs", lib.filename);
QString urlString = BuildConfig.FMLLIBS_BASE_URL + lib.filename;
QString urlString = base + lib.filename;
dljob->addNetAction(Net::ApiDownload::makeCached(QUrl(urlString), entry, options));
}
connect(dljob.get(), &NetJob::succeeded, this, &FMLLibrariesTask::fmllibsFinished);
connect(dljob.get(), &NetJob::failed, this, &FMLLibrariesTask::fmllibsFailed);
connect(dljob.get(), &NetJob::succeeded, this, &LegacyFMLLibrariesTask::fmllibsFinished);
connect(dljob.get(), &NetJob::failed, this, &LegacyFMLLibrariesTask::fmllibsFailed);
connect(dljob.get(), &NetJob::aborted, this, [this] { emitFailed(tr("Aborted")); });
connect(dljob.get(), &NetJob::progress, this, &FMLLibrariesTask::progress);
connect(dljob.get(), &NetJob::stepProgress, this, &FMLLibrariesTask::propagateStepProgress);
connect(dljob.get(), &NetJob::progress, this, &LegacyFMLLibrariesTask::progress);
connect(dljob.get(), &NetJob::stepProgress, this, &LegacyFMLLibrariesTask::propagateStepProgress);
downloadJob.reset(dljob);
downloadJob->start();
}
bool FMLLibrariesTask::canAbort() const
bool LegacyFMLLibrariesTask::canAbort() const
{
return true;
}
void FMLLibrariesTask::fmllibsFinished()
void LegacyFMLLibrariesTask::fmllibsFinished()
{
downloadJob.reset();
if (!fmlLibsToProcess.isEmpty()) {
@ -107,19 +108,28 @@ void FMLLibrariesTask::fmllibsFinished()
}
emitSucceeded();
}
void FMLLibrariesTask::fmllibsFailed(QString reason)
void LegacyFMLLibrariesTask::fmllibsFailed(QString reason)
{
QStringList failed = downloadJob->getFailedFiles();
QString failed_all = failed.join("\n");
emitFailed(tr("Failed to download the following files:\n%1\n\nReason:%2\nPlease try again.").arg(failed_all, reason));
}
bool FMLLibrariesTask::abort()
bool LegacyFMLLibrariesTask::abort()
{
if (downloadJob) {
return downloadJob->abort();
} else {
qWarning() << "Prematurely aborted FMLLibrariesTask";
qWarning() << "Prematurely aborted LegacyFMLLibrariesTask";
}
return true;
}
QString LegacyFMLLibrariesTask::baseUrl()
{
if (const QString urlOverride = APPLICATION->settings()->get("LegacyFMLLibsURLOverride").toString(); !urlOverride.isEmpty()) {
return urlOverride;
}
return BuildConfig.LEGACY_FMLLIBS_BASE_URL;
}

View file

@ -5,11 +5,11 @@
class MinecraftInstance;
class FMLLibrariesTask : public Task {
class LegacyFMLLibrariesTask : public Task {
Q_OBJECT
public:
FMLLibrariesTask(MinecraftInstance* inst);
virtual ~FMLLibrariesTask() = default;
LegacyFMLLibrariesTask(MinecraftInstance* inst);
virtual ~LegacyFMLLibrariesTask() = default;
void executeTask() override;
@ -22,6 +22,9 @@ class FMLLibrariesTask : public Task {
public slots:
bool abort() override;
private:
static QString baseUrl();
private:
MinecraftInstance* m_inst;
NetJob::Ptr downloadJob;

View file

@ -77,10 +77,12 @@ APIPage::APIPage(QWidget* parent) : QWidget(parent), ui(new Ui::APIPage)
ui->metaURL->setValidator(new QRegularExpressionValidator(s_validUrlRegExp, ui->metaURL));
ui->resourceURL->setValidator(new QRegularExpressionValidator(s_validUrlRegExp, ui->resourceURL));
ui->baseURLEntry->setValidator(new QRegularExpressionValidator(s_validUrlRegExp, ui->baseURLEntry));
ui->legacyFMLLibsURL->setValidator(new QRegularExpressionValidator(s_validUrlRegExp, ui->legacyFMLLibsURL));
ui->msaClientID->setValidator(new QRegularExpressionValidator(s_validMSAClientID, ui->msaClientID));
ui->metaURL->setPlaceholderText(BuildConfig.META_URL);
ui->resourceURL->setPlaceholderText(BuildConfig.DEFAULT_RESOURCE_BASE);
ui->legacyFMLLibsURL->setPlaceholderText(BuildConfig.LEGACY_FMLLIBS_BASE_URL);
ui->userAgentLineEdit->setPlaceholderText(BuildConfig.USER_AGENT);
loadSettings();
@ -139,6 +141,8 @@ void APIPage::loadSettings()
ui->metaURL->setText(metaURL);
QString resourceURL = s->get("ResourceURLOverride").toString();
ui->resourceURL->setText(resourceURL);
QString fmlLibsURL = s->get("LegacyFMLLibsURLOverride").toString();
ui->legacyFMLLibsURL->setText(fmlLibsURL);
QString flameKey = s->get("FlameKeyOverride").toString();
ui->flameKey->setText(flameKey);
QString modrinthToken = s->get("ModrinthToken").toString();
@ -159,34 +163,34 @@ void APIPage::applySettings()
s->set("MSAClientIDOverride", msaClientID);
QUrl metaURL(ui->metaURL->text());
QUrl resourceURL(ui->resourceURL->text());
// Add required trailing slash
if (!metaURL.isEmpty() && !metaURL.path().endsWith('/')) {
QString path = metaURL.path();
path.append('/');
metaURL.setPath(path);
}
QUrl fmlLibsURL(ui->legacyFMLLibsURL->text());
if (!resourceURL.isEmpty() && !resourceURL.path().endsWith('/')) {
QString path = resourceURL.path();
auto addRequiredTrailingSlash = [](QUrl& url) {
if (!url.isEmpty() && !url.path().endsWith('/')) {
QString path = url.path();
path.append('/');
resourceURL.setPath(path);
url.setPath(path);
}
};
addRequiredTrailingSlash(metaURL);
addRequiredTrailingSlash(resourceURL);
addRequiredTrailingSlash(fmlLibsURL);
auto isLocalhost = [](const QUrl& url) { return url.host() == "localhost" || url.host() == "127.0.0.1" || url.host() == "::1"; };
auto isUnsafe = [isLocalhost](const QUrl& url) { return !url.isEmpty() && url.scheme() == "http" && !isLocalhost(url); };
// Don't allow HTTP, since meta is basically RCE with all the jar files.
if (isUnsafe(metaURL)) {
metaURL.setScheme("https");
auto upgradeToHTTPS = [isUnsafe](QUrl& url) {
if (isUnsafe(url)) {
url.setScheme("https");
}
};
// Also don't allow HTTP
if (isUnsafe(resourceURL)) {
resourceURL.setScheme("https");
}
upgradeToHTTPS(metaURL);
upgradeToHTTPS(resourceURL);
upgradeToHTTPS(fmlLibsURL);
s->set("MetaURLOverride", metaURL.toString());
s->set("ResourceURLOverride", resourceURL.toString());
s->set("LegacyFMLLibsURLOverride", fmlLibsURL.toString());
QString flameKey = ui->flameKey->text();
s->set("FlameKeyOverride", flameKey);
QString modrinthToken = ui->modrinthToken->text();

View file

@ -161,6 +161,34 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_fmllibs">
<property name="title">
<string>Legacy FML Libraries Server</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_8">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>You can set this to another server if you have problems with downloading legacy FML libraries (Minecraft 1.5.2 and earlier).</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="legacyFMLLibsURL"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_ua">
<property name="minimumSize">