29#include <opendht/crypto.h>
32#include <TargetConditionals.h>
35#if defined(__ANDROID__) || (defined(TARGET_OS_IOS) && TARGET_OS_IOS)
66#if !defined __ANDROID__ && !defined _WIN32
70#include <nettle/sha3.h>
85#include <pjlib-util/md5.h>
88#define PROTECTED_GETENV(str) \
90 char* envvar_ = getenv((str)); \
91 envvar_ ? envvar_ : ""; \
94#define XDG_DATA_HOME (PROTECTED_GETENV("XDG_DATA_HOME"))
95#define XDG_CONFIG_HOME (PROTECTED_GETENV("XDG_CONFIG_HOME"))
96#define XDG_CACHE_HOME (PROTECTED_GETENV("XDG_CACHE_HOME"))
99winGetEnv(
const wchar_t* name)
101 const DWORD buffSize = 65535;
102 static wchar_t buffer[buffSize];
103 if (GetEnvironmentVariable(name, buffer, buffSize)) {
110#define PROTECTED_GETENV(str) winGetEnv(str)
112#define JAMI_DATA_HOME PROTECTED_GETENV(L"JAMI_DATA_HOME")
113#define JAMI_CONFIG_HOME PROTECTED_GETENV(L"JAMI_CONFIG_HOME")
114#define JAMI_CACHE_HOME PROTECTED_GETENV(L"JAMI_CACHE_HOME")
117#define PIDFILE ".ring.pid"
118#define ERASE_BLOCK 4096
131const std::filesystem::path&
141#if defined __ANDROID__ || defined _MSC_VER || defined WIN32 || defined __APPLE__
142 JAMI_ERR(
"Path expansion not implemented, returning original");
153 JAMI_ERR(
"Illegal occurrence of newline or one of |, &, ;, <, >, "
157 JAMI_ERR(
"An undefined shell variable was referenced");
160 JAMI_ERR(
"Command substitution occurred");
171 result = std::string(p.we_wordv[0]);
222 auto status = std::filesystem::symlink_status(
linkFile,
ec);
223 if (status.type() != std::filesystem::file_type::not_found) {
224 if (status.type() == std::filesystem::file_type::symlink
231 if (status.type() == std::filesystem::file_type::regular
232 || status.type() == std::filesystem::file_type::symlink) {
246 std::string_view result;
250 if (result.size() >= 8)
258 return not path.empty()
and path.is_relative();
264 if (base.empty()
or path.size() < base.size())
268 return path.substr(
base_sep.size());
274getFullPath(
const std::filesystem::path& base,
const std::filesystem::path& path)
300 throw std::runtime_error(
"Unable to read file: " + path.string());
302 file.seekg(0, std::ios::end);
303 auto size =
file.tellg();
304 if (size > std::numeric_limits<unsigned>::max())
305 throw std::runtime_error(
"File is too big: " + path.string());
307 file.seekg(0, std::ios::beg);
309 throw std::runtime_error(
"Unable to load file: " + path.string());
316 std::ofstream
file(path, std::ios::trunc | std::ios::binary);
317 if (!
file.is_open()) {
318 JAMI_ERROR(
"Unable to write data to {}", path);
324 if (
chmod(path.c_str(), mode) < 0)
334 auto writeTime = std::filesystem::last_write_time(path,
ec);
336 throw std::runtime_error(
"unable to get last write time of file");
339 throw std::runtime_error(
"file too old " + dht::print_time_relative(
now,
writeTime));
341 JAMI_LOG(
"Loading cache file '{}'", path);
342 return dhtnet::fileutils::loadFile(path);
350 auto writeTime = std::filesystem::last_write_time(path,
ec);
352 throw std::runtime_error(
"unable to get last write time of file");
355 throw std::runtime_error(
"file too old " + dht::print_time_relative(
now,
writeTime));
357 JAMI_LOG(
"Loading cache file '{}'", path);
362readArchive(
const std::filesystem::path& path, std::string_view scheme,
const std::string&
pwd)
364 JAMI_LOG(
"Reading archive from {} with scheme '{}'", path, scheme);
372 return data.size() > 3 && data[0] == 0x1f && data[1] == 0x8b && data[2] == 0x08;
375 auto decompress = [](std::vector<uint8_t>& data) {
378 }
catch (
const std::exception&
e) {
379 JAMI_ERROR(
"Error decrypting archive: {}",
e.what());
389 }
catch (
const std::exception&
e) {
396 JAMI_WARNING(
"A gunzip in a gunzip is detected. A webserver may have a bad config");
409 }
catch (
const std::exception&
e) {
410 JAMI_ERROR(
"Error decrypting archive: {}",
e.what());
417 }
catch (
const std::exception&
e) {
418 JAMI_ERROR(
"Error decrypting archive: {}",
e.what());
424 JAMI_WARNING(
"A gunzip in a gunzip is detected. A webserver may have a bad config");
433 const std::filesystem::path& path,
434 std::string_view scheme,
435 const std::string& password,
436 const std::vector<uint8_t>& password_salt)
438 JAMI_LOG(
"Writing archive to {} using scheme '{}'", path, scheme);
446 }
catch (
const std::runtime_error&
ex) {
454 }
catch (
const std::runtime_error&
ex) {
471#if defined(__ANDROID__) || (defined(TARGET_OS_IOS) && TARGET_OS_IOS)
472 std::vector<std::string>
paths;
478#elif defined(__APPLE__)
494const std::filesystem::path&
504#if defined(__ANDROID__) || (defined(TARGET_OS_IOS) && TARGET_OS_IOS)
505 std::vector<std::string>
paths;
537const std::filesystem::path&
547#if defined(__ANDROID__) || (defined(TARGET_OS_IOS) && TARGET_OS_IOS)
548 std::vector<std::string>
paths;
554#elif defined(__APPLE__)
576const std::filesystem::path&
587#if defined(__ANDROID__) || (defined(TARGET_OS_IOS) && TARGET_OS_IOS)
588 std::vector<std::string>
paths;
592#elif defined(__APPLE__)
610 if (!dhtnet::fileutils::recursive_mkdir(
configdir, 0700)) {
618const std::filesystem::path&
635 JAMI_WARN(
"Unable to open file %s for erasing.", path.c_str());
641 JAMI_WARN(
"Unable to erase file %s: GetFileSizeEx() failed.", path.c_str());
645 if (size.QuadPart == 0) {
657 }
catch (std::bad_alloc&
ba) {
658 JAMI_WARN(
"Unable to allocate buffer for erasing %s.", path.c_str());
665 if (size.QuadPart < (1024 - 42)) {
673 ovlp.Offset = offset & 0x00000000FFFFFFFF;
674 ovlp.OffsetHigh = offset >> 32;
693 if (
stat(path.c_str(), &
st) == -1) {
694 JAMI_WARN(
"Unable to erase file %s: fstat() failed.", path.c_str());
702 JAMI_WARN(
"Unable to open file %s for erasing.", path.c_str());
706 if (
st.st_size == 0) {
713 std::array<char, ERASE_BLOCK>
buffer;
719 JAMI_WARNING(
"Error while overriding file with zeros.");
744remove(
const std::filesystem::path& path,
bool erase)
746 if (erase
and dhtnet::fileutils::isFile(path,
false)
and !dhtnet::fileutils::hasHardLink(path))
751 if (std::filesystem::is_directory(path))
755 return std::remove(path.string().c_str());
765 if (
not std::filesystem::is_regular_file(path)) {
766 JAMI_ERROR(
"Unable to compute sha3sum of {}: not a regular file", path);
769 std::ifstream
file(path, std::ios::binary | std::ios::in);
771 JAMI_ERROR(
"Unable to compute sha3sum of {}: failed to open file", path);
783 }
catch (
const std::exception&
e) {
784 JAMI_ERROR(
"Unable to compute sha3sum of {}: {}", path,
e.what());
823 return std::chrono::duration_cast<std::chrono::seconds>(
lastWrite.time_since_epoch()).count();
850 std::filesystem::create_directories(
localDir,
ec);
#define PROTECTED_GETENV(str)
#define DIR_SEPARATOR_STR
#define JAMI_ERROR(formatstr,...)
#define JAMI_DEBUG(formatstr,...)
#define JAMI_WARNING(formatstr,...)
#define JAMI_LOG(formatstr,...)
void compressGzip(const std::string &str, const std::string &path)
Compress string to a Gzip file.
std::vector< uint8_t > decompress(const std::vector< uint8_t > &str)
Decompress an STL string using zlib and return the original data.
std::vector< uint8_t > compress(const std::string &str)
Compress a STL string using zlib with given compression level and return the binary data.
std::vector< unsigned char > decode(std::string_view str)
bool createSymlink(const std::filesystem::path &linkFile, const std::filesystem::path &target)
const std::filesystem::path & get_data_dir()
void set_resource_dir_path(const std::filesystem::path &resourceDirPath)
Set the program's resource directory path.
std::vector< uint8_t > loadCacheFile(const std::filesystem::path &path, std::chrono::system_clock::duration maxAge)
static constexpr auto ARCHIVE_AUTH_SCHEME_PASSWORD
int accessFile(const std::string &file, int mode)
Windows compatibility wrapper for checking read-only attribute.
std::string getOrCreateLocalDeviceId()
std::string sha3File(const std::filesystem::path &path)
std::filesystem::path get_home_dir_impl()
int remove(const std::filesystem::path &path, bool erase)
bool createFileLink(const std::filesystem::path &linkFile, const std::filesystem::path &target, bool hard)
void saveFile(const std::filesystem::path &path, const uint8_t *data, size_t data_size, mode_t UNUSED mode)
bool eraseFile(const std::string &path, bool dosync)
static constexpr auto ARCHIVE_AUTH_SCHEME_NONE
std::string getCleanPath(const std::string &base, const std::string &path)
If path is contained in base, return the suffix, otherwise return the full path.
ArchiveStorageData readArchive(const std::filesystem::path &path, std::string_view scheme, const std::string &pwd)
static std::filesystem::path resource_dir_path
const std::filesystem::path & get_config_dir()
bool createHardlink(const std::filesystem::path &linkFile, const std::filesystem::path &target)
std::string loadCacheTextFile(const std::filesystem::path &path, std::chrono::system_clock::duration maxAge)
std::vector< uint8_t > loadFile(const std::filesystem::path &path, const std::filesystem::path &default_dir)
Read the full content of a file at path.
uint64_t lastWriteTimeInSeconds(const std::filesystem::path &filePath)
Return the last write time (epoch time) of a given file path (in seconds).
static constexpr auto ARCHIVE_AUTH_SCHEME_KEY
bool isPathRelative(const std::filesystem::path &path)
std::string sha3sum(const std::vector< uint8_t > &buffer)
std::string_view getFileExtension(std::string_view filename)
const std::filesystem::path & get_cache_dir()
bool isDirectoryWritable(const std::string &directory)
std::filesystem::path getFullPath(const std::filesystem::path &base, const std::filesystem::path &path)
If path is relative, it is appended to base.
bool writeArchive(const std::string &archive_str, const std::filesystem::path &path, std::string_view scheme, const std::string &password, const std::vector< uint8_t > &password_salt)
const std::filesystem::path & get_resource_dir_path()
Get the resource directory path that was set with set_resource_dir_path.
std::string expand_path(const std::string &path)
Expand the given path.
const std::filesystem::path & get_home_dir()
std::string loadTextFile(const std::filesystem::path &path, const std::filesystem::path &default_dir)
bool eraseFile_posix(const std::string &path, bool dosync)
void emitSignal(Args... args)
std::string to_hex_string(uint64_t id)
std::string to_string(double value)
std::vector< uint8_t > salt