diff --git a/MSVC/config.h b/MSVC/config.h index 9fbc913d3e994cc1e28b176bcf705664bb77f4a1..b901b64900de3f93e8fcd5cf1032fd8863d0cc55 100644 --- a/MSVC/config.h +++ b/MSVC/config.h @@ -191,7 +191,8 @@ STACK_DIRECTION = 0 => direction of growth unknown */ #define TIME_WITH_SYS_TIME 1 /* Define to 1 for Unicode (Wide Chars) APIs. */ -/* #undef UNICODE */ +#define UNICODE 1 +#undef _MBCS /* Version number of package */ #define VERSION "2.3.0" diff --git a/MSVC/ring-daemon.vcxproj b/MSVC/ring-daemon.vcxproj index 1f777b471a91858dc8e69007a7348c0092198ab6..487b41eb40ff84205d6ea0fabb9b0f06e87ec794 100644 --- a/MSVC/ring-daemon.vcxproj +++ b/MSVC/ring-daemon.vcxproj @@ -118,7 +118,7 @@ <UseDebugLibraries>false</UseDebugLibraries> <PlatformToolset>v141</PlatformToolset> <WholeProgramOptimization>false</WholeProgramOptimization> - <CharacterSet>MultiByte</CharacterSet> + <CharacterSet>Unicode</CharacterSet> <WindowsAppContainer>false</WindowsAppContainer> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseLib|x64'" Label="Configuration"> @@ -579,7 +579,7 @@ <IntrinsicFunctions>true</IntrinsicFunctions> <SDLCheck>false</SDLCheck> <AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)..\;$(ProjectDir)..\src;$(ProjectDir)..\src\client;$(ProjectDir)..\src\config;$(ProjectDir)..\src\dring;$(ProjectDir)..\src\hooks;$(ProjectDir)..\src\im;$(ProjectDir)..\src\media;$(ProjectDir)..\src\jamidht;$(ProjectDir)..\src\security;$(ProjectDir)..\src\sip;$(ProjectDir)..\src\upnp;$(ProjectDir)..\src\upnp\igd;$(ProjectDir)..\src\upnp\protocol;$(ProjectDir)..\src\upnp\mapping;$(ProjectDir)..\src\jamidht\eth;$(ProjectDir)..\contrib\msvc;$(ProjectDir)..\contrib\msvc\include;$(ProjectDir)..\contrib\build\pupnp\upnp\inc;$(ProjectDir)..\contrib\build\msgpack-c\include;$(ProjectDir)..\contrib\build\jsoncpp\include;$(ProjectDir)..\contrib\build\yaml-cpp\include;$(ProjectDir)..\contrib\build\pjproject\pjlib\include;$(ProjectDir)..\contrib\build\pjproject\pjnath\include;$(ProjectDir)..\contrib\build\pjproject\pjlib-util\include;$(ProjectDir)..\contrib\build\pjproject\pjsip\include;$(ProjectDir)..\contrib\build\pjproject\third_party;$(ProjectDir)..\contrib\build\pjproject\pjmedia\include;$(ProjectDir)..\contrib\build\restbed\source;$(ProjectDir)..\contrib\build\ffmpeg\Build\Windows10\x64\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>RING_UWP;STATICLIB;_USE_MATH_DEFINES;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;NOMINMAX;HAVE_CONFIG_H;WIN32_LEAN_AND_MEAN;WIN32_NATIVE;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <PreprocessorDefinitions>STATICLIB;_USE_MATH_DEFINES;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;NOMINMAX;HAVE_CONFIG_H;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions> <DisableSpecificWarnings>4996;4503;4180;4244;4267;</DisableSpecificWarnings> <SuppressStartupBanner>true</SuppressStartupBanner> <BasicRuntimeChecks> @@ -587,6 +587,7 @@ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> <MultiProcessorCompilation>true</MultiProcessorCompilation> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions> </ClCompile> <Link> <EnableCOMDATFolding>true</EnableCOMDATFolding> diff --git a/src/archiver.cpp b/src/archiver.cpp index 7a68157aa26cce13c13cff789bf949cc0dc5204f..b62fc24d5689d7b8e978747a7bb010cd7cb1b739 100644 --- a/src/archiver.cpp +++ b/src/archiver.cpp @@ -75,7 +75,7 @@ accountToJsonValue(const std::map<std::string, std::string>& details) { i.first == DRing::Account::ConfProperties::TLS::CERTIFICATE_FILE || i.first == DRing::Account::ConfProperties::TLS::PRIVATE_KEY_FILE) { // replace paths by the files content - std::ifstream ifs(i.second); + std::ifstream ifs = fileutils::ifstream(i.second); std::string fileContent((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>()); root[i.first] = fileContent; } else diff --git a/src/data_transfer.cpp b/src/data_transfer.cpp index 05e638b32f6c3bc6b01cc53fb8283e5ad378a71f..5b8a46e56f960d15a0aa1e2240d364743a58af87 100644 --- a/src/data_transfer.cpp +++ b/src/data_transfer.cpp @@ -276,7 +276,7 @@ SubOutgoingFileTransfer::SubOutgoingFileTransfer(DRing::DataTransferId tid, { info_ = metaInfo_->info(); - input_.open(info_.path, std::ios::binary); + fileutils::openStream(input_, info_.path, std::ios::binary); if (!input_) throw std::runtime_error("input file open failed"); metaInfo_->addLinkedTransfer(this); @@ -438,7 +438,7 @@ private: OutgoingFileTransfer::OutgoingFileTransfer(DRing::DataTransferId tid, const DRing::DataTransferInfo& info) : DataTransfer(tid) { - input_.open(info.path, std::ios::binary); + fileutils::openStream(input_, info.path, std::ios::binary); if (!input_) throw std::runtime_error("input file open failed"); @@ -518,7 +518,7 @@ IncomingFileTransfer::start() if (!DataTransfer::start()) return false; - fout_.open(&info_.path[0], std::ios::binary); + fileutils::openStream(fout_, &info_.path[0], std::ios::binary); if (!fout_) { JAMI_ERR() << "[FTP] Can't open file " << info_.path; return false; @@ -725,7 +725,7 @@ DataTransferFacade::acceptAsFile(const DRing::DataTransferId& id, #ifndef _WIN32 iter->second->accept(file_path, offset); #else - iter->second->accept(decodeMultibyteString(file_path), offset); + iter->second->accept(file_path, offset); #endif return DRing::DataTransferError::success; } diff --git a/src/fileutils.cpp b/src/fileutils.cpp index 6e433073efa1788365d8de5ac9b6312ffb3e7a83..cdea17da706326a563ac90bb6e66492211806079 100644 --- a/src/fileutils.cpp +++ b/src/fileutils.cpp @@ -231,23 +231,29 @@ getFileLock(const std::string& path) bool isFile(const std::string& path, bool resolveSymlink) { +#ifdef _WIN32 if (resolveSymlink) { - struct stat s; - if (stat(path.c_str(), &s) == 0) + struct _stat64i32 s; + if (_wstat(jami::to_wstring(path).c_str(), &s) == 0) return S_ISREG(s.st_mode); } else { -#ifdef _WIN32 - DWORD attr = GetFileAttributesA(path.c_str()); + DWORD attr = GetFileAttributes(jami::to_wstring(path).c_str()); if ((attr != INVALID_FILE_ATTRIBUTES) && !(attr & FILE_ATTRIBUTE_DIRECTORY) && !(attr & FILE_ATTRIBUTE_REPARSE_POINT)) return true; + } #else + if (resolveSymlink) { + struct stat s; + if (stat(path.c_str(), &s) == 0) + return S_ISREG(s.st_mode); + } else { struct stat s; if (lstat(path.c_str(), &s) == 0) return S_ISREG(s.st_mode); -#endif } +#endif return false; } @@ -262,10 +268,7 @@ bool isDirectory(const std::string& path) bool isDirectoryWritable(const std::string &directory) { -#ifdef _WIN32 - return access(decodeMultibyteString(directory).c_str(), W_OK) == 0; -#endif - return access(directory.c_str(), W_OK) == 0; + return accessFile(directory, W_OK) == 0; } bool isSymLink(const std::string& path) @@ -301,10 +304,8 @@ writeTime(const std::string& path) ext_params.lpSecurityAttributes = nullptr; ext_params.hTemplateFile = nullptr; HANDLE h = CreateFile2(jami::to_wstring(path).c_str(), GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, &ext_params); -#elif _MSC_VER - HANDLE h = CreateFile(path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); -#else - HANDLE h = CreateFile(jami::to_wstring(path).c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); +#elif _WIN32 + HANDLE h = CreateFileW(jami::to_wstring(path).c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); #endif if (h == INVALID_HANDLE_VALUE) throw std::runtime_error("Can't open: " + path); @@ -359,7 +360,7 @@ std::vector<uint8_t> loadFile(const std::string& path, const std::string& default_dir) { std::vector<uint8_t> buffer; - std::ifstream file(getFullPath(default_dir, path), std::ios::binary); + std::ifstream file = ifstream(getFullPath(default_dir, path), std::ios::binary); if (!file) throw std::runtime_error("Can't read file: "+path); file.seekg(0, std::ios::end); @@ -378,7 +379,7 @@ saveFile(const std::string& path, const std::vector<uint8_t>& data, mode_t UNUSED mode) { - std::ofstream file(path, std::ios::trunc | std::ios::binary); + std::ofstream file = fileutils::ofstream(path, std::ios::trunc | std::ios::binary); if (!file.is_open()) { JAMI_ERR("Could not write data to %s", path.c_str()); return; @@ -581,12 +582,9 @@ get_home_dir() files_path = paths[0]; return files_path; #elif defined _WIN32 - WCHAR path[MAX_PATH]; - if (SUCCEEDED(SHGetFolderPathW(nullptr, CSIDL_PROFILE, nullptr, 0, path))) { - char tmp[MAX_PATH]; - char DefChar = ' '; - WideCharToMultiByte(CP_ACP, 0, path, -1, tmp, MAX_PATH, &DefChar, nullptr); - return std::string(tmp); + TCHAR path[MAX_PATH]; + if (SUCCEEDED(SHGetFolderPath(nullptr, CSIDL_PROFILE, nullptr, 0, path))) { + return jami::to_string(path); } return program_dir; #else @@ -727,14 +725,14 @@ recursive_mkdir(const std::string& path, mode_t mode) #ifndef _WIN32 if (mkdir(path.data(), mode) != 0) { #else - if (mkdir(path.data()) != 0) { + if (_wmkdir(jami::to_wstring(path.data()).c_str()) != 0) { #endif if (errno == ENOENT) { recursive_mkdir(path.substr(0, path.find_last_of(DIR_SEPARATOR_CH)), mode); #ifndef _WIN32 if (mkdir(path.data(), mode) != 0) { #else - if (mkdir(path.data()) != 0) { + if (_wmkdir(jami::to_wstring(path.data()).c_str()) != 0) { #endif JAMI_ERR("Could not create directory."); return false; @@ -891,4 +889,54 @@ removeAll(const std::string& path, bool erase) return remove(path, erase); } +void +openStream(std::ifstream& file, const std::string& path, std::ios_base::openmode mode) +{ +#ifdef _WIN32 + file.open(jami::to_wstring(path), mode); +#else + file.open(path, mode); +#endif +} + +void +openStream(std::ofstream& file, const std::string& path, std::ios_base::openmode mode) +{ +#ifdef _WIN32 + file.open(jami::to_wstring(path), mode); +#else + file.open(path, mode); +#endif +} + +std::ifstream +ifstream(const std::string& path, std::ios_base::openmode mode) +{ +#ifdef _WIN32 + return std::ifstream(jami::to_wstring(path), mode); +#else + return std::ifstream(path, mode); +#endif +} + +std::ofstream +ofstream(const std::string& path, std::ios_base::openmode mode) +{ +#ifdef _WIN32 + return std::ofstream(jami::to_wstring(path), mode); +#else + return std::ofstream(path, mode); +#endif +} + +int +accessFile(const std::string& file, int mode) +{ +#ifdef _WIN32 + return _waccess(jami::to_wstring(file).c_str(), mode); +#else + return access(file.c_str(), mode); +#endif +} + }} // namespace jami::fileutils diff --git a/src/fileutils.h b/src/fileutils.h index 06a561f0b16e817ec0cf99ce8c883239965d0ca5..05ceabd6c1de03cc90c190af896a6be46ccdef53 100644 --- a/src/fileutils.h +++ b/src/fileutils.h @@ -26,6 +26,7 @@ #include <chrono> #include <mutex> #include <cstdio> +#include <ios> #include "dring/def.h" @@ -134,6 +135,20 @@ namespace jami { namespace fileutils { */ int removeAll(const std::string& path, bool erase = false); + /** + * Wrappers for fstream opening that will convert paths to wstring + * on windows + */ + void openStream(std::ifstream& file, const std::string& path, std::ios_base::openmode mode = std::ios_base::in); + void openStream(std::ofstream& file, const std::string& path, std::ios_base::openmode mode = std::ios_base::out); + std::ifstream ifstream(const std::string& path, std::ios_base::openmode mode = std::ios_base::in); + std::ofstream ofstream(const std::string& path, std::ios_base::openmode mode = std::ios_base::out); + + /** + * Windows compatibility wrapper for checking read-only attribute + */ + int accessFile(const std::string& file, int mode); + }} // namespace jami::fileutils #endif // FILEUTILS_H_ diff --git a/src/im/message_engine.cpp b/src/im/message_engine.cpp index c13ac59602074d9f5aed69394a8ef3ecd99759d6..033fdec71cee957bf5c4f93bc30556164be26e41 100644 --- a/src/im/message_engine.cpp +++ b/src/im/message_engine.cpp @@ -182,7 +182,7 @@ MessageEngine::load() std::lock_guard<std::mutex> lock(fileutils::getFileLock(savePath_)); std::ifstream file; file.exceptions(std::ifstream::failbit | std::ifstream::badbit); - file.open(savePath_); + fileutils::openStream(file, savePath_); file >> root; } std::lock_guard<std::mutex> lock(messagesMutex_); @@ -262,7 +262,7 @@ MessageEngine::save_() const const std::unique_ptr<Json::StreamWriter> writer(wbuilder.newStreamWriter()); std::ofstream file; file.exceptions(std::ifstream::failbit | std::ifstream::badbit); - file.open(path, std::ios::trunc); + fileutils::openStream(file, path, std::ios::trunc); writer->write(root, &file); } catch (const std::exception& e) { JAMI_ERR("[Account %s] Couldn't save messages to %s: %s", accountID.c_str(), path.c_str(), e.what()); diff --git a/src/jamidht/jamiaccount.cpp b/src/jamidht/jamiaccount.cpp index 72c2f509d6316270cda364884c417238300226a6..4b69a43d31b999740955c6ac3ce32bad5895f4ea 100644 --- a/src/jamidht/jamiaccount.cpp +++ b/src/jamidht/jamiaccount.cpp @@ -233,7 +233,6 @@ static const auto PROXY_REGEX = std::regex("(https?://)?([\\w\\.]+)(:(\\d+)|:\\[ static const std::string PEER_DISCOVERY_JAMI_SERVICE = "jami"; const constexpr auto PEER_DISCOVERY_EXPIRATION = std::chrono::minutes(1); - constexpr const char* const JamiAccount::ACCOUNT_TYPE; /* constexpr */ const std::pair<uint16_t, uint16_t> JamiAccount::DHT_PORT_RANGE {4000, 8888}; @@ -310,9 +309,9 @@ JamiAccount::JamiAccount(const std::string& accountID, bool /* presenceEnabled * turnServerRealm_ = DEFAULT_TURN_REALM; turnEnabled_ = true; - std::ifstream proxyCache(cachePath_ + DIR_SEPARATOR_STR "dhtproxy"); + std::ifstream proxyCache = fileutils::ifstream(cachePath_ + DIR_SEPARATOR_STR "dhtproxy"); if (proxyCache) - std::getline(proxyCache, proxyServerCached_); + std::getline(proxyCache, proxyServerCached_); setActiveCodecs({}); } @@ -662,7 +661,6 @@ JamiAccount::SIPStartCall(SIPCall& call, IpAddr target) (int)pjContact.slen, pjContact.ptr, from.c_str(), toUri.c_str(), (int)pjTarget.slen, pjTarget.ptr); - auto local_sdp = call.getSDP().getLocalSdpSession(); pjsip_dialog* dialog {nullptr}; pjsip_inv_session* inv {nullptr}; @@ -712,7 +710,7 @@ void JamiAccount::saveConfig() const auto accountConfig = getPath() + DIR_SEPARATOR_STR + "config.yml"; std::lock_guard<std::mutex> lock(fileutils::getFileLock(accountConfig)); - std::ofstream fout(accountConfig); + std::ofstream fout = fileutils::ofstream(accountConfig); fout << accountOut.c_str(); JAMI_DBG("Exported account to %s", accountConfig.c_str()); } catch (const std::exception& e) { @@ -1022,7 +1020,6 @@ JamiAccount::readArchive(const std::string& pwd) const return AccountArchive(fileutils::getFullPath(idPath_, archivePath_), pwd); } - void JamiAccount::updateArchive(AccountArchive& archive) const { @@ -1190,9 +1187,9 @@ JamiAccount::exportArchive(const std::string& destinationPath, const std::string } // Export the file auto sourcePath = fileutils::getFullPath(idPath_, archivePath_); - std::ifstream src(sourcePath, std::ios::in | std::ios::binary); + std::ifstream src = fileutils::ifstream(sourcePath, std::ios::in | std::ios::binary); if (!src) return false; - std::ofstream dst(destinationPath, std::ios::out | std::ios::binary); + std::ofstream dst = fileutils::ofstream(destinationPath, std::ios::out | std::ios::binary); dst << src.rdbuf(); } catch (const std::runtime_error& ex) { JAMI_ERR("[Account %s] Can't export archive: %s", getAccountID().c_str(), ex.what()); @@ -2083,7 +2080,6 @@ JamiAccount::doRegister() } } - std::vector<std::string> JamiAccount::loadBootstrap() const { @@ -2809,7 +2805,7 @@ std::set<ID> loadIdList(const std::string& path) { std::set<ID> ids; - std::ifstream file(path); + std::ifstream file = fileutils::ifstream(path); if (!file.is_open()) { JAMI_DBG("Could not load %s", path.c_str()); return ids; @@ -2828,7 +2824,7 @@ template<typename ID=dht::Value::Id> void saveIdList(const std::string& path, const std::set<ID>& ids) { - std::ofstream file(path, std::ios::trunc | std::ios::binary); + std::ofstream file = fileutils::ofstream(path, std::ios::trunc | std::ios::binary); if (!file.is_open()) { JAMI_ERR("Could not save to %s", path.c_str()); return; @@ -2915,7 +2911,7 @@ JamiAccount::loadKnownDevices() void JamiAccount::saveKnownDevices() const { - std::ofstream file(idPath_+DIR_SEPARATOR_STR "knownDevicesNames", std::ios::trunc | std::ios::binary); + std::ofstream file = fileutils::ofstream(idPath_+DIR_SEPARATOR_STR "knownDevicesNames", std::ios::trunc | std::ios::binary); std::map<dht::InfoHash, std::pair<std::string, uint64_t>> devices; for (const auto& id : knownDevices_) @@ -2996,7 +2992,7 @@ JamiAccount::getDhtProxyServer() // Cache it! fileutils::check_dir(cachePath_.c_str(), 0700); std::string proxyCachePath = cachePath_ + DIR_SEPARATOR_STR "dhtproxy"; - std::ofstream file(proxyCachePath); + std::ofstream file = fileutils::ofstream(proxyCachePath); JAMI_DBG("Cache DHT proxy server: %s", proxyServerCached_.c_str()); if (file.is_open()) file << proxyServerCached_; @@ -3202,7 +3198,7 @@ JamiAccount::loadContacts() void JamiAccount::saveContacts() const { - std::ofstream file(idPath_+DIR_SEPARATOR_STR "contacts", std::ios::trunc | std::ios::binary); + std::ofstream file = fileutils::ofstream(idPath_+DIR_SEPARATOR_STR "contacts", std::ios::trunc | std::ios::binary); msgpack::pack(file, contacts_); } @@ -3292,7 +3288,7 @@ JamiAccount::sendTrustRequestConfirm(const dht::InfoHash& to) void JamiAccount::saveTrustRequests() const { - std::ofstream file(idPath_+DIR_SEPARATOR_STR "incomingTrustRequests", std::ios::trunc | std::ios::binary); + std::ofstream file = fileutils::ofstream(idPath_+DIR_SEPARATOR_STR "incomingTrustRequests", std::ios::trunc | std::ios::binary); msgpack::pack(file, trustRequests_); } @@ -3661,7 +3657,6 @@ void JamiAccount::pushNotificationReceived(const std::string& from, const std::m dht_.pushNotificationReceived(data); } - std::string JamiAccount::getUserUri() const { @@ -3672,7 +3667,6 @@ JamiAccount::getUserUri() const return username_; } - std::vector<DRing::Message> JamiAccount::getLastMessages(const uint64_t& base_timestamp) { @@ -3746,7 +3740,6 @@ JamiAccount::getNearbyPeers() const return discoveredPeerMap_; } - void JamiAccount::setActiveCodecs(const std::vector<unsigned>& list) { diff --git a/src/jamidht/namedirectory.cpp b/src/jamidht/namedirectory.cpp index 37f4dbb3b8872a918c3c9276602cf1a1711f9f5c..04e54076ee270b32a5813491a42a94a0d1de44a8 100644 --- a/src/jamidht/namedirectory.cpp +++ b/src/jamidht/namedirectory.cpp @@ -399,7 +399,7 @@ NameDirectory::saveCache() { fileutils::recursive_mkdir(fileutils::get_cache_dir()+DIR_SEPARATOR_STR+CACHE_DIRECTORY); std::lock_guard<std::mutex> lock(fileutils::getFileLock(cachePath_)); - std::ofstream file(cachePath_, std::ios::trunc | std::ios::binary); + std::ofstream file = fileutils::ofstream(cachePath_, std::ios::trunc | std::ios::binary); { std::lock_guard<std::mutex> l(lock_); msgpack::pack(file, nameCache_); @@ -415,7 +415,7 @@ NameDirectory::loadCache() // read file { std::lock_guard<std::mutex> lock(fileutils::getFileLock(cachePath_)); - std::ifstream file(cachePath_); + std::ifstream file = fileutils::ifstream(cachePath_); if (!file.is_open()) { JAMI_DBG("Could not load %s", cachePath_.c_str()); return; diff --git a/src/manager.cpp b/src/manager.cpp index 8d0c00fa62a053bc805eb45869784ff1eef6dfe8..644108eec5bb1256006132493931a685f1e15053 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -120,8 +120,8 @@ std::atomic_bool Manager::initialized = {false}; static void copy_over(const std::string &srcPath, const std::string &destPath) { - std::ifstream src(srcPath.c_str()); - std::ofstream dest(destPath.c_str()); + std::ifstream src = fileutils::ifstream(srcPath.c_str()); + std::ofstream dest = fileutils::ofstream(destPath.c_str()); dest << src.rdbuf(); src.close(); dest.close(); @@ -439,7 +439,8 @@ Manager::ManagerPimpl::parseConfiguration() bool result = true; try { - YAML::Node parsedFile = YAML::LoadFile(path_); + std::ifstream file = fileutils::ifstream(path_); + YAML::Node parsedFile = YAML::Load(file); const int error_count = base_.loadAccountMap(parsedFile); if (error_count > 0) { @@ -1772,7 +1773,7 @@ Manager::saveConfig() shortcutPreferences.serialize(out); std::lock_guard<std::mutex> lock(fileutils::getFileLock(pimpl_->path_)); - std::ofstream fout(pimpl_->path_); + std::ofstream fout = fileutils::ofstream(pimpl_->path_); fout << out.c_str(); } catch (const YAML::Exception &e) { JAMI_ERR("%s", e.what()); @@ -2158,9 +2159,7 @@ Manager::playRingtone(const std::string& accountID) CFStringEncoding encodingMethod = CFStringGetSystemEncoding(); const char *buindlePath = CFStringGetCStringPtr(stringPath, encodingMethod); ringchoice = std::string(buindlePath) + DIR_SEPARATOR_STR + ringchoice; -#elif _WIN32 - ringchoice = decodeMultibyteString(ringchoice); -#else +#elif !defined(_WIN32) if (ringchoice.find(DIR_SEPARATOR_CH) == std::string::npos) { // check inside global share directory static const char * const RINGDIR = "ringtones"; @@ -2858,7 +2857,8 @@ Manager::loadAccountMap(const YAML::Node& node) if (fileutils::isFile(configFile)) { try { if (auto a = accountFactory.createAccount(JamiAccount::ACCOUNT_TYPE, dir)) { - YAML::Node parsedConfig = YAML::LoadFile(configFile); + std::ifstream file = fileutils::ifstream(configFile); + YAML::Node parsedConfig = YAML::Load(file); a->unserialize(parsedConfig); } } catch (const std::exception& e) { diff --git a/src/media/media_encoder.cpp b/src/media/media_encoder.cpp index 1203670210ac2fa9749b5ee827a563c783ea790c..8287162bdcb5e2e7194bfcd54ef10d4df886bf94 100644 --- a/src/media/media_encoder.cpp +++ b/src/media/media_encoder.cpp @@ -832,7 +832,6 @@ MediaEncoder::getCurrentVideoAVCtx() return nullptr; } - void MediaEncoder::stopEncoder() { @@ -858,7 +857,7 @@ MediaEncoder::readConfig(AVCodecContext* encoderCtx) if (fileutils::isFile(path)) { try { Json::Value root; - std::ifstream file(path); + std::ifstream file = fileutils::ifstream(path); file >> root; if (!root.isObject()) { JAMI_ERR() << "Invalid encoder configuration: root is not an object"; diff --git a/src/media/recordable.cpp b/src/media/recordable.cpp index 669615205344d74b122bd99f164a54d5f3de74db..ed8b578d628efaa4c7604527b5116d6209c72890 100644 --- a/src/media/recordable.cpp +++ b/src/media/recordable.cpp @@ -60,9 +60,6 @@ Recordable::toggleRecording() auto startTime = *std::localtime(&t); std::stringstream ss; auto dir = Manager::instance().audioPreference.getRecordPath(); -#ifdef _WIN32 - dir = decodeMultibyteString(dir); -#endif if (dir.empty()) dir = fileutils::get_home_dir(); ss << dir; diff --git a/src/sip/sipaccount.cpp b/src/sip/sipaccount.cpp index 597753b863b12f8ccfd36bab70b1325c62fa00e0..88f1bd40b199d9e9e140b23239ce0b9b982a87ce 100644 --- a/src/sip/sipaccount.cpp +++ b/src/sip/sipaccount.cpp @@ -1308,18 +1308,11 @@ std::string SIPAccount::getLoginName() #elif defined (RING_UWP) return "Unknown"; #else - TCHAR username[UNLEN + 1]; DWORD size = UNLEN + 1; + TCHAR username[UNLEN + 1]; std::string uname; if (GetUserName((TCHAR*)username, &size)) { -#ifdef _MSC_VER - wchar_t* tmpstr = new wchar_t[UNLEN + 1]; - mbstowcs(tmpstr, username, UNLEN + 1); - std::wstring wStr = tmpstr; -#else - std::wstring wStr = username; -#endif - uname = std::string(wStr.begin(), wStr.end()); + uname = jami::to_string(username); } return uname; #endif diff --git a/src/string_utils.cpp b/src/string_utils.cpp index 2f432214d8f5f16a15416ace89ab1af528a9202a..3e9cbe07051d9b9af2945a7b61713206cfd581cc 100644 --- a/src/string_utils.cpp +++ b/src/string_utils.cpp @@ -37,25 +37,33 @@ namespace jami { #ifdef _WIN32 std::wstring -to_wstring(const std::string& s) +to_wstring(const std::string& str, int codePage) { - int slength = (int)s.length(); - int len = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), slength, nullptr, 0); - if (not len) - throw std::runtime_error("Can't convert string to wchar"); - std::wstring r((size_t)len, 0); - if (!MultiByteToWideChar(CP_UTF8, 0, s.c_str(), slength, &(*r.begin()), len)) - throw std::runtime_error("Can't convert string to wchar"); - return r; + int srcLength = (int)str.length(); + int requiredSize = MultiByteToWideChar(codePage, 0, str.c_str(), srcLength, nullptr, 0); + if (!requiredSize) { + throw std::runtime_error("Can't convert string to wstring"); + } + std::wstring result((size_t)requiredSize, 0); + if (!MultiByteToWideChar(codePage, 0, str.c_str(), srcLength, &(*result.begin()), requiredSize)) { + throw std::runtime_error("Can't convert string to wstring"); + } + return result; } std::string -decodeMultibyteString(const std::string& s) +to_string(const std::wstring& wstr, int codePage) { - if (not s.length()) - return {}; - auto wstr = to_wstring(s); - return std::string(wstr.begin(), wstr.end()); + int srcLength = (int)wstr.length(); + int requiredSize = WideCharToMultiByte(codePage, 0, wstr.c_str(), srcLength, nullptr, 0, 0, 0); + if (!requiredSize) { + throw std::runtime_error("Can't convert wstring to string"); + } + std::string result((size_t)requiredSize, 0); + if (!WideCharToMultiByte(codePage, 0, wstr.c_str(), srcLength, &(*result.begin()), requiredSize, 0, 0)) { + throw std::runtime_error("Can't convert wstring to string"); + } + return result; } std::string diff --git a/src/string_utils.h b/src/string_utils.h index 8f27e78690b7cb490a838dc36a6d38aa5f8d476b..f5c69cc5a76c5d2cb4335677a7c092249db36e45 100644 --- a/src/string_utils.h +++ b/src/string_utils.h @@ -42,8 +42,8 @@ bool_to_str(bool b) noexcept std::string to_string(double value); #ifdef _WIN32 -std::wstring to_wstring(const std::string& s); -std::string decodeMultibyteString(const std::string& s); +std::wstring to_wstring(const std::string& str, int codePage = CP_UTF8); +std::string to_string(const std::wstring& wstr, int codePage = CP_ACP); std::string bstrToStdString(BSTR bstr); #endif