#include "desktop_integration.h" #include "debug_config.h" #include #include #include bool registerDesktopApplication(const QString& executable) { #ifdef Q_OS_LINUX const QString relative = QStringLiteral("applications/org.utun.vibechat.desktop"); if (!QStandardPaths::locate(QStandardPaths::GenericDataLocation, relative).isEmpty()) return true; const QString root = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation); const QString path = root + '/' + relative; if (root.isEmpty() || !QDir().mkpath(root + "/applications")) { DEBUG_WARN(DEBUG_CATEGORY_GENERAL, "Desktop registration: cannot create applications directory in %s", qPrintable(root)); return false; } // Exec сначала разбирается как desktop string, затем как командная строка; shell не используется. QString command; for (QChar c : executable) { if (c == '%') command += "%%"; else { if (c == '\\' || c == '"' || c == '$' || c == '`') command += '\\'; command += c; } } command = '"' + command + '"'; command.replace("\\", "\\\\"); command.replace('\n', "\\n"); command.replace('\r', "\\r"); command.replace('\t', "\\t"); // GLib проверяет executable до раскрытия %%; env оставляет путь аргументом и корректно обрабатывает '%' в имени. const QByteArray content = QString("[Desktop Entry]\nType=Application\nName=VibeChat\nExec=/usr/bin/env %1\n" "Icon=applications-internet\nTerminal=false\nCategories=Network;InstantMessaging;\n").arg(command).toUtf8(); QSaveFile file(path); if (!file.open(QIODevice::WriteOnly) || file.write(content) != content.size() || !file.commit()) { DEBUG_WARN(DEBUG_CATEGORY_GENERAL, "Desktop registration failed path=%s: %s", qPrintable(path), qPrintable(file.errorString())); return false; } DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "Desktop application registered path=%s", qPrintable(path)); #else Q_UNUSED(executable); #endif return true; }