diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2020-01-08 22:32:54 +0100 |
|---|---|---|
| committer | Even Rouault <even.rouault@spatialys.com> | 2020-01-08 22:32:54 +0100 |
| commit | 9263e1d36eec53ee3c4e4d04da93a032c0596eec (patch) | |
| tree | 12afe91a09b60a9ae2a1b2fbff8fa81b24ceee41 /src | |
| parent | da93fe3bea35ae8d2383e6006b7775bb96af6885 (diff) | |
| download | PROJ-9263e1d36eec53ee3c4e4d04da93a032c0596eec.tar.gz PROJ-9263e1d36eec53ee3c4e4d04da93a032c0596eec.zip | |
Add capability to read resource files from the user writable directory
Diffstat (limited to 'src')
| -rw-r--r-- | src/4D_api.cpp | 11 | ||||
| -rw-r--r-- | src/filemanager.cpp | 77 | ||||
| -rw-r--r-- | src/filemanager.hpp | 8 | ||||
| -rw-r--r-- | src/open_lib.cpp | 21 | ||||
| -rw-r--r-- | src/proj_internal.h | 4 |
5 files changed, 84 insertions, 37 deletions
diff --git a/src/4D_api.cpp b/src/4D_api.cpp index cee8262e..9107723d 100644 --- a/src/4D_api.cpp +++ b/src/4D_api.cpp @@ -48,6 +48,7 @@ #include <math.h> #include "geodesic.h" #include "grids.hpp" +#include "filemanager.hpp" #include "proj/common.hpp" #include "proj/coordinateoperation.hpp" @@ -1450,6 +1451,16 @@ PJ_INFO proj_info (void) { /* build search path string */ auto ctx = pj_get_default_ctx(); if (!ctx || ctx->search_paths.empty()) { + // Env var mostly for testing purposes and being independent from + // an existing installation + const char* ignoreUserWritableDirectory = + getenv("PROJ_IGNORE_USER_WRITABLE_DIRECTORY"); + if( ignoreUserWritableDirectory == nullptr || + ignoreUserWritableDirectory[0] == '\0' ) { + buf = path_append(buf, + pj_context_get_user_writable_directory(ctx, false).c_str(), + &buf_size); + } const char *envPROJ_LIB = getenv("PROJ_LIB"); buf = path_append(buf, envPROJ_LIB, &buf_size); #ifdef PROJ_LIB diff --git a/src/filemanager.cpp b/src/filemanager.cpp index 1a94216d..1c49a16b 100644 --- a/src/filemanager.cpp +++ b/src/filemanager.cpp @@ -2294,48 +2294,61 @@ static void CreateDirectory(const std::string &path) { // --------------------------------------------------------------------------- -std::string pj_context_get_grid_cache_filename(PJ_CONTEXT *ctx) { - pj_load_ini(ctx); - if (!ctx->gridChunkCache.filename.empty()) { - return ctx->gridChunkCache.filename; - } - std::string path; +std::string pj_context_get_user_writable_directory(PJ_CONTEXT *ctx, + bool create) { + if (ctx->user_writable_directory.empty()) { + std::string path; #ifdef _WIN32 - std::wstring wPath; - wPath.resize(MAX_PATH); - if (SHGetFolderPathW(nullptr, CSIDL_LOCAL_APPDATA, nullptr, 0, &wPath[0]) == - S_OK) { - wPath.resize(wcslen(wPath.data())); - path = WStringToUTF8(wPath); - } else { - const char *local_app_data = getenv("LOCALAPPDATA"); - if (!local_app_data) { - local_app_data = getenv("TEMP"); + std::wstring wPath; + wPath.resize(MAX_PATH); + if (SHGetFolderPathW(nullptr, CSIDL_LOCAL_APPDATA, nullptr, 0, + &wPath[0]) == S_OK) { + wPath.resize(wcslen(wPath.data())); + path = WStringToUTF8(wPath); + } else { + const char *local_app_data = getenv("LOCALAPPDATA"); if (!local_app_data) { - local_app_data = "c:/users"; + local_app_data = getenv("TEMP"); + if (!local_app_data) { + local_app_data = "c:/users"; + } } + path = local_app_data; } - path = local_app_data; - } #else - const char *xdg_data_home = getenv("XDG_DATA_HOME"); - if (xdg_data_home != nullptr) { - path = xdg_data_home; - } else { - const char *home = getenv("HOME"); - if (home) { + const char *xdg_data_home = getenv("XDG_DATA_HOME"); + if (xdg_data_home != nullptr) { + path = xdg_data_home; + } else { + const char *home = getenv("HOME"); + if (home) { #if defined(__MACH__) && defined(__APPLE__) - path = std::string(home) + "/Library/Logs"; + path = std::string(home) + "/Library/Logs"; #else - path = std::string(home) + "/.local/share"; + path = std::string(home) + "/.local/share"; #endif - } else { - path = "/tmp"; + } else { + path = "/tmp"; + } } - } #endif - path += "/proj"; - CreateDirectory(path); + path += "/proj"; + ctx->user_writable_directory = path; + } + if (create) { + CreateDirectory(ctx->user_writable_directory); + } + return ctx->user_writable_directory; +} + +// --------------------------------------------------------------------------- + +std::string pj_context_get_grid_cache_filename(PJ_CONTEXT *ctx) { + pj_load_ini(ctx); + if (!ctx->gridChunkCache.filename.empty()) { + return ctx->gridChunkCache.filename; + } + const std::string path(pj_context_get_user_writable_directory(ctx, true)); ctx->gridChunkCache.filename = path + "/cache.db"; return ctx->gridChunkCache.filename; } diff --git a/src/filemanager.hpp b/src/filemanager.hpp index 11fb6356..9793267c 100644 --- a/src/filemanager.hpp +++ b/src/filemanager.hpp @@ -33,10 +33,10 @@ #include "proj.h" #include "proj/util.hpp" -NS_PROJ_START - //! @cond Doxygen_Suppress +NS_PROJ_START + class File; class FileManager { @@ -74,8 +74,8 @@ class File { const std::string &name() const { return name_; } }; -//! @endcond Doxygen_Suppress - NS_PROJ_END +//! @endcond Doxygen_Suppress + #endif // FILEMANAGER_HPP_INCLUDED
\ No newline at end of file diff --git a/src/open_lib.cpp b/src/open_lib.cpp index 222dd757..ae387281 100644 --- a/src/open_lib.cpp +++ b/src/open_lib.cpp @@ -224,6 +224,16 @@ static bool is_rel_or_absolute_filename(const char *name) || (name[0] != '\0' && name[1] == ':' && strchr(dir_chars,name[2])); } +static bool ignoreUserWritableDirectory() +{ + // Env var mostly for testing purposes and being independent from + // an existing installation + const char* envVarIgnoreUserWritableDirectory = + getenv("PROJ_IGNORE_USER_WRITABLE_DIRECTORY"); + return envVarIgnoreUserWritableDirectory != nullptr && + envVarIgnoreUserWritableDirectory[0] != '\0'; +} + static void* pj_open_lib_internal(projCtx ctx, const char *name, const char *mode, void* (*open_file)(projCtx, const char*, const char*), @@ -279,6 +289,17 @@ pj_open_lib_internal(projCtx ctx, const char *name, const char *mode, break; } } + + else if( !ignoreUserWritableDirectory() && + (fid = open_file(ctx, + (pj_context_get_user_writable_directory(ctx, false) + + DIR_CHAR + name).c_str(), mode)) != nullptr ) { + fname = pj_context_get_user_writable_directory(ctx, false); + fname += DIR_CHAR; + fname += name; + sysname = fname.c_str(); + } + /* if is environment PROJ_LIB defined */ else if ((sysname = getenv("PROJ_LIB")) != nullptr) { auto paths = NS_PROJ::internal::split(std::string(sysname), dirSeparator); diff --git a/src/proj_internal.h b/src/proj_internal.h index 63c53551..ce7b9d74 100644 --- a/src/proj_internal.h +++ b/src/proj_internal.h @@ -709,6 +709,7 @@ struct projCtx_t { bool iniFileLoaded = false; std::string endpoint{}; + std::string user_writable_directory{}; projGridChunkCache gridChunkCache{}; int projStringParserCreateFromPROJStringRecursionCounter = 0; // to avoid potential infinite recursion in PROJStringParser::createFromPROJString() @@ -844,8 +845,9 @@ std::string pj_context_get_url_endpoint(PJ_CONTEXT* ctx); void pj_load_ini(PJ_CONTEXT* ctx); -// For testing purposes +// Exported for testing purposes only std::string PROJ_DLL pj_context_get_grid_cache_filename(PJ_CONTEXT *ctx); +std::string PROJ_DLL pj_context_get_user_writable_directory(PJ_CONTEXT *ctx, bool create); /* classic public API */ #include "proj_api.h" |
