aboutsummaryrefslogtreecommitdiff
path: root/src/Storage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Storage.cpp')
-rw-r--r--src/Storage.cpp105
1 files changed, 105 insertions, 0 deletions
diff --git a/src/Storage.cpp b/src/Storage.cpp
new file mode 100644
index 0000000..a0cc891
--- /dev/null
+++ b/src/Storage.cpp
@@ -0,0 +1,105 @@
+#include "../include/dchat/Storage.hpp"
+#include "../include/dchat/env.hpp"
+#include "../include/dchat/FileUtil.hpp"
+#include <boost/filesystem/convenience.hpp>
+#include <sibs/SafeSerializer.hpp>
+#include <sibs/SafeDeserializer.hpp>
+
+#if OS_FAMILY == OS_FAMILY_POSIX
+#include <pwd.h>
+#endif
+
+namespace dchat
+{
+ boost::filesystem::path getHomeDir()
+ {
+ #if OS_FAMILY == OS_FAMILY_POSIX
+ const char *homeDir = getenv("HOME");
+ if(!homeDir)
+ {
+ passwd *pw = getpwuid(getuid());
+ homeDir = pw->pw_dir;
+ }
+ return boost::filesystem::path(homeDir);
+ #elif OS_FAMILY == OS_FAMILY_WINDOWS
+ BOOL ret;
+ HANDLE hToken;
+ std::wstring homeDir;
+ DWORD homeDirLen = MAX_PATH;
+ homeDir.resize(homeDirLen);
+
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &hToken))
+ throw std::runtime_error("Failed to open process token");
+
+ if (!GetUserProfileDirectory(hToken, &homeDir[0], &homeDirLen))
+ {
+ CloseHandle(hToken);
+ throw std::runtime_error("Failed to get home directory");
+ }
+
+ CloseHandle(hToken);
+ homeDir.resize(wcslen(homeDir.c_str()));
+ return boost::filesystem::path(homeDir);
+ #endif
+ }
+
+ boost::filesystem::path getDchatDir()
+ {
+ boost::filesystem::path dchatHomeDir = getHomeDir() / ".local" / "share" / "dchat";
+ boost::filesystem::create_directories(dchatHomeDir);
+ return dchatHomeDir;
+ }
+
+ boost::filesystem::path getImagesDir()
+ {
+ boost::filesystem::path imagesDir = getDchatDir() / "images";
+ boost::filesystem::create_directories(imagesDir);
+ return imagesDir;
+ }
+
+ void loadBindsFromFile(LoadBindsCallbackFunc callbackFunc)
+ {
+ assert(callbackFunc);
+ StringView fileContent;
+ try
+ {
+ fileContent = getFileContent(getDchatDir() / "binds");
+ sibs::SafeDeserializer deserializer((const u8*)fileContent.data, fileContent.size);
+
+ while(!deserializer.empty())
+ {
+ u8 keySize = deserializer.extract<u8>();
+ std::string key;
+ key.resize(keySize);
+ deserializer.extract((u8*)&key[0], keySize);
+
+ u8 valueSize = deserializer.extract<u8>();
+ std::string value;
+ value.resize(valueSize);
+ deserializer.extract((u8*)&value[0], valueSize);
+
+ callbackFunc(key, value);
+ }
+ }
+ catch(FileException &e)
+ {
+ fprintf(stderr, "Failed to read binds from file, reason: %s\n", e.what());
+ }
+
+ delete[] fileContent.data;
+ }
+
+ void replaceBindsInFile(const std::unordered_map<std::string, std::string> &binds)
+ {
+ sibs::SafeSerializer serializer;
+ for(auto &it : binds)
+ {
+ serializer.add((u8)it.first.size());
+ serializer.add((const u8*)it.first.data(), it.first.size());
+
+ serializer.add((u8)it.second.size());
+ serializer.add((const u8*)it.second.data(), it.second.size());
+ }
+ fileReplace(getDchatDir() / "binds", StringView((const char*)serializer.getBuffer().data(), serializer.getBuffer().size()));
+ }
+} \ No newline at end of file