Merge pull request #561 from bschramke/develop

Support for XDG Base Directory Specification
This commit is contained in:
Aleksandar Fabijanic 2015-02-09 21:04:28 -06:00
commit c00f13d277
12 changed files with 399 additions and 2 deletions

View File

@ -291,9 +291,37 @@ public:
static std::string home();
/// Returns the user's home directory.
static std::string configHome();
/// Returns the user's config directory.
///
/// On Unix systems, this is the '~/.config/'. On Windows systems,
/// this is '%APPDATA%'.
static std::string dataHome();
/// Returns the user's data directory.
///
/// On Unix systems, this is the '~/.local/share/'. On Windows systems,
/// this is '%APPDATA%'.
static std::string tempHome();
/// Returns the user's temp directory.
///
/// On Unix systems, this is the '~/.local/temp/'.
static std::string cacheHome();
/// Returns the user's cache directory.
///
/// On Unix systems, this is the '~/.cache/'. On Windows systems,
/// this is '%APPDATA%'.
static std::string temp();
/// Returns the temporary directory.
static std::string config();
/// Returns the systemwide config directory.
///
/// On Unix systems, this is the '/etc/'.
static std::string null();
/// Returns the name of the null device.

View File

@ -32,7 +32,12 @@ class PathImpl
public:
static std::string currentImpl();
static std::string homeImpl();
static std::string configHomeImpl();
static std::string dataHomeImpl();
static std::string tempHomeImpl();
static std::string cacheHomeImpl();
static std::string tempImpl();
static std::string configImpl();
static std::string nullImpl();
static std::string expandImpl(const std::string& path);
static void listRootsImpl(std::vector<std::string>& roots);

View File

@ -32,7 +32,12 @@ class Foundation_API PathImpl
public:
static std::string currentImpl();
static std::string homeImpl();
static std::string configHomeImpl();
static std::string dataHomeImpl();
static std::string cacheHomeImpl();
static std::string tempHomeImpl();
static std::string tempImpl();
static std::string configImpl();
static std::string nullImpl();
static std::string systemImpl();
static std::string expandImpl(const std::string& path);

View File

@ -32,7 +32,12 @@ class Foundation_API PathImpl
public:
static std::string currentImpl();
static std::string homeImpl();
static std::string configHomeImpl();
static std::string dataHomeImpl();
static std::string cacheHomeImpl();
static std::string tempHomeImpl();
static std::string tempImpl();
static std::string configImpl();
static std::string nullImpl();
static std::string systemImpl();
static std::string expandImpl(const std::string& path);

View File

