diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Build/CMakeLists.txt | 15 | ||||
-rw-r--r-- | src/Common/Common.rc | 4 | ||||
-rw-r--r-- | src/Common/Dlgcode.c | 50 | ||||
-rw-r--r-- | src/Main/UserInterface.cpp | 98 |
4 files changed, 112 insertions, 55 deletions
diff --git a/src/Build/CMakeLists.txt b/src/Build/CMakeLists.txt index ce3d372b..458040e8 100644 --- a/src/Build/CMakeLists.txt +++ b/src/Build/CMakeLists.txt @@ -84,114 +84,125 @@ if ( UNIX ) file(READ "/etc/lsb-release" UBUNTU_RELEASE) string(REGEX MATCH "DISTRIB_RELEASE=([0-9 /\\.]+)" _ ${UBUNTU_RELEASE}) set(PLATFORM_VERSION ${CMAKE_MATCH_1}) else() file(READ "/etc/debian_version" DEBIAN_RELEASE) string(REGEX MATCH "([0-9]+\\.[0-9]+)" _ ${DEBIAN_RELEASE}) set(PLATFORM_VERSION ${CMAKE_MATCH_1}) endif() # Get debian release version elseif(EXISTS "/etc/debian_version") file(READ "/etc/debian_version" DEBIAN_RELEASE) string(REGEX MATCH "([0-9]+\\.[0-9]+)" _ ${DEBIAN_RELEASE}) set(PLATFORM_VERSION ${CMAKE_MATCH_1}) endif() # Get centos release version elseif(EXISTS "/etc/centos-release") set ( PLATFORM "CentOS" ) file(READ "/etc/centos-release" CENTOS_RELEASE) string(REGEX MATCH "release ([0-9 /\\.]+)" _ ${CENTOS_RELEASE}) set(PLATFORM_VERSION ${CMAKE_MATCH_1}) + + # Get fedora release version + elseif(EXISTS "/etc/fedora-release") + + set ( PLATFORM "Fedora" ) + + file(READ "/etc/fedora-release" FEDORA_RELEASE) + string(REGEX MATCH "release ([0-9 /\\.]+)" _ ${FEDORA_RELEASE}) + set(PLATFORM_VERSION ${CMAKE_MATCH_1}) # Only if distribution uses systemd and if all previous files didn't exist # i.e OpenSUSE elseif(EXISTS "/etc/os-release") file(READ "/etc/os-release" OS_RELEASE_NAME) string(REGEX MATCH "NAME=\"([a-zA-Z0-9 /\\.]+)\"" _ ${OS_RELEASE_NAME}) set(FULL_PLATFORM ${CMAKE_MATCH_1}) if (FULL_PLATFORM MATCHES "^.*openSUSE.*$") set ( PLATFORM "openSUSE" ) elseif ( FULL_PLATFORM MATCHES "^.*Ubuntu.*$") set ( PLATFORM "Ubuntu" ) elseif ( FULL_PLATFORM MATCHES "^.*Debian.*$") set ( PLATFORM "Debian" ) elseif ( FULL_PLATFORM MATCHES "^.*CentOS.*$" ) set ( PLATFORM "CentOS" ) + elseif ( FULL_PLATFORM MATCHES "^.*Fedora.*$" ) + set ( PLATFORM "Fedora" ) endif ( ) # Get ditribution release version file(READ "/etc/os-release" OS_RELEASE) string(REGEX MATCH "VERSION=\"([a-zA-Z0-9 /\\.]+)\"" _ ${OS_RELEASE}) set(PLATFORM_VERSION ${CMAKE_MATCH_1}) endif() endif ( ) string(REGEX REPLACE " $" "" PLATFORM_VERSION "${PLATFORM_VERSION}") # Trim the last trailing whitespace set ( DISTRO_NAME ${PLATFORM}-${PLATFORM_VERSION} ) MESSAGE ( STATUS "Platform = ${PLATFORM}" ) MESSAGE ( STATUS "Platform Version = ${PLATFORM_VERSION}" ) MESSAGE ( STATUS "Distribution name = ${DISTRO_NAME}" ) # - Detect the architecture under OSX, Debian, CentOS and OpenSUSE platforms # The following variable will be set # $ARCHITECTURE if ( PLATFORM STREQUAL "Debian" OR PLATFORM STREQUAL "Ubuntu" ) # There is no such thing as i686 architecture on debian, i386 is to be used instead # dpkg --print-architecture find_program(DPKG_CMD dpkg) if(NOT DPKG_CMD) # Cannot find dpkg in path # Try best guess following SUFFIX value calculated from CMAKE_SIZEOF_VOID_P if (SUFFIX STREQUAL "32") SET(ARCHITECTURE i386) elseif (SUFFIX STREQUAL "64") SET(ARCHITECTURE amd64) endif() else( ) execute_process(COMMAND dpkg --print-architecture OUTPUT_VARIABLE ARCHITECTURE OUTPUT_STRIP_TRAILING_WHITESPACE) endif( ) -elseif ( ( PLATFORM STREQUAL "CentOS" ) OR ( PLATFORM STREQUAL "openSUSE" ) ) +elseif ( ( PLATFORM STREQUAL "CentOS" ) OR ( PLATFORM STREQUAL "openSUSE" ) OR ( PLATFORM STREQUAL "Fedora" )) execute_process(COMMAND arch OUTPUT_VARIABLE ARCHITECTURE OUTPUT_STRIP_TRAILING_WHITESPACE) else () MESSAGE(FATAL_ERROR "Unrecognized / unsupported distribution") endif ( ) MESSAGE ( STATUS "Architecture = ${ARCHITECTURE}" ) # - Create installation folder directory at install time # This won't lead to the files being actually installed (in CMAKE_INSTALL_PREFIX) # unless "cmake --build . --target install" is executed, which is not the case here. # # Doing things like the following # - install(DIRECTORY ${VERACRYPT_BUILD_DIR}/usr DESTINATION /) # - install(DIRECTORY ${VERACRYPT_BUILD_DIR}/usr/bin DESTINATION /usr) # lead to conflicts despite the usage of CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION # because install() forces CpackRPM to create the DESTINATION folders. # # We fix this by installing ALL directories inside '/usr' in '.', and setting # CPACK_PACKAGING_INSTALL_PREFIX to '/usr'. # This way, during the packaging, 'bin' and 'share' folders will be installed # inside '${CPACK_PACKAGE_DIRECTORY}/_CPack_Packages/<system_name>/DEB,RPM/${CPACK_PACKAGE_NAME}/${CPACK_PACKAGING_INSTALL_PREFIX}'. # # Also, we use USE_SOURCE_PERMISSIONS to save the permissions install(DIRECTORY ${VERACRYPT_BUILD_DIR}/usr/bin DESTINATION . USE_SOURCE_PERMISSIONS) install(DIRECTORY ${VERACRYPT_BUILD_DIR}/usr/sbin @@ -268,61 +279,61 @@ if ( ( PLATFORM STREQUAL "Debian" ) OR ( PLATFORM STREQUAL "Ubuntu" ) ) OR ( ( PLATFORM STREQUAL "Ubuntu" ) AND ( PLATFORM_VERSION VERSION_GREATER_EQUAL "23.04" ) ) ) set( CPACK_DEBIAN_PACKAGE_DEPENDS "libwxgtk3.2-1, libayatana-appindicator3-1, libfuse2, dmsetup, sudo, libpcsclite1, pcscd" ) elseif ( ( ( PLATFORM STREQUAL "Debian" ) AND ( PLATFORM_VERSION VERSION_GREATER_EQUAL "10" ) ) OR ( ( PLATFORM STREQUAL "Ubuntu" ) AND ( PLATFORM_VERSION VERSION_GREATER_EQUAL "18.04" ) ) ) set( CPACK_DEBIAN_PACKAGE_DEPENDS "libwxgtk3.0-gtk3-0v5, libayatana-appindicator3-1, libfuse2, dmsetup, sudo, libpcsclite1, pcscd" ) else () # Link against statically built wxWidgets on Ubuntu 14.04 and older, and Debian 8 and older if ( ( ( PLATFORM STREQUAL "Debian" ) AND ( PLATFORM_VERSION VERSION_LESS_EQUAL "8" ) ) OR ( ( PLATFORM STREQUAL "Ubuntu" ) AND ( PLATFORM_VERSION VERSION_LESS_EQUAL "14.04" ) ) ) set( CPACK_DEBIAN_PACKAGE_DEPENDS "libgtk2.0-0, libfuse2, dmsetup, sudo, libpcsclite1, pcscd" ) else () set( CPACK_DEBIAN_PACKAGE_DEPENDS "libwxgtk3.0-0v5, libfuse2, dmsetup, sudo, libpcsclite1, pcscd" ) endif () endif() endif() set( CPACK_DEBIAN_PACKAGE_MAINTAINER ${CONTACT} ) # mandatory set( CPACK_DEBIAN_PACKAGE_DESCRIPTION ${CPACK_PACKAGE_DESCRIPTION_SUMMARY} ) # mandatory set( CPACK_DEBIAN_ARCHIVE_TYPE "gnutar") # mandatory set( CPACK_DEBIAN_COMPRESSION_TYPE "gzip") # mandatory set( CPACK_DEBIAN_PACKAGE_PRIORITY "optional" ) # mandatory set( CPACK_DEBIAN_PACKAGE_SECTION "libs" ) # recommended, Section relative to Debian sections (https://www.debian.org/doc/debian-policy/ch-archive.html#s-subsections) set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA ${DEBIAN_PREINST};${DEBIAN_POSTINST};${DEBIAN_PRERM};${DEBIAN_POSTRM}) set(CPACK_DEBIAN_PACKAGE_CONFLICTS "${CONFLICT_PACKAGE}") -elseif ( ( PLATFORM STREQUAL "CentOS" ) OR ( PLATFORM STREQUAL "openSUSE" ) ) +elseif ( ( PLATFORM STREQUAL "CentOS" ) OR ( PLATFORM STREQUAL "openSUSE" ) OR ( PLATFORM STREQUAL "Fedora" )) # RPM control script(s) file( MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/Packaging/rpm-control) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/Packaging/rpm-control/prerm.sh ${CMAKE_CURRENT_BINARY_DIR}/Packaging/rpm-control/prerm.sh) set( RPM_PRERM ${CMAKE_CURRENT_BINARY_DIR}/Packaging/rpm-control/prerm.sh) set( CPACK_GENERATOR "RPM" ) # mandatory set( CPACK_RPM_PACKAGE_SUMMARY ${CPACK_PACKAGE_SUMMARY} ) # mandatory set( CPACK_RPM_PACKAGE_DESCRIPTION ${CPACK_PACKAGE_DESCRIPTION} ) # mandatory set( CPACK_RPM_PACKAGE_NAME ${CPACK_PACKAGE_NAME} ) # mandatory set( CPACK_RPM_FILE_NAME ${CPACK_PACKAGE_FILE_NAME}.rpm ) # mandatory set( CPACK_RPM_PACKAGE_VERSION ${CPACK_PACKAGE_VERSION} ) # mandatory set( CPACK_RPM_PACKAGE_ARCHITECTURE ${ARCHITECTURE} ) # mandatory set( CPACK_RPM_PACKAGE_RELEASE ${CPACK_PACKAGE_RELEASE} ) # mandatory set( CPACK_RPM_PACKAGE_LICENSE ${CPACK_PACKAGE_LICENSE} ) # mandatory set( CPACK_RPM_PACKAGE_GROUP "Applications/System" ) # mandatory, https://fedoraproject.org/wiki/RPMGroups set( CPACK_RPM_PACKAGE_VENDOR ${CPACK_PACKAGE_VENDOR} ) # mandatory set( CPACK_RPM_PACKAGE_AUTOREQ "no" ) # disable automatic shared libraries dependency detection (most of the time buggy) if (NOGUI) set( CPACK_RPM_PACKAGE_REQUIRES "fuse, device-mapper, sudo" ) else () find_package(PkgConfig REQUIRED) pkg_check_modules(GTK3 gtk+-3.0) if(GTK3_FOUND) set( CPACK_RPM_PACKAGE_REQUIRES "fuse, device-mapper, gtk3, sudo, pcsc-lite" ) else() set( CPACK_RPM_PACKAGE_REQUIRES "fuse, device-mapper, gtk2, sudo, pcsc-lite" ) endif() diff --git a/src/Common/Common.rc b/src/Common/Common.rc index cbd401d8..41778dfc 100644 --- a/src/Common/Common.rc +++ b/src/Common/Common.rc @@ -317,63 +317,63 @@ BEGIN RTEXT "Mixing PRF:",IDT_PRF,6,51,67,10,SS_CENTERIMAGE GROUPBOX "Current Pool Content",IDT_POOL_CONTENTS,6,70,296,170 CONTROL "",IDC_POOL_CONTENTS,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,16,83,282,148,WS_EX_TRANSPARENT CONTROL "Display pool content",IDC_DISPLAY_POOL_CONTENTS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,191,51,111,10 CONTROL "",IDC_ENTROPY_BAR,"msctls_progress32",PBS_SMOOTH | WS_BORDER,16,255,275,12 GROUPBOX "Randomness Collected From Mouse Movements",IDT_ENTROPY_BAR,7,244,294,29 END IDD_STATIC_MODELESS_WAIT_DLG DIALOGEX 0, 0, 292, 42 STYLE DS_SYSMODAL | DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION EXSTYLE WS_EX_TOPMOST | WS_EX_TOOLWINDOW CAPTION "VeraCrypt" FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN LTEXT "Please wait. This process may take a long time...",IDT_STATIC_MODELESS_WAIT_DLG_INFO,9,8,274,27 END IDD_STATIC_MODAL_WAIT_DLG DIALOGEX 0, 0, 292, 74 STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION CAPTION "VeraCrypt" FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN CTEXT "Please wait...\nThis process may take a long time and VeraCrypt may seem unresponsive.",IDT_STATIC_MODAL_WAIT_DLG_INFO,9,11,274,33 CONTROL "",IDC_WAIT_PROGRESS_BAR,"msctls_progress32",WS_BORDER,7,49,278,14 END IDD_TEXT_EDIT_DLG DIALOGEX 0, 0, 372, 220 STYLE DS_SETFONT | DS_MODALFRAME | DS_3DLOOK | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN - PUSHBUTTON "OK",IDOK,306,201,58,14 + PUSHBUTTON "OK",IDOK,244,201,58,14 CONTROL "",IDC_INFO_BOX_TEXT,"RichEdit20W",ES_MULTILINE | ES_WANTRETURN | ES_NUMBER | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP,5,6,361,188 - DEFPUSHBUTTON "Cancel",IDCANCEL,240,201,58,14 + DEFPUSHBUTTON "Cancel",IDCANCEL,308,201,58,14 END ///////////////////////////////////////////////////////////////////////////// // // DESIGNINFO // #ifdef APSTUDIO_INVOKED GUIDELINES DESIGNINFO BEGIN IDD_ABOUT_DLG, DIALOG BEGIN END IDD_COMMANDHELP_DLG, DIALOG BEGIN BOTTOMMARGIN, 281 END IDD_RAWDEVICES_DLG, DIALOG BEGIN LEFTMARGIN, 7 RIGHTMARGIN, 298 TOPMARGIN, 7 BOTTOMMARGIN, 205 END IDD_MOUNT_OPTIONS, DIALOG BEGIN diff --git a/src/Common/Dlgcode.c b/src/Common/Dlgcode.c index 269817d8..b91167d4 100644 --- a/src/Common/Dlgcode.c +++ b/src/Common/Dlgcode.c @@ -4138,103 +4138,143 @@ struct _TEXT_EDIT_DIALOG_PARAM { _TEXT_EDIT_DIALOG_PARAM (const _TEXT_EDIT_DIALOG_PARAM& other) : ReadOnly (other.ReadOnly), Text (other.Text), Title (other.Title) {} _TEXT_EDIT_DIALOG_PARAM(BOOL _readOnly, const WCHAR* title, std::string& _text) : ReadOnly(_readOnly), Text(_text), Title(title) {} _TEXT_EDIT_DIALOG_PARAM& operator=( const _TEXT_EDIT_DIALOG_PARAM& other) { if (this != &other) { ReadOnly = other.ReadOnly; Text = other.Text; Title = other.Title; } return *this; } }; typedef struct _TEXT_EDIT_DIALOG_PARAM TEXT_INFO_DIALOG_PARAM,*TEXT_INFO_DIALOG_PARAM_PTR; INT_PTR TextEditDialogBox (BOOL readOnly, HWND parent, const WCHAR* Title, std::string& text) { TEXT_INFO_DIALOG_PARAM pm(readOnly, Title, text); return DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TEXT_EDIT_DLG), parent, (DLGPROC) TextEditDlgProc, (LPARAM) &pm); } BOOL CALLBACK TextEditDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { WORD lw = LOWORD (wParam); static int nID = 0; static TEXT_INFO_DIALOG_PARAM_PTR prm; switch (msg) { case WM_INITDIALOG: { prm = (TEXT_INFO_DIALOG_PARAM_PTR)lParam; + LocalizeDialog (hwndDlg, NULL); // increase size limit of rich edit control SendMessage(GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), EM_EXLIMITTEXT, 0, -1); SetWindowTextW (hwndDlg, prm->Title); // Left margin for rich edit text field SendMessage (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), EM_SETMARGINS, (WPARAM) EC_LEFTMARGIN, (LPARAM) CompensateXDPI (4)); if (prm->ReadOnly) { // switch rich edit control to ReadOnly - SendMessage(GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), ES_READONLY, TRUE, 0); + SendMessage(GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), EM_SETREADONLY , TRUE, 0); // hide cancel button - ShowWindow(GetDlgItem(hwndDlg, IDCANCEL), SW_HIDE); + HWND hwndCancel = GetDlgItem(hwndDlg, IDCANCEL); + ShowWindow(hwndCancel, SW_HIDE); + + // Reposition OK button to Cancel button's position + HWND hwndOK = GetDlgItem(hwndDlg, IDOK); + if (hwndOK && hwndCancel) + { + // Get Cancel button's position in screen coordinates + RECT rectCancel; + if (GetWindowRect(hwndCancel, &rectCancel)) + { + // Convert Cancel button's position to dialog's client coordinates + POINT ptCancel = { rectCancel.left, rectCancel.top }; + ScreenToClient(hwndDlg, &ptCancel); + + // Get OK button's current size + RECT rectOK; + if (GetWindowRect(hwndOK, &rectOK)) + { + int width = rectOK.right - rectOK.left; + int height = rectOK.bottom - rectOK.top; + + // Move OK button to Cancel button's position + SetWindowPos( + hwndOK, + NULL, + ptCancel.x, + ptCancel.y, + width, + height, + SWP_NOZORDER | SWP_NOACTIVATE + ); + } + } + } } SendMessage (hwndDlg, TC_APPMSG_LOAD_TEXT_BOX_CONTENT, 0, 0); } return 0; case WM_COMMAND: if (lw == IDOK ) { if (!prm->ReadOnly) { - prm->Text.resize(GetWindowTextLengthA (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT)) + 1); - GetWindowTextA (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), &(prm->Text)[0], (int) prm->Text.size()); + // read content of the text box as UTF16 and then convert it to UTF8 + HWND hEdit = GetDlgItem(hwndDlg, IDC_INFO_BOX_TEXT); + int size = GetWindowTextLengthW(hEdit); + std::vector<WCHAR> buffer(size + 1); + GetWindowTextW(hEdit, buffer.data(), size + 1); + prm->Text = WideToUtf8String(buffer.data()); } NormalCursor (); EndDialog (hwndDlg, IDOK); return 1; } if (lw == IDCANCEL ) { NormalCursor (); EndDialog (hwndDlg, IDCANCEL); return 1; } return 0; case TC_APPMSG_LOAD_TEXT_BOX_CONTENT: { - SetWindowTextA (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), prm->Text.c_str()); + // convert prm->Text to UTF16 using Utf8StringToWide + SetWindowTextW(GetDlgItem(hwndDlg, IDC_INFO_BOX_TEXT), Utf8StringToWide(prm->Text).c_str()); } return 0; case WM_CLOSE: NormalCursor (); EndDialog (hwndDlg, 0); return 1; } return 0; } INT_PTR TextInfoDialogBox (int nID) { return DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TEXT_INFO_DIALOG_BOX_DLG), MainDlg, (DLGPROC) TextInfoDialogBoxDlgProc, (LPARAM) nID); } BOOL CALLBACK TextInfoDialogBoxDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { WORD lw = LOWORD (wParam); static int nID = 0; switch (msg) { case WM_INITDIALOG: { nID = (int) lParam; // increase size limit of rich edit control SendMessage(GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), EM_EXLIMITTEXT, 0, -1); diff --git a/src/Main/UserInterface.cpp b/src/Main/UserInterface.cpp index ad2f22b8..b216101a 100644 --- a/src/Main/UserInterface.cpp +++ b/src/Main/UserInterface.cpp @@ -846,138 +846,144 @@ namespace VeraCrypt catch (UserAbort&) { } catch (exception &e) { ShowError (e); } catch (...) { ShowError (LangString["LINUX_UNKNOWN_EXC_OCCURRED"]); } Yield(); Application::SetExitCode (1); } void UserInterface::OnVolumeMounted (EventArgs &args) { shared_ptr <VolumeInfo> mountedVolume = (dynamic_cast <VolumeEventArgs &> (args)).mVolume; if (Preferences.OpenExplorerWindowAfterMount && !mountedVolume->MountPoint.IsEmpty()) OpenExplorerWindow (mountedVolume->MountPoint); } void UserInterface::OnWarning (EventArgs &args) { ExceptionEventArgs &e = dynamic_cast <ExceptionEventArgs &> (args); ShowWarning (e.mException); } +#if !defined(TC_WINDOWS) && !defined(TC_MACOSX) +// Function to check if a given executable exists and is executable +static bool IsExecutable(const string& exe) { + return wxFileName::IsFileExecutable("/usr/bin/" + exe) || + wxFileName::IsFileExecutable("/usr/local/bin/" + exe); +} +#endif + void UserInterface::OpenExplorerWindow (const DirectoryPath &path) { if (path.IsEmpty()) return; list <string> args; #ifdef TC_WINDOWS wstring p (Directory::AppendSeparator (path)); SHFILEINFO fInfo; SHGetFileInfo (p.c_str(), 0, &fInfo, sizeof (fInfo), 0); // Force explorer to discover the drive ShellExecute (GetTopWindow() ? static_cast <HWND> (GetTopWindow()->GetHandle()) : nullptr, L"open", p.c_str(), nullptr, nullptr, SW_SHOWNORMAL); #elif defined (TC_MACOSX) args.push_back (string (path)); try { Process::Execute ("open", args); } catch (exception &e) { ShowError (e); } #else - // MIME handler for directory seems to be unavailable through wxWidgets - wxString desktop = GetTraits()->GetDesktopEnvironment(); - bool xdgOpenPresent = wxFileName::IsFileExecutable (wxT("/usr/bin/xdg-open")) || wxFileName::IsFileExecutable (wxT("/usr/local/bin/xdg-open")); - bool nautilusPresent = wxFileName::IsFileExecutable (wxT("/usr/bin/nautilus")) || wxFileName::IsFileExecutable (wxT("/usr/local/bin/nautilus")); - - if (desktop == L"GNOME" || (desktop.empty() && !xdgOpenPresent && nautilusPresent)) - { - // args.push_back ("--no-default-window"); // This option causes nautilus not to launch under FreeBSD 11 - args.push_back ("--no-desktop"); - args.push_back (string (path)); - try - { - Process::Execute ("nautilus", args, 2000); + string directoryPath = string(path); + // Primary attempt: Use xdg-open + if (IsExecutable("xdg-open")) { + try { + args.push_back(directoryPath); + Process::Execute("xdg-open", args, 2000); + return; } catch (TimeOut&) { } - catch (exception &e) { ShowError (e); } + catch (exception&) {} } - else if (desktop == L"KDE") - { - try - { - args.push_back (string (path)); - Process::Execute ("dolphin", args, 2000); - } - catch (TimeOut&) { } - catch (exception&) - { + + // Fallback attempts: Try known file managers + const char* fallbackFileManagers[] = { "gio", "kioclient5", "kfmclient", "exo-open", "nautilus", "dolphin", "caja", "thunar", "pcmanfm" }; + const size_t numFileManagers = sizeof(fallbackFileManagers) / sizeof(fallbackFileManagers[0]); + + for (size_t i = 0; i < numFileManagers; ++i) { + const char* fm = fallbackFileManagers[i]; + if (IsExecutable(fm)) { args.clear(); - args.push_back ("openURL"); - args.push_back (string (path)); - try - { - Process::Execute ("kfmclient", args, 2000); + if (strcmp(fm, "gio") == 0) { + args.push_back("open"); + args.push_back(directoryPath); + } + else if (strcmp(fm, "kioclient5") == 0) { + args.push_back("exec"); + args.push_back(directoryPath); + } + else if (strcmp(fm, "kfmclient") == 0) { + args.push_back("openURL"); + args.push_back(directoryPath); + } + else if (strcmp(fm, "exo-open") == 0) { + args.push_back("--launch"); + args.push_back("FileManager"); + args.push_back(directoryPath); + } + else { + args.push_back(directoryPath); + } + + try { + Process::Execute(fm, args, 2000); + return; // Success } catch (TimeOut&) { } - catch (exception &e) { ShowError (e); } - } - } - else if (xdgOpenPresent) - { - // Fallback on the standard xdg-open command - // which is not always available by default - args.push_back (string (path)); - try - { - Process::Execute ("xdg-open", args, 2000); + catch (exception &) {} } - catch (TimeOut&) { } - catch (exception &e) { ShowError (e); } - } - else - { - ShowWarning (wxT("Unable to find a file manager to open the mounted volume")); } + + ShowWarning(wxT("Unable to find a file manager to open the mounted volume.\n" + "Please install xdg-utils or set a default file manager.")); #endif } bool UserInterface::ProcessCommandLine () { CommandLineInterface &cmdLine = *CmdLine; if (cmdLine.ArgCommand == CommandId::None) return false; if (Preferences.UseStandardInput) { wstring pwdInput; getline(wcin, pwdInput); size_t maxUtf8Len = cmdLine.ArgUseLegacyPassword? VolumePassword::MaxLegacySize : VolumePassword::MaxSize; cmdLine.ArgPassword = ToUTF8Password ( pwdInput.c_str (), pwdInput.size (), maxUtf8Len); } switch (cmdLine.ArgCommand) { case CommandId::AutoMountDevices: case CommandId::AutoMountFavorites: case CommandId::AutoMountDevicesFavorites: case CommandId::MountVolume: { cmdLine.ArgMountOptions.Path = cmdLine.ArgVolumePath; cmdLine.ArgMountOptions.MountPoint = cmdLine.ArgMountPoint; cmdLine.ArgMountOptions.Password = cmdLine.ArgPassword; cmdLine.ArgMountOptions.Pim = cmdLine.ArgPim; |