diff --git a/client/client_scripts/mac_installer.sh b/client/client_scripts/mac_installer.sh new file mode 100644 index 00000000..a572be8e --- /dev/null +++ b/client/client_scripts/mac_installer.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +EXTRACT_DIR="$1" +INSTALLER_PATH="$2" + +# Create and clean extract directory +rm -rf "$EXTRACT_DIR" +mkdir -p "$EXTRACT_DIR" + +# Mount the DMG +hdiutil attach "$INSTALLER_PATH" -mountpoint "$EXTRACT_DIR/mounted_dmg" -nobrowse -quiet +if [ $? -ne 0 ]; then + echo "Failed to mount DMG" + exit 1 +fi + +# Copy the app to /Applications +cp -R "$EXTRACT_DIR/mounted_dmg/AmneziaVPN.app" /Applications/ +if [ $? -ne 0 ]; then + echo "Failed to copy AmneziaVPN.app to /Applications" + hdiutil detach "$EXTRACT_DIR/mounted_dmg" -quiet + exit 1 +fi + +# Unmount the DMG +hdiutil detach "$EXTRACT_DIR/mounted_dmg" -quiet +if [ $? -ne 0 ]; then + echo "Failed to unmount DMG" + exit 1 +fi + +# Optional: Remove the DMG file +rm "$INSTALLER_PATH" + +echo "Installation completed successfully" +exit 0 \ No newline at end of file diff --git a/client/core/scripts_registry.cpp b/client/core/scripts_registry.cpp index 9b02fba9..d2b17cb9 100644 --- a/client/core/scripts_registry.cpp +++ b/client/core/scripts_registry.cpp @@ -58,6 +58,7 @@ QString amnezia::scriptName(ClientScriptType type) { switch (type) { case ClientScriptType::linux_installer: return QLatin1String("linux_installer.sh"); + case ClientScriptType::mac_installer: return QLatin1String("mac_installer.sh"); default: return QString(); } } diff --git a/client/core/scripts_registry.h b/client/core/scripts_registry.h index 2b4bf087..87fddbb5 100644 --- a/client/core/scripts_registry.h +++ b/client/core/scripts_registry.h @@ -35,7 +35,8 @@ namespace amnezia enum ClientScriptType { // Client-side scripts - linux_installer + linux_installer, + mac_installer }; QString scriptFolder(DockerContainer container); diff --git a/client/resources.qrc b/client/resources.qrc index ae015b9f..4b6689e5 100644 --- a/client/resources.qrc +++ b/client/resources.qrc @@ -4,6 +4,7 @@ images/tray/default.png images/tray/error.png client_scripts/linux_installer.sh + client_scripts/mac_installer.sh images/AmneziaVPN.png server_scripts/remove_container.sh server_scripts/setup_host_firewall.sh diff --git a/client/ui/controllers/updateController.cpp b/client/ui/controllers/updateController.cpp index 7eb5c63f..e62ee02f 100644 --- a/client/ui/controllers/updateController.cpp +++ b/client/ui/controllers/updateController.cpp @@ -193,9 +193,51 @@ int UpdateController::runWindowsInstaller(const QString &installerPath) #if defined(Q_OS_MACOS) int UpdateController::runMacInstaller(const QString &installerPath) { - logger.info() << "macOS installer path:" << installerPath; - // TODO: Implement macOS installation logic - return -1; + // Create temporary directory for extraction + QTemporaryDir extractDir; + extractDir.setAutoRemove(false); + if (!extractDir.isValid()) { + logger.error() << "Failed to create temporary directory"; + return -1; + } + logger.info() << "Temporary directory created:" << extractDir.path(); + + // Create script file in the temporary directory + QString scriptPath = extractDir.path() + "/mac_installer.sh"; + QFile scriptFile(scriptPath); + if (!scriptFile.open(QIODevice::WriteOnly)) { + logger.error() << "Failed to create script file"; + return -1; + } + + // Get script content from registry + QString scriptContent = amnezia::scriptData(amnezia::ClientScriptType::mac_installer); + if (scriptContent.isEmpty()) { + logger.error() << "macOS installer script content is empty"; + scriptFile.close(); + return -1; + } + + scriptFile.write(scriptContent.toUtf8()); + scriptFile.close(); + logger.info() << "Script file created:" << scriptPath; + + // Make script executable + QFile::setPermissions(scriptPath, QFile::permissions(scriptPath) | QFile::ExeUser); + + // Start detached process + qint64 pid; + bool success = QProcess::startDetached( + "/bin/bash", QStringList() << scriptPath << extractDir.path() << installerPath, extractDir.path(), &pid); + + if (success) { + logger.info() << "Installation process started with PID:" << pid; + } else { + logger.error() << "Failed to start installation process"; + return -1; + } + + return 0; } #endif