@ -595,11 +595,60 @@ std::string Path::home()
}
std::string Path::configHome()
{
#if defined(POCO_OS_FAMILY_UNIX) || defined(POCO_OS_FAMILY_WINDOWS)
return PathImpl::configHomeImpl();
#else
return PathImpl::homeImpl();
#endif
}
std::string Path::dataHome()
{
#if defined(POCO_OS_FAMILY_UNIX) || defined(POCO_OS_FAMILY_WINDOWS)
return PathImpl::dataHomeImpl();
#else
return PathImpl::homeImpl();
#endif
}
std::string Path::tempHome()
{
#if defined(POCO_OS_FAMILY_UNIX) || defined(POCO_OS_FAMILY_WINDOWS)
return PathImpl::tempHomeImpl();
#else
return PathImpl::tempImpl();
#endif
}
std::string Path::cacheHome()
{
#if defined(POCO_OS_FAMILY_UNIX) || defined(POCO_OS_FAMILY_WINDOWS)
return PathImpl::cacheHomeImpl();
#else
return PathImpl::homeImpl();
#endif
}
std::string Path::temp()
{
return PathImpl::tempImpl();
}
std::string Path::config()
{
#if defined(POCO_OS_FAMILY_UNIX) || defined(POCO_OS_FAMILY_WINDOWS)
return PathImpl::configImpl();
#else
return PathImpl::currentImpl();
#endif
}
std::string Path::null()
{

View File

@ -76,6 +76,82 @@ std::string PathImpl::homeImpl()
}
std::string PathImpl::configHomeImpl()
{
#if defined(POCO_VXWORKS)
return PathImpl::homeImpl();
#else
std::string path = PathImpl::homeImpl();
std::string::size_type n = path.size();
if (n > 0 && path[n - 1] == '/')
#if POCO_OS == POCO_OS_MAC_OS_X
path.append("Library/Preferences/");
#else
path.append(".config/");
#endif
return path;
#endif
}
std::string PathImpl::dataHomeImpl()
{
#if defined(POCO_VXWORKS)
return PathImpl::homeImpl();
#else
std::string path = PathImpl::homeImpl();
std::string::size_type n = path.size();
if (n > 0 && path[n - 1] == '/')
#if POCO_OS == POCO_OS_MAC_OS_X
path.append("Library/Application Support/");
#else
path.append(".local/share/");
#endif
return path;
#endif
}
std::string PathImpl::cacheHomeImpl()
{
#if defined(POCO_VXWORKS)
return PathImpl::tempImpl();
#else
std::string path = PathImpl::homeImpl();
std::string::size_type n = path.size();
if (n > 0 && path[n - 1] == '/')
#if POCO_OS == POCO_OS_MAC_OS_X
path.append("Library/Caches/");
#else
path.append(".cache/");
#endif
return path;
#endif
}
std::string PathImpl::tempHomeImpl()
{
#if defined(POCO_VXWORKS)
return PathImpl::tempImpl();
#else
std::string path = PathImpl::homeImpl();
std::string::size_type n = path.size();
if (n > 0 && path[n - 1] == '/')
#if POCO_OS == POCO_OS_MAC_OS_X
path.append("Library/Caches/");
#else
path.append(".local/tmp/");
#endif
return path;
#endif
}
std::string PathImpl::tempImpl()
{
std::string path;
@ -94,6 +170,19 @@ std::string PathImpl::tempImpl()
}
std::string PathImpl::configImpl()
{
std::string path;
#if POCO_OS == POCO_OS_MAC_OS_X
path = "/Library/Preferences/";
#else
path = "/etc/";
#endif
return path;
}
std::string PathImpl::nullImpl()
{
#if defined(POCO_VXWORKS)

View File

@ -76,6 +76,59 @@ std::string PathImpl::homeImpl()
}
std::string PathImpl::configHomeImpl()
{
std::string result;
// if APPDATA environment variable not exist, return home directory instead
try
{
result = EnvironmentImpl::getImpl("APPDATA");
}
catch (NotFoundException&)
{
result = homeImpl();
}
std::string::size_type n = result.size();
if (n > 0 && result[n - 1] != '\\')
result.append("\\");
return result;
}
std::string PathImpl::dataHomeImpl()
{
std::string result;
// if LOCALAPPDATA environment variable not exist, return config home instead
try
{
result = EnvironmentImpl::getImpl("LOCALAPPDATA");
}
catch (NotFoundException&)
{
result = configHomeImpl();
}
std::string::size_type n = result.size();
if (n > 0 && result[n - 1] != '\\')
result.append("\\");
return result;
}
std::string PathImpl::cacheHomeImpl()
{
return tempImpl();
}
std::string PathImpl::tempHomeImpl()
{
return tempImpl();
}
std::string PathImpl::tempImpl()
{
char buffer[MAX_PATH];
@ -93,6 +146,26 @@ std::string PathImpl::tempImpl()
}
std::string PathImpl::configImpl()
{
std::string result;
// if PROGRAMDATA environment variable not exist, return system directory instead
try
{
result = EnvironmentImpl::getImpl("PROGRAMDATA");
}
catch (NotFoundException&)
{
result = systemImpl();
}
std::string::size_type n = result.size();
if (n > 0 && result[n - 1] != '\\')
result.append("\\");
return result;
}
std::string PathImpl::nullImpl()
{
return "NUL:";

View File

@ -86,6 +86,59 @@ std::string PathImpl::homeImpl()
}
std::string PathImpl::configHomeImpl()
{
std::string result;
// if APPDATA environment variable no exist, return home directory instead
try
{
result = EnvironmentImpl::getImpl("APPDATA");
}
catch (NotFoundException&)
{
result = homeImpl();
}
std::string::size_type n = result.size();
if (n > 0 && result[n - 1] != '\\')
result.append("\\");
return result;
}
std::string PathImpl::dataHomeImpl()
{
std::string result;
// if LOCALAPPDATA environment variable no exist, return config home instead
try
{
result = EnvironmentImpl::getImpl("LOCALAPPDATA");
}
catch (NotFoundException&)
{
result = configHomeImpl();
}
std::string::size_type n = result.size();
if (n > 0 && result[n - 1] != '\\')
result.append("\\");
return result;
}
std::string PathImpl::cacheHomeImpl()
{
return tempImpl();
}
std::string PathImpl::tempHomeImpl()
{
return tempImpl();
}
std::string PathImpl::tempImpl()
{
Buffer<wchar_t> buffer(MAX_PATH_LEN);
@ -104,6 +157,26 @@ std::string PathImpl::tempImpl()
}
std::string PathImpl::configImpl()
{
std::string result;
// if PROGRAMDATA environment variable not exist, return system directory instead
try
{
result = EnvironmentImpl::getImpl("PROGRAMDATA");
}
catch (NotFoundException&)
{
result = systemImpl();
}
std::string::size_type n = result.size();
if (n > 0 && result[n - 1] != '\\')
result.append("\\");
return result;
}
std::string PathImpl::nullImpl()
{
return "NUL:";

View File

@ -76,7 +76,10 @@ class Util_API Application: public Subsystem
/// - application.name: the file name of the application executable
/// - application.baseName: the file name (excluding extension) of the application executable
/// - application.dir: the path to the directory where the application executable resides
/// - application.configDir: the path to the directory where the last configuration file loaded with loadConfiguration() was found.
/// - application.configDir: the path to the directory where user specific configuration files of the application should be stored.
/// - application.cacheDir: the path to the directory where user specific non-essential data files of the application should be stored.
/// - application.dataDir: the path to the directory where user specific data files of the application should be stored.
/// - application.tempDir: the path to the directory where user specific temporary files and other file objects of the application should be stored.
///
/// If loadConfiguration() has never been called, application.configDir will be equal to application.dir.
///
@ -371,6 +374,7 @@ private:
void getApplicationPath(Poco::Path& path) const;
void processOptions();
bool findAppConfigFile(const std::string& appName, const std::string& extension, Poco::Path& path) const;
bool findAppConfigFile(const Path& basePath, const std::string& appName, const std::string& extension, Poco::Path& path) const;
typedef Poco::AutoPtr<LayeredConfiguration> ConfigPtr;

View File

@ -41,7 +41,12 @@ class Util_API SystemConfiguration: public AbstractConfiguration
/// of the first Ethernet adapter found on the system.
/// - system.currentDir: the current working directory
/// - system.homeDir: the user's home directory
/// - system.configHomeDir: the base directory relative to which user specific configuration files should be stored
/// - system.cacheHomeDir: the base directory relative to which user specific non-essential data files should be stored
/// - system.dataHomeDir: the base directory relative to which user specific data files should be stored
/// - system.tempHomeDir: the base directory relative to which user-specific temporary files and other file objects should be placed
/// - system.tempDir: the system's temporary directory
/// - system.configDir: the system's configuration directory
/// - system.dateTime: the current UTC date and time, formatted in ISO 8601 format.
/// - system.pid: the current process ID.
/// - system.env.<NAME>: the environment variable with the given <NAME>.
@ -76,7 +81,12 @@ private:
static const std::string NODEID;
static const std::string CURRENTDIR;
static const std::string HOMEDIR;
static const std::string CONFIGHOMEDIR;
static const std::string CACHEHOMEDIR;
static const std::string DATAHOMEDIR;
static const std::string TEMPHOMEDIR;
static const std::string TEMPDIR;
static const std::string CONFIGDIR;
static const std::string DATETIME;
#if !defined(POCO_VXWORKS)
static const std::string PID;

View File

@ -166,7 +166,10 @@ void Application::init()
_pConfig->setString("application.name", appPath.getFileName());
_pConfig->setString("application.baseName", appPath.getBaseName());
_pConfig->setString("application.dir", appPath.parent().toString());
_pConfig->setString("application.configDir", appPath.parent().toString());
_pConfig->setString("application.configDir", Path::configHome() + appPath.getBaseName() + Path::separator());
_pConfig->setString("application.cacheDir", Path::cacheHome() + appPath.getBaseName() + Path::separator());
_pConfig->setString("application.tempDir", Path::tempHome() + appPath.getBaseName() + Path::separator());
_pConfig->setString("application.dataDir", Path::dataHome() + appPath.getBaseName() + Path::separator());
processOptions();
}
@ -506,6 +509,29 @@ bool Application::findAppConfigFile(const std::string& appName, const std::strin
}
bool Application::findAppConfigFile(const Path& basePath, const std::string& appName, const std::string& extension, Path& path) const
{
poco_assert (!appName.empty());
Path p(basePath,appName);
p.setExtension(extension);
bool found = findFile(p);
if (!found)
{
#if defined(_DEBUG)
if (appName[appName.length() - 1] == 'd')
{
p.setBaseName(appName.substr(0, appName.length() - 1));
found = findFile(p);
}
#endif
}
if (found)
path = p;
return found;
}
void Application::defineOptions(OptionSet& options)
{
for (SubsystemVec::iterator it = _subsystems.begin(); it != _subsystems.end(); ++it)

View File

@ -43,7 +43,12 @@ const std::string SystemConfiguration::NODENAME = "system.nodeName";
const std::string SystemConfiguration::NODEID = "system.nodeId";
const std::string SystemConfiguration::CURRENTDIR = "system.currentDir";
const std::string SystemConfiguration::HOMEDIR = "system.homeDir";
const std::string SystemConfiguration::CONFIGHOMEDIR = "system.configHomeDir";
const std::string SystemConfiguration::CACHEHOMEDIR = "system.cacheHomeDir";
const std::string SystemConfiguration::DATAHOMEDIR = "system.dataHomeDir";
const std::string SystemConfiguration::TEMPHOMEDIR = "system.tempHomeDir";
const std::string SystemConfiguration::TEMPDIR = "system.tempDir";
const std::string SystemConfiguration::CONFIGDIR = "system.configDir";
const std::string SystemConfiguration::DATETIME = "system.dateTime";
#if !defined(POCO_VXWORKS)
const std::string SystemConfiguration::PID = "system.pid";
@ -108,10 +113,30 @@ bool SystemConfiguration::getRaw(const std::string& key, std::string& value) con
{
value = Path::home();
}
else if (key == CONFIGHOMEDIR)
{
value = Path::configHome();
}
else if (key == CACHEHOMEDIR)
{
value = Path::cacheHome();
}
else if (key == DATAHOMEDIR)
{
value = Path::dataHome();
}
else if (key == TEMPHOMEDIR)
{
value = Path::tempHome();
}
else if (key == TEMPDIR)
{
value = Path::temp();
}
else if (key == CONFIGDIR)
{
value = Path::config();
}
else if (key == DATETIME)
{
value = Poco::DateTimeFormatter::format(Poco::DateTime(), Poco::DateTimeFormat::ISO8601_FORMAT);
@ -153,7 +178,12 @@ void SystemConfiguration::enumerate(const std::string& key, Keys& range) const
range.push_back("nodeId");
range.push_back("currentDir");
range.push_back("homeDir");
range.push_back("configHomeDir");
range.push_back("cacheHomeDir");
range.push_back("dataHomeDir");
range.push_back("tempHomeDir");
range.push_back("tempDir");
range.push_back("configDir");
range.push_back("dateTime");
#if !defined(POCO_VXWORKS)
range.push_back("pid");