aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2020-01-08 22:32:54 +0100
committerEven Rouault <even.rouault@spatialys.com>2020-01-08 22:32:54 +0100
commit9263e1d36eec53ee3c4e4d04da93a032c0596eec (patch)
tree12afe91a09b60a9ae2a1b2fbff8fa81b24ceee41 /src
parentda93fe3bea35ae8d2383e6006b7775bb96af6885 (diff)
downloadPROJ-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.cpp11
-rw-r--r--src/filemanager.cpp77
-rw-r--r--src/filemanager.hpp8
-rw-r--r--src/open_lib.cpp21
-rw-r--r--src/proj_internal.h4
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"