diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index d6c4ccbec..1afc248b7 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -940,6 +941,11 @@ void MainWindow::processURLs(QList urls) QMap extra_info; QUrl local_url; if (!url.isLocalFile()) { // download the remote resource and identify + + const bool isExternalURLImport = + (url.host().toLower() == "import") || + (url.path().startsWith("/import", Qt::CaseInsensitive)); + QUrl dl_url; if (url.scheme() == "curseforge") { // need to find the download link for the modpack / resource @@ -993,7 +999,7 @@ void MainWindow::processURLs(QList urls) dlUrlDialod.execWithTask(job.get()); } - } else if (url.scheme() == BuildConfig.LAUNCHER_APP_BINARY_NAME) { + } else if (url.scheme() == BuildConfig.LAUNCHER_APP_BINARY_NAME && !isExternalURLImport) { QVariantMap receivedData; const QUrlQuery query(url.query()); const auto items = query.queryItems(); @@ -1001,6 +1007,78 @@ void MainWindow::processURLs(QList urls) receivedData.insert(it->first, it->second); emit APPLICATION->oauthReplyRecieved(receivedData); continue; + } else if ((url.scheme() == "prismlauncher" || url.scheme() == BuildConfig.LAUNCHER_APP_BINARY_NAME) + && isExternalURLImport) { + // PrismLauncher URL protocol modpack import + // works for any prism fork + // preferred import format: prismlauncher://import?url=ENCODED + const auto host = url.host().toLower(); + const auto path = url.path(); + + QString encodedTarget; + + { + QUrlQuery query(url); + const auto values = query.allQueryItemValues("url"); + if (!values.isEmpty()) { + encodedTarget = values.first(); + } + } + + // alternative import format: prismlauncher://import/ENCODED + if (encodedTarget.isEmpty()) { + + QString p = path; + + if (p.startsWith("/import/", Qt::CaseInsensitive)) { + p = p.mid(QString("/import/").size()); + } else if (host == "import" && p.startsWith("/")) { + p = p.mid(1); + } + + if (!p.isEmpty() && p != "/import") { + encodedTarget = p; + } + } + + if (encodedTarget.isEmpty()) { + CustomMessageBox::selectable( + this, + tr("Error"), + tr("Invalid import link: missing 'url' parameter."), + QMessageBox::Critical + )->show(); + continue; + } + + const QString decodedStr = QUrl::fromPercentEncoding(encodedTarget.toUtf8()).trimmed(); + + QUrl target = QUrl::fromUserInput(decodedStr); + + // Validate: only allow http(s) + if (!target.isValid() || (target.scheme() != "https" && target.scheme() != "http")) { + CustomMessageBox::selectable( + this, + tr("Error"), + tr("Invalid import link: URL must be http(s)."), + QMessageBox::Critical + )->show(); + continue; + } + + const auto res = QMessageBox::question( + this, + tr("Install modpack"), + tr("Do you want to download and import a modpack from:\n%1\n\nURL:\n%2") + .arg(target.host(), target.toString()), + QMessageBox::Yes | QMessageBox::No, + QMessageBox::Yes + ); + if (res != QMessageBox::Yes) { + continue; + } + + dl_url = target; } else { dl_url = url; } diff --git a/program_info/win_install.nsi.in b/program_info/win_install.nsi.in index e957f4d36..ba6b7e061 100644 --- a/program_info/win_install.nsi.in +++ b/program_info/win_install.nsi.in @@ -397,6 +397,10 @@ Section "@Launcher_DisplayName@" WriteRegStr HKCU Software\Classes\@Launcher_APP_BINARY_NAME@ "URL Protocol" "" WriteRegStr HKCU Software\Classes\@Launcher_APP_BINARY_NAME@\shell\open\command "" '"$INSTDIR\@Launcher_APP_BINARY_NAME@.exe" "%1"' + ; Write the URL Handler into registry for prismlauncher import + WriteRegStr HKCU Software\Classes\prismlauncher "URL Protocol" "" + WriteRegStr HKCU Software\Classes\prismlauncher\shell\open\command "" '"$INSTDIR\@Launcher_APP_BINARY_NAME@.exe" "%1"' + ; Write the uninstall keys for Windows ; https://learn.microsoft.com/en-us/windows/win32/msi/uninstall-registry-key ${GetParameters} $R0