Feature Request: Allow Windows users to define custom directory for configuration (.xml) files

Moderator: Project members

Post Reply
Message
Author
iambesi
500 Command not understood
Posts: 2
Joined: 2021-12-03 01:43
First name: Bernard
Last name: Simmons

Feature Request: Allow Windows users to define custom directory for configuration (.xml) files

#1 Post by iambesi » 2021-12-05 01:55

Hello FileZilla Developers,

In the FileZilla Client, the Windows version defaults to saving the configuration files -- i.e., filezilla.xml, layout.xml, and recentservers.xml -- to the %APPDATA%\FileZilla directory (or the current directory of the filezilla.exe executable if (and only if) for some reason the aforementioned directory fails.) On the Linux version, however, it checks if the $XDG_CONFIG_HOME environment variable is defined, followed by the $HOME/.config and $HOME/filezilla directories respectively. And if found, it looks like it tries to use the $XDG_CONFIG_HOME/filezilla directory as the preferred one.

For that reason, I am wondering why is there not a similar behaviour in the Windows version? In the case of the installed version, it makes perfect sense to use the %APPDATA%\FileZilla directory; however, when using the ‘portable’ (.zip) version, there should at least be some flexibility via a specific environment variable or the like. Case in point, if a user has FileZilla on a USB drive and uses it on PC 1, the configuration and preferences are saved locally; and consequently, when said user moves his or her USB drive to a different PC, the settings are left behind on the previous PC.

With that said, I propose having an environment variable -- e.g., FZ_CONFIG_ROOT -- in Windows that could be checked and used as the directory for saving configuration files. Looking at source code -- specifically in the commonui\fz_paths.cpp file, I think that it would be fairly easily to make this tweak. While I am not a proper developer, I took a stab at updating the existing code (as seen below.)

[ fz_paths.cpp ]

Code: Select all

#ifndef FZ_WINDOWS
namespace {
static std::wstring TryDirectory(std::wstring path, std::wstring const& suffix, bool check_exists)
{
	if (!path.empty() && path[0] == '/') {
		if (path[path.size() - 1] != '/') {
			path += '/';
		}

		path += suffix;

		if (check_exists) {
			if (!CLocalPath(path).Exists(nullptr)) {
				path.clear();
			}
		}
	}
	else {
		path.clear();
	}
	return path;
}
}
// BEGIN ADDED SECTION.
#else
namespace {
static std::wstring TryDirectory(std::wstring path, std::wstring const& suffix, bool check_exists)
{
	if (!path.empty()) {
		if (path[path.size() - 1] == '\\') {
			path = path.substr(0, path.size() - 1);
		
			if (check_exists) {
				if (!CLocalPath(path).Exists(nullptr)) {
					path.clear();
				}
			}
		}
	}
	else {
		path.clear();
	}
	return path;
}
}
// END ADDED SECTION.
#endif

[ … ]

CLocalPath GetUnadjustedSettingsDir()
{
	CLocalPath ret;

#ifdef FZ_WINDOWS
	wchar_t* out{};
	
	// BEGIN ADDED SECTION.
	
	// Check if the user has set the FZ_CONFIG_ROOT environment variable.
	if ( GetEnv("FZ_CONFIG_ROOT") != null )
	{
		std::wstring cfg = TryDirectory(GetEnv("FZ_CONFIG_ROOT"), L"", true);  // check if the path truly exists.
		
		if (!cfg.empty()) {  // if it does, set it and append the '.config' subdirectory to the specified root.
			std:wstring const& dir = cfg;
			ret.SetPath(dir);
			ret.AddSegment(L".config");
		}
	}
	
	if ( ret.empty() )  // If the FZ_CONFIG_ROOT environment variable is not set or the specified path does not exist
	{                   // (or if running the installed version of Filezilla), proceed with the normal %APPDATA% path.
	// END ADDED SECTION.
		if (SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, 0, &out) == S_OK) {
			ret.SetPath(out);
			CoTaskMemFree(out);
		}
		if (!ret.empty()) {
			ret.AddSegment(L"FileZilla");
		}
	}

	if (ret.empty()) {
		// Fall back to directory where the executable is
		std::wstring const& dir = GetOwnExecutableDir();
		ret.SetPath(dir);
	}
#else
	std::wstring cfg = TryDirectory(GetEnv("XDG_CONFIG_HOME"), L"filezilla/", true);
	if (cfg.empty()) {
		cfg = TryDirectory(GetEnv("HOME"), L".config/filezilla/", true);
	}
	if (cfg.empty()) {
		cfg = TryDirectory(GetEnv("HOME"), L".filezilla/", true);
	}
	if (cfg.empty()) {
		cfg = TryDirectory(GetEnv("XDG_CONFIG_HOME"), L"filezilla/", false);
	}
	if (cfg.empty()) {
		cfg = TryDirectory(GetEnv("HOME"), L".config/filezilla/", false);
	}
	if (cfg.empty()) {
		cfg = TryDirectory(GetEnv("HOME"), L".filezilla/", false);
	}
	ret.SetPath(cfg);
#endif
	return ret;
}
[ … ]
In short, I really enjoy using FileZilla for my secure SFTP connections and it is hands down better than WinSCP any day. Thus, I truly hope that this code (or similar) can be implemented in a very near-future version of FileZilla.

Thanks and regards,
iambesi

User avatar
boco
Contributor
Posts: 26899
Joined: 2006-05-01 03:28
Location: Germany

Re: Feature Request: Allow Windows users to define custom directory for configuration (.xml) files

#2 Post by boco » 2021-12-05 02:52

That functionality is set via fzdefaults.xml - a template skeleton of that file is located in the .\docs subdirectory. Instructions are inside.
### BEGIN SIGNATURE BLOCK ###
No support requests per PM! You will NOT get any reply!!!
FTP connection problems? Please do yourself a favor and read Network Configuration.
FileZilla connection test: https://filezilla-project.org/conntest.php
### END SIGNATURE BLOCK ###

iambesi
500 Command not understood
Posts: 2
Joined: 2021-12-03 01:43
First name: Bernard
Last name: Simmons

Re: Feature Request: Allow Windows users to define custom directory for configuration (.xml) files

#3 Post by iambesi » 2021-12-09 01:17

Hello boco,

You hit the nail on the head! This is exactly what I was looking to do, and now, I am cooking on gas. 8) I truly thank you for your help!

Best regards,
iambesi

Post Reply