From 8cbadfe89767ef8a86c35fde9c9238010744ed14 Mon Sep 17 00:00:00 2001 From: Pablo Martin Date: Wed, 2 May 2018 18:01:02 +0200 Subject: [PATCH 01/17] fix ambiguous isnan --- src/gfx/qt.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/gfx/qt.cpp b/src/gfx/qt.cpp index 3511d18105..8cf83ecf33 100644 --- a/src/gfx/qt.cpp +++ b/src/gfx/qt.cpp @@ -833,7 +833,11 @@ QImageReader *GfxProcQT::readbitmapFfmpeg(int &w, int &h, int &orientation, QStr if (displaymatrix) { double rot = av_display_rotation_get((int32_t*) displaymatrix); - if (!isnan(rot)) +#if __cplusplus >= 201103L + if (!std::isnan(rot)) +#else + if (!(rot != rot)) +#endif { if (rot < -135 || rot > 135) { From 7ccd33ea1f7962eb0cf71e7264602e1e455af587 Mon Sep 17 00:00:00 2001 From: Javier Gomez Date: Thu, 3 May 2018 13:23:41 +0200 Subject: [PATCH 02/17] Support to check if MegaTransfer is finished (WP & UWP bindings) --- bindings/wp8/MTransfer.cpp | 5 +++++ bindings/wp8/MTransfer.h | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/bindings/wp8/MTransfer.cpp b/bindings/wp8/MTransfer.cpp index a10ed7de60..3c1ad33290 100644 --- a/bindings/wp8/MTransfer.cpp +++ b/bindings/wp8/MTransfer.cpp @@ -188,6 +188,11 @@ bool MTransfer::isStreamingTransfer() return megaTransfer ? megaTransfer->isStreamingTransfer() : false; } +bool MTransfer::isFinished() +{ + return megaTransfer ? megaTransfer->isFinished() : false; +} + bool MTransfer::isFolderTransfer() { return megaTransfer ? megaTransfer->isFolderTransfer() : false; diff --git a/bindings/wp8/MTransfer.h b/bindings/wp8/MTransfer.h index 22c4905085..88b6943329 100644 --- a/bindings/wp8/MTransfer.h +++ b/bindings/wp8/MTransfer.h @@ -82,6 +82,13 @@ namespace mega MNode^ getPublicMegaNode(); bool isSyncTransfer(); bool isStreamingTransfer(); + + /** + * @brief Returns true is the transfer is at finished state (COMPLETED, CANCELLED OR FAILED) + * @return true if this transfer is finished, false otherwise + */ + bool isFinished(); + bool isFolderTransfer(); int getFolderTransferTag(); String^ getAppData(); From b85ab21e9215d79789dfba6527b92a77a0518c09 Mon Sep 17 00:00:00 2001 From: Javier Gomez Date: Thu, 3 May 2018 14:07:23 +0200 Subject: [PATCH 03/17] Add retrySSLerrors, setPublicKeyPinning methods (WP & UWP bindings) Update the localLogout method documentation --- bindings/wp8/MegaSDK.cpp | 10 ++++++ bindings/wp8/MegaSDK.h | 70 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 78 insertions(+), 2 deletions(-) diff --git a/bindings/wp8/MegaSDK.cpp b/bindings/wp8/MegaSDK.cpp index 5a330b7b74..90df19484d 100644 --- a/bindings/wp8/MegaSDK.cpp +++ b/bindings/wp8/MegaSDK.cpp @@ -3636,6 +3636,16 @@ void MegaSDK::getContactLinksOption() megaApi->getContactLinksOption(); } +void MegaSDK::retrySSLerrors(bool enable) +{ + megaApi->retrySSLerrors(enable); +} + +void MegaSDK::setPublicKeyPinning(bool enable) +{ + megaApi->setPublicKeyPinning(enable); +} + bool MegaSDK::createThumbnail(String^ imagePath, String^ dstPath) { std::string utf8imagePath; diff --git a/bindings/wp8/MegaSDK.h b/bindings/wp8/MegaSDK.h index 145d50dd92..1f1db6fb45 100644 --- a/bindings/wp8/MegaSDK.h +++ b/bindings/wp8/MegaSDK.h @@ -741,10 +741,49 @@ namespace mega void removeContact(MUser^ user, MRequestListenerInterface^ listener); void removeContact(MUser^ user); - void logout(MRequestListenerInterface^ listener); + + /** + * @brief Logout of the MEGA account invalidating the session + * + * The associated request type with this request is MRequestType::TYPE_LOGOUT + * + * Under certain circumstances, this request might return the error code + * MError::API_ESID. It should not be taken as an error, since the reason + * is that the logout action has been notified before the reception of the + * logout response itself. + * + * @param listener MRequestListener to track this request + */ + void logout(MRequestListenerInterface^ listener); + + /** + * @brief Logout of the MEGA account invalidating the session + * + * The associated request type with this request is MRequestType::TYPE_LOGOUT + * + * Under certain circumstances, this request might return the error code + * MError::API_ESID. It should not be taken as an error, since the reason + * is that the logout action has been notified before the reception of the + * logout response itself. + */ void logout(); + + /** + * @brief Logout of the MEGA account without invalidating the session + * + * The associated request type with this request is MRequestType::TYPE_LOGOUT + * + * @param listener MRequestListener to track this request + */ void localLogout(MRequestListenerInterface^ listener); - void localLogout(); + + /** + * @brief Logout of the MEGA account without invalidating the session + * + * The associated request type with this request is MRequestType::TYPE_LOGOUT + */ + void localLogout(); + int getPasswordStrength(String^ password); void submitFeedback(int rating, String^ comment, MRequestListenerInterface^ listener); void submitFeedback(int rating, String^ comment); @@ -1032,6 +1071,33 @@ namespace mega */ void getContactLinksOption(); + /** + * @brief Keep retrying when public key pinning fails + * + * By default, when the check of the MEGA public key fails, it causes an automatic + * logout. Pass false to this function to disable that automatic logout and + * keep the SDK retrying the request. + * + * Even if the automatic logout is disabled, a request of the type MegaRequestType::TYPE_LOGOUT + * will be automatically created and callbacks (onRequestStart, onRequestFinish) will + * be sent. However, logout won't be really executed and in onRequestFinish the error code + * for the request will be MError::API_EINCOMPLETE + * + * @param enable true to keep retrying failed requests due to a fail checking the MEGA public key + * or false to perform an automatic logout in that case + */ + void retrySSLerrors(bool enable); + + /** + * @brief Enable / disable the public key pinning + * + * Public key pinning is enabled by default for all sensible communications. + * It is strongly discouraged to disable this feature. + * + * @param enable true to keep public key pinning enabled, false to disable it + */ + void setPublicKeyPinning(bool enable); + bool createThumbnail(String^ imagePath, String^ dstPath); bool createPreview(String^ imagePath, String^ dstPath); From f7a0348de6f29f3f4d1d6bde15501ac14ca1603e Mon Sep 17 00:00:00 2001 From: Javier Serrano Date: Mon, 7 May 2018 19:44:54 +0200 Subject: [PATCH 04/17] Changes to get an early compatibility with the new registration and login procedure --- include/megaapi.h | 3 +++ src/megaapi_impl.cpp | 15 ++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/include/megaapi.h b/include/megaapi.h index f64be49f03..84bc6d8510 100644 --- a/include/megaapi.h +++ b/include/megaapi.h @@ -5089,6 +5089,9 @@ class MegaApi * * @param password Access password * @return Base64-encoded private key + * + * @deprecated The registration and login procedure will be changed soon. When that happens, this function will stop being + * compatible and will be deleted, so please stop using it as soon as possible. */ char* getBase64PwKey(const char *password); diff --git a/src/megaapi_impl.cpp b/src/megaapi_impl.cpp index e008a857dd..26e5b9c7a7 100644 --- a/src/megaapi_impl.cpp +++ b/src/megaapi_impl.cpp @@ -10338,14 +10338,23 @@ void MegaApiImpl::fetchnodes_result(error e) } byte pwkey[SymmCipher::KEYLENGTH]; - if(!request->getPrivateKey()) - client->pw_key(request->getPassword(),pwkey); + if (!request->getPrivateKey()) + { + client->pw_key(request->getPassword(), pwkey); + + char* buf = new char[SymmCipher::KEYLENGTH * 4 / 3 + 4]; + Base64::btoa((byte *)pwkey, SymmCipher::KEYLENGTH, buf); + request->setPrivateKey(buf); + delete [] buf; + } else + { Base64::atob(request->getPrivateKey(), (byte *)pwkey, sizeof pwkey); + } // ...and finally send confirmation link client->reqtag = client->restag; - client->sendsignuplink(request->getEmail(),request->getName(),pwkey); + client->sendsignuplink(request->getEmail(), request->getName(), pwkey); client->reqtag = creqtag; } } From a2fbe4e2ad4552ba7fa1d4ecea96c821a2f9b69a Mon Sep 17 00:00:00 2001 From: Javier Serrano Date: Mon, 7 May 2018 20:11:06 +0200 Subject: [PATCH 05/17] Prevent the usage of a deleted pointer `send_request` can be deleted in `send_request()`. --- src/posix/net.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/posix/net.cpp b/src/posix/net.cpp index 3d327ffab2..87a7c65d7b 100644 --- a/src/posix/net.cpp +++ b/src/posix/net.cpp @@ -1079,6 +1079,7 @@ void CurlHttpIO::ares_completed_callback(void* arg, int status, int, struct host return; } + bool ares_pending = httpctx->ares_pending; if (httpctx->hostip.size()) { LOG_verbose << "Name resolution finished"; @@ -1110,7 +1111,7 @@ void CurlHttpIO::ares_completed_callback(void* arg, int status, int, struct host } } - if (httpctx->ares_pending) + if (ares_pending) { LOG_verbose << "Waiting for the completion of the c-ares request"; } From a832cb25ee57b86882afd9117d5008d67e32325d Mon Sep 17 00:00:00 2001 From: Javier Serrano Date: Wed, 9 May 2018 13:21:03 +0200 Subject: [PATCH 06/17] Fixed URL codec --- include/mega/base64.h | 2 +- src/base64.cpp | 10 +++++----- src/megaapi_impl.cpp | 1 + 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/include/mega/base64.h b/include/mega/base64.h index 12f3e3593f..9da6935f1f 100644 --- a/include/mega/base64.h +++ b/include/mega/base64.h @@ -57,7 +57,7 @@ class MEGA_API URLCodec { static bool ishexdigit(char c); static bool issafe(char c); - static char hexval(char c); + static unsigned char hexval(char c); public: diff --git a/src/base64.cpp b/src/base64.cpp index 32759c19a9..14e35b324d 100644 --- a/src/base64.cpp +++ b/src/base64.cpp @@ -391,9 +391,9 @@ bool URLCodec::issafe(char c) return false; } -char URLCodec::hexval(char c) +unsigned char URLCodec::hexval(char c) { - return c > '9' ? (c > 'a' ? c - 'a' + 10 : c - 'A' + 10) : c - '0'; + return c > '9' ? (c >= 'a' ? c - 'a' + 10 : c - 'A' + 10) : c - '0'; } bool URLCodec::ishexdigit(char c) @@ -442,9 +442,9 @@ void URLCodec::unescape(string *escaped, string *plain) { if (escaped->at(i) == '%' && ishexdigit(escaped->at(i + 1)) && ishexdigit(escaped->at(i + 2))) { - char c1 = hexval(escaped->at(i + 1)); - char c2 = hexval(escaped->at(i + 2)); - char c = 0xFF & ((c1 << 4) | c2); + unsigned char c1 = hexval(escaped->at(i + 1)); + unsigned char c2 = hexval(escaped->at(i + 2)); + unsigned char c = 0xFF & ((c1 << 4) | c2); plain->push_back(c); i += 2; diff --git a/src/megaapi_impl.cpp b/src/megaapi_impl.cpp index 26e5b9c7a7..729b758809 100644 --- a/src/megaapi_impl.cpp +++ b/src/megaapi_impl.cpp @@ -19854,6 +19854,7 @@ int MegaHTTPServer::onUrlReceived(http_parser *parser, const char *url, size_t l } URLCodec::unescape(&nodename, &httpctx->nodename); + httpctx->server->fsAccess->normalize(&httpctx->nodename); LOG_debug << "Node name: " << httpctx->nodename; } From 1fb175b7b2226fe16d949f7889e2af41d9edf11c Mon Sep 17 00:00:00 2001 From: Matt Weir Date: Fri, 11 May 2018 18:33:45 +1200 Subject: [PATCH 07/17] Merge changes that were needed for building MEGAcmd 0.9.9 for NAS. - freeimage adjustment for arm_64 - cmake script that gives an easy non-cygwin way to develop and test changes with visual studio - use m_time_t a lot more to avoid problems with time_t where it is only 32 bits - provide m_time() m_localtime() m_mktime to use instead of time() localtime() mktime() - address quite a few warnings about 64/32 bit lossy conversions in 32 bit builds where it was safe to do so - fix for (probably never hit case) where streaming fingerprint calc can't jump between block with a 32 bit value - sdk_test added to confirm fingerprint calc is still working --- contrib/build_sdk.sh | 17 ++ contrib/cmake/CMakeLists.txt | 308 +++++++++++++++++++++++++++++++++++ examples/megacli.cpp | 2 +- include/mega.h | 10 +- include/mega/megaclient.h | 2 +- include/mega/types.h | 4 +- include/mega/utils.h | 6 +- src/base64.cpp | 2 +- src/commands.cpp | 52 +++--- src/crypto/sodium.cpp | 2 +- src/filefingerprint.cpp | 20 ++- src/mediafileattribute.cpp | 6 +- src/megaapi_impl.cpp | 84 +++++----- src/megaclient.cpp | 46 +++--- src/node.cpp | 6 +- src/sync.cpp | 6 +- src/transferslot.cpp | 2 +- src/user.cpp | 16 +- src/utils.cpp | 57 +++++++ tests/sdk_test.cpp | 96 ++++++++++- 20 files changed, 616 insertions(+), 128 deletions(-) create mode 100644 contrib/cmake/CMakeLists.txt diff --git a/contrib/build_sdk.sh b/contrib/build_sdk.sh index c32364154f..3792c156c6 100755 --- a/contrib/build_sdk.sh +++ b/contrib/build_sdk.sh @@ -787,6 +787,23 @@ freeimage_pkg() { export FREEIMAGE_LIBRARY_TYPE=STATIC fi +cat << EOF > $build_dir/freeimage_neon_arm64_patch +138c138 +< # define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_neon +--- +> //# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_neon +1931,1932c1931,1932 +< PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_neon, +< (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); +--- +> //PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_neon, +> // (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); +EOF + # freeimage's LibPNG has a problem with deciding to use neon on 64 bit arm, resulting in a missing symbol + if [ "$ARCH" == "aarch64" ]; then + (patch `find . -name pngpriv.h` < $build_dir/freeimage_neon_arm64_patch) + fi + if [ "$(expr substr $(uname -s) 1 10)" != "MINGW32_NT" ]; then package_build $name $freeimage_dir # manually copy header and library diff --git a/contrib/cmake/CMakeLists.txt b/contrib/cmake/CMakeLists.txt new file mode 100644 index 0000000000..56b9901599 --- /dev/null +++ b/contrib/cmake/CMakeLists.txt @@ -0,0 +1,308 @@ +# This file enables building with cmake on windows +# +# use cases +# - generate a visual studio solution and projects, eg: cmake . -G "Visual Studio 15 2017" +# - or for 64 bit: cmake . -G "Visual Studio 15 2017 Win64" +# - or set your build options before VS project generation by using the gui, eg: cmake-gui.exe . +# - open this CMakeLists.txt as a 'cmake project' with Visual Studio 2017 or beyond, and you can build and test/debug on windows or on Linux from one IDE (eg. a virtualbox linux instance on the same machine) +# (though it seems in order for it to copy the needed build tree, this file must be copied up one level (to the mega root dir) and opened as a CMake project in VS from there + +cmake_minimum_required(VERSION 3.8) + +#set this to 1 if building 64 bit with eg. cmake . -G "Visual Studio 15 2017 Win64" +#set this to 0 if building 32 bit with eg. cmake . -G "Visual Studio 15 2017" +set (build_64_bit 1 CACHE TYPE BOOL) + +#indicate which dependent libraries to use in the build +set (USE_CRYPTOPP 1 CACHE TYPE BOOL) +set (USE_OPENSSL 0 CACHE TYPE BOOL) +set (OPENSSL_IS_BORINGSSL 0 CACHE TYPE BOOL) +set (USE_CURL 0 CACHE TYPE BOOL) +set (USE_SQLITE 1 CACHE TYPE BOOL) +set (USE_MEDIAINFO 1 CACHE TYPE BOOL) +set (USE_FREEIMAGE 1 CACHE TYPE BOOL) +set (USE_SODIUM 1 CACHE TYPE BOOL) +set (ENABLE_SYNC 1 CACHE TYPE BOOL) +set (ENABLE_CHAT 1 CACHE TYPE BOOL) + +if (WIN32) + set (NO_READLINE 1 CACHE TYPE BOOL) +else(WIN32) + set(NO_READLINE 0) +endif(WIN32) + +if(build_64_bit) + project (MegaSDK64 LANGUAGES CXX C) +else(build_64_bit) + project (MegaSDK32 LANGUAGES CXX C) +endif(build_64_bit) + +IF(WIN32) + set(MegaDir "${CMAKE_CURRENT_LIST_DIR}/../..") + if ("${Mega3rdPartyDir}" STREQUAL "") + set(Mega3rdPartyDir "${MegaDir}/../3rdparty") + endif() +ELSE(WIN32) + set(MegaDir "${CMAKE_CURRENT_LIST_DIR}") +ENDIF(WIN32) + +if (NOT CMAKE_BUILD_TYPE) + message("Generated with config types: ${CMAKE_CONFIGURATION_TYPES}") +else(NOT CMAKE_BUILD_TYPE) + message("CMAKE_BUILD_TYPE is ${CMAKE_BUILD_TYPE}") +endif(NOT CMAKE_BUILD_TYPE) + +#windows projects usually need _DEBUG and/or DEBUG set rather than NDEBUG not set +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG -DDEBUG") +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG -DDEBUG") + +IF(WIN32) + #Link against the static C/C++ libraries on windows + foreach(flag_var + CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE + CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE + CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) + if(${flag_var} MATCHES "/MD") + string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") + endif(${flag_var} MATCHES "/MD") + endforeach(flag_var) +ENDIF(WIN32) + + +function(ImportStaticLibrary libName includeDir lib32debug lib32release lib64debug lib64release) + add_library(${libName} STATIC IMPORTED) + set_property(TARGET ${libName} PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${includeDir}) + if(build_64_bit) + set_property(TARGET ${libName} PROPERTY IMPORTED_LOCATION_DEBUG ${lib64debug}) + set_property(TARGET ${libName} PROPERTY IMPORTED_LOCATION_RELEASE ${lib64release}) + else(build_64_bit) + set_property(TARGET ${libName} PROPERTY IMPORTED_LOCATION_DEBUG ${lib32debug}) + set_property(TARGET ${libName} PROPERTY IMPORTED_LOCATION_RELEASE ${lib32release}) + endif(build_64_bit) +endfunction(ImportStaticLibrary) + + +IF(WIN32) + + IF(USE_CRYPTOPP) + ImportStaticLibrary(cryptopp "${Mega3rdPartyDir}/cryptopp565/include" + "${Mega3rdPartyDir}/cryptopp565/Win32/Output/Debug/cryptlib.lib" + "${Mega3rdPartyDir}/cryptopp565/Win32/Output/Release/cryptlib.lib" + "${Mega3rdPartyDir}/cryptopp565/x64/Output/Debug/cryptlib.lib" + "${Mega3rdPartyDir}/cryptopp565/x64/Output/Release/cryptlib.lib") + ENDIF(USE_CRYPTOPP) + + IF(USE_SODIUM) + ImportStaticLibrary(sodium "${Mega3rdPartyDir}/libsodium-1.0.15/src/libsodium/include" + "${Mega3rdPartyDir}/libsodium-1.0.15/Build/Debug/Win32/libsodium.lib" + "${Mega3rdPartyDir}/libsodium-1.0.15/Build/Release/Win32/libsodium.lib" + "${Mega3rdPartyDir}/libsodium-1.0.15/Build/Debug/x64/libsodium.lib" + "${Mega3rdPartyDir}/libsodium-1.0.15/Build/Release/x64/libsodium.lib") + ENDIF(USE_SODIUM) + + IF(USE_CURL) + ImportStaticLibrary(curl "${Mega3rdPartyDir}/curl-7.56.0/include" + "${Mega3rdPartyDir}/curl-7.56.0/builds/libcurl-vc-x86-debug-static-ssl-static-cares-static-zlib-static-ipv6-sspi/lib/libcurl_a_debug.lib" + "${Mega3rdPartyDir}/curl-7.56.0/builds/libcurl-vc-x86-release-static-ssl-static-cares-static-zlib-static-ipv6-sspi/lib/libcurl_a.lib" + "${Mega3rdPartyDir}/curl-7.56.0/builds/libcurl-vc-x64-debug-static-ssl-static-cares-static-zlib-static-ipv6-sspi/lib/libcurl_a_debug.lib" + "${Mega3rdPartyDir}/curl-7.56.0/builds/libcurl-vc-x64-release-static-ssl-static-cares-static-zlib-static-ipv6-sspi/lib/libcurl_a.lib") + + ImportStaticLibrary(cares "${Mega3rdPartyDir}/c-ares-1.13.0/include" + "${Mega3rdPartyDir}/c-ares-1.13.0/built32/lib/libcaresd.lib" + "${Mega3rdPartyDir}/c-ares-1.13.0/built32/lib/libcares.lib" + "${Mega3rdPartyDir}/c-ares-1.13.0/built64/lib/libcaresd.lib" + "${Mega3rdPartyDir}/c-ares-1.13.0/built64/lib/libcares.lib") + ENDIF(USE_CURL) + + IF(USE_OPENSSL) + ImportStaticLibrary(ssl "${Mega3rdPartyDir}/openssl-1.1.0f/include" + "${Mega3rdPartyDir}/openssl-1.1.0f/built_32d/lib/libssl.lib" + "${Mega3rdPartyDir}/openssl-1.1.0f/built_32/lib/libssl.lib" + "${Mega3rdPartyDir}/openssl-1.1.0f/built_64d/lib/libssl.lib" + "${Mega3rdPartyDir}/openssl-1.1.0f/built_64/lib/libssl.lib") + ENDIF(USE_OPENSSL) + + ImportStaticLibrary(sslcrypto "${Mega3rdPartyDir}/openssl-1.1.0f/include" + "${Mega3rdPartyDir}/openssl-1.1.0f/built_32d/lib/libcrypto.lib" + "${Mega3rdPartyDir}/openssl-1.1.0f/built_32/lib/libcrypto.lib" + "${Mega3rdPartyDir}/openssl-1.1.0f/built_64d/lib/libcrypto.lib" + "${Mega3rdPartyDir}/openssl-1.1.0f/built_64/lib/libcrypto.lib") + + + ImportStaticLibrary(zlib "${Mega3rdPartyDir}/zlib-1.2.11" + "${Mega3rdPartyDir}/zlib-1.2.11/contrib/vstudio/vc14/x86/ZlibStatDebug/zlibstat.lib" + "${Mega3rdPartyDir}zlib-1.2.11/contrib/vstudio/vc14/x86/ZlibStatReleaseWithoutAsm/zlibstat.lib" + "${Mega3rdPartyDir}/zlib-1.2.11/contrib/vstudio/vc14/x64/ZlibStatDebug/zlibstat.lib" + "${Mega3rdPartyDir}/zlib-1.2.11/contrib/vstudio/vc14/x64/ZlibStatReleaseWithoutAsm/zlibstat.lib") + + ImportStaticLibrary(gtest "${Mega3rdPartyDir}/googletest/googletest/include" + "${Mega3rdPartyDir}/googletest/googletest/msvc/2010/gtest/Win32-Debug/gtestd.lib" + "${Mega3rdPartyDir}/googletest/googletest/msvc/2010/gtest/Win32-Release/gtest.lib" + "${Mega3rdPartyDir}/googletest/googletest/msvc/2010/gtest/x64-Debug/gtestd.lib" + "${Mega3rdPartyDir}/googletest/googletest/msvc/2010/gtest/x64-Release/gtest.lib") + + IF(USE_MEDIAINFO) + ImportStaticLibrary(mediainfo "${Mega3rdPartyDir}/MediaInfoLib-mw/Source" + "${Mega3rdPartyDir}/MediaInfoLib-mw/Project/MSVC2017/Win32/Debug/MediaInfo-Static.lib" + "${Mega3rdPartyDir}/MediaInfoLib-mw/Project/MSVC2017/Win32/Release/MediaInfo-Static.lib" + "${Mega3rdPartyDir}/MediaInfoLib-mw/Project/MSVC2017/x64/Debug/MediaInfo-Static.lib" + "${Mega3rdPartyDir}/MediaInfoLib-mw/Project/MSVC2017/x64/Release/MediaInfo-Static.lib") + + ImportStaticLibrary(zen "${Mega3rdPartyDir}/ZenLib/Source" + "${Mega3rdPartyDir}/MediaInfoLib-mw/Project/MSVC2017/Win32/Debug/ZenLib.lib" + "${Mega3rdPartyDir}/MediaInfoLib-mw/Project/MSVC2017/Win32/Release/ZenLib.lib" + "${Mega3rdPartyDir}/MediaInfoLib-mw/Project/MSVC2017/x64/Debug/ZenLib.lib" + "${Mega3rdPartyDir}/MediaInfoLib-mw/Project/MSVC2017/x64/Release/ZenLib.lib") + ENDIF(USE_MEDIAINFO) + + IF(USE_FREEIMAGE) + ImportStaticLibrary(freeimage "${Mega3rdPartyDir}/FreeImage3170/FreeImage/Source" + "${Mega3rdPartyDir}/FreeImage3170/FreeImage/Source/FreeImageLib/Win32/Debug/FreeImageLib.lib" + "${Mega3rdPartyDir}/FreeImage3170/FreeImage/Source/FreeImageLib/Win32/Release/FreeImageLib.lib" + "${Mega3rdPartyDir}/FreeImage3170/FreeImage/Source/FreeImageLib/x64/Debug/FreeImageLib.lib" + "${Mega3rdPartyDir}/FreeImage3170/FreeImage/Source/FreeImageLib/x64/Release/FreeImageLib.lib") + + ENDIF(USE_FREEIMAGE) + + + IF(USE_SQLITE) + add_library(sqlite3 INTERFACE IMPORTED) + set_property(TARGET sqlite3 PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${Mega3rdPartyDir}/sqlite-3.20.1") + ENDIF(USE_SQLITE) + + add_definitions(-D_CRT_SECURE_NO_WARNINGS -DCURL_STATICLIB -DCARES_STATICLIB -DWIN32_LEAN_AND_MEAN -DUNICODE -DSODIUM_STATIC -DPCRE_STATICWIN32 -D_CONSOLE) + SET(Mega_PlatformSpecificIncludes ${MegaDir}/include/mega/$) + SET(Mega_PlatformSpecificLibs ws2_32 winhttp Shlwapi) + + get_target_property(sqlite3dir sqlite3 INTERFACE_INCLUDE_DIRECTORIES) + SET(Mega_PlatformSpecificFiles ${MegaDir}/src/win32/console.cpp +# ${MegaDir}/src/win32/autocomplete.cpp + ${MegaDir}/src/win32/consolewaiter.cpp + ${MegaDir}/src/win32/fs.cpp + $ + ${MegaDir}/src/win32/waiter.cpp + ${MegaDir}/src/thread/win32thread.cpp + ${sqlite3dir}/sqlite3.c ) + + +ELSE(WIN32) + + add_definitions(-DUSE_PTHREAD ) + SET(Mega_PlatformSpecificFiles ${MegaDir}/src/posix/console.cpp ${MegaDir}/src/posix/consolewaiter.cpp ${MegaDir}/src/posix/fs.cpp ${MegaDir}/src/posix/net.cpp ${MegaDir}/src/posix/waiter.cpp ${MegaDir}/src/thread/posixthread.cpp ) + SET(Mega_PlatformSpecificIncludes ${MegaDir}/include/mega/posix) + SET(Mega_PlatformSpecificLibs crypto pthread rt z) + +ENDIF(WIN32) + + +SET(Mega_CryptoFiles ${MegaDir}/src/crypto/cryptopp.cpp ${MegaDir}/src/crypto/sodium.cpp) +SET(Mega_DbFiles ${MegaDir}/src/db/sqlite.cpp ${MegaDir}/src/db/sqlite.cpp ) +SET(Mega_GfxFiles ${MegaDir}/src/gfx/external.cpp ${MegaDir}/src/gfx/freeimage.cpp ) + +add_library(Mega STATIC + ${MegaDir}/src/attrmap.cpp + ${MegaDir}/src/backofftimer.cpp + ${MegaDir}/src/base64.cpp + ${MegaDir}/src/command.cpp + ${MegaDir}/src/commands.cpp + ${MegaDir}/src/db.cpp + ${MegaDir}/src/file.cpp + ${MegaDir}/src/fileattributefetch.cpp + ${MegaDir}/src/filefingerprint.cpp + ${MegaDir}/src/filesystem.cpp + ${MegaDir}/src/gfx.cpp + ${MegaDir}/src/http.cpp + ${MegaDir}/src/json.cpp + ${MegaDir}/src/logging.cpp + ${MegaDir}/src/mediafileattribute.cpp + ${MegaDir}/src/mega_ccronexpr.cpp + ${MegaDir}/src/mega_http_parser.cpp + ${MegaDir}/src/mega_utf8proc.cpp + ${MegaDir}/src/mega_zxcvbn.cpp + ${MegaDir}/src/megaapi.cpp + ${MegaDir}/src/megaapi_impl.cpp + ${MegaDir}/src/megaclient.cpp + ${MegaDir}/src/node.cpp + ${MegaDir}/src/pendingcontactrequest.cpp + ${MegaDir}/src/proxy.cpp + ${MegaDir}/src/pubkeyaction.cpp +# ${MegaDir}/src/raid.cpp + ${MegaDir}/src/request.cpp + ${MegaDir}/src/serialize64.cpp + ${MegaDir}/src/share.cpp + ${MegaDir}/src/sharenodekeys.cpp + ${MegaDir}/src/sync.cpp +# ${MegaDir}/src/testhooks.cpp + ${MegaDir}/src/transfer.cpp + ${MegaDir}/src/transferslot.cpp + ${MegaDir}/src/treeproc.cpp + ${MegaDir}/src/user.cpp + ${MegaDir}/src/utils.cpp + ${MegaDir}/src/waiterbase.cpp + ${Mega_PlatformSpecificFiles} ${Mega_CryptoFiles} ${Mega_DbFiles} ${Mega_GfxFiles} ) + +target_include_directories(Mega PRIVATE ${MegaDir}/include ${Mega_PlatformSpecificIncludes}) +target_include_directories(Mega PUBLIC ${MegaDir}/include ${Mega_PlatformSpecificIncludes}) +target_link_libraries(Mega PUBLIC zlib + $<${USE_CRYPTOPP}:cryptopp> + $<${USE_SODIUM}:sodium> + $<${USE_OPENSSL}:ssl> + $<${USE_CURL}:curl> $<${USE_CURL}:cares> + $<${USE_SQLITE}:sqlite3> + $<${USE_MEDIAINFO}:mediainfo> $<${USE_MEDIAINFO}:zen> + $<${USE_FREEIMAGE}:freeimage> + ${Mega_PlatformSpecificLibs}) +target_compile_definitions(Mega PUBLIC + $<${USE_MEDIAINFO}:USE_MEDIAINFO> + $<${USE_FREEIMAGE}:USE_FREEIMAGE> $<${USE_FREEIMAGE}:FREEIMAGE_LIB> + $<${USE_SQLITE}:USE_SQLITE> + $<${USE_CRYPTOPP}:USE_CRYPTOPP> + $<${USE_OPENSSL}:USE_OPENSSL> + $<${USE_CURL}:USE_CURL> + $<${USE_SODIUM}:USE_SODIUM> + $<${ENABLE_SYNC}:ENABLE_SYNC> + $<${ENABLE_CHAT}:ENABLE_CHAT> + $<${NO_READLINE}:NO_READLINE> ) + +if(WIN32) +target_link_libraries(Mega PUBLIC crypt32.lib) +endif(WIN32) + +#test apps +add_executable(test_sdk ${MegaDir}/tests/sdk_test.cpp + ${MegaDir}/tests/sdktests.cpp) +add_executable(test_misc ${MegaDir}/tests/tests.cpp + ${MegaDir}/tests/paycrypt_test.cpp + ${MegaDir}/tests/crypto_test.cpp) +add_executable(test_purge_account ${MegaDir}/tests/purge_account.cpp) + +target_compile_definitions(test_sdk PRIVATE _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING) +target_compile_definitions(test_misc PRIVATE _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING) +target_compile_definitions(test_purge_account PRIVATE _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING) +target_link_libraries(test_sdk gtest Mega ) +target_link_libraries(test_misc gtest Mega ) +target_link_libraries(test_purge_account gtest Mega ) + +#test apps need this file or tests fail +configure_file("${MegaDir}/logo.png" logo.png COPYONLY) + +# actual apps + +add_executable(megacli ${MegaDir}/examples/megacli.cpp) +target_link_libraries(megacli Mega) +if (NOT NO_READLINE) + target_link_libraries(megacli readline) +endif (NOT NO_READLINE) + +add_executable(megasimplesync ${MegaDir}/examples/megasimplesync.cpp) +target_link_libraries(megasimplesync Mega ) + +if(WIN32) +add_executable(testmega "${MegaDir}/examples/win32/testmega/main.cpp") +target_link_libraries(testmega Mega ) +endif(WIN32) + +#enable_testing() +#add_test(NAME SdkTestStreaming COMMAND test_sdk "--gtest_filter=\"*Streaming*\"") +#add_test(NAME SdkTestAll COMMAND test_sdk ) + diff --git a/examples/megacli.cpp b/examples/megacli.cpp index d3302f8c24..15ef79e34b 100644 --- a/examples/megacli.cpp +++ b/examples/megacli.cpp @@ -5274,7 +5274,7 @@ void DemoApp::account_details(AccountDetails* ad, bool storage, bool transfer, b if (ad->transfer_hist_starttime) { - time_t t = time(NULL) - ad->transfer_hist_starttime; + m_time_t t = m_time() - ad->transfer_hist_starttime; cout << "\tTransfer history:\n"; diff --git a/include/mega.h b/include/mega.h index 6842ac5ac0..f71dc71040 100644 --- a/include/mega.h +++ b/include/mega.h @@ -72,11 +72,11 @@ #include "mega/thread/win32thread.h" #include "mega/thread/cppthread.h" -#include "megawaiter.h" -#include "meganet.h" -#include "megafs.h" -#include "megaconsole.h" -#include "megaconsolewaiter.h" +#include +#include +#include +#include +#include #include "mega/db/sqlite.h" #include "mega/db/bdb.h" diff --git a/include/mega/megaclient.h b/include/mega/megaclient.h index d2444fc905..8455c7bdc5 100644 --- a/include/mega/megaclient.h +++ b/include/mega/megaclient.h @@ -195,7 +195,7 @@ class MEGA_API MegaClient string k; // timestamp of the creation of the account - time_t accountsince; + m_time_t accountsince; #ifdef ENABLE_CHAT // all chats diff --git a/include/mega/types.h b/include/mega/types.h index 63383fe40c..34a20a8df2 100644 --- a/include/mega/types.h +++ b/include/mega/types.h @@ -103,7 +103,9 @@ struct Achievement; #define EOO 0 -typedef int64_t m_time_t; +// Our own version of time_t which we can be sure is 64 bit. +// Utils.h has functions m_time() and so on corresponding to time() which help us to use this type and avoid arithmetic overflow when working with time_t on systems where it's 32-bit +typedef int64_t m_time_t; // monotonously increasing time in deciseconds typedef uint32_t dstime; diff --git a/include/mega/utils.h b/include/mega/utils.h index 428bdcdc16..74903e68b9 100644 --- a/include/mega/utils.h +++ b/include/mega/utils.h @@ -1,4 +1,4 @@ -/** +/** * @file mega/utils.h * @brief Mega SDK various utilities and helper classes * @@ -334,6 +334,10 @@ class Utils { // for pre-c++11 where this version is not defined yet. long long abs(long long n); +extern m_time_t m_time(m_time_t* tt = NULL); +extern struct tm* m_localtime(m_time_t, struct tm *dt); +extern m_time_t m_mktime(struct tm*); + } // namespace #endif diff --git a/src/base64.cpp b/src/base64.cpp index 14e35b324d..d6ce31bd18 100644 --- a/src/base64.cpp +++ b/src/base64.cpp @@ -152,7 +152,7 @@ void Base64::itoa(int64_t val, string *result) { rest = val % 64; val /= 64; - c = to64(rest); + c = to64(byte(rest)); result->insert(result->begin(), (char) c); } } diff --git a/src/commands.cpp b/src/commands.cpp index eee3a8500e..9ccd15fee9 100644 --- a/src/commands.cpp +++ b/src/commands.cpp @@ -443,7 +443,7 @@ void CommandDirectRead::procresult() break; case MAKENAMEID2('t', 'l'): - tl = client->json.getint(); + tl = dstime(client->json.getint()); break; case EOO: @@ -544,7 +544,7 @@ void CommandGetFile::procresult() dstime tl = 0; int d = 0; byte* buf; - time_t ts = 0, tm = 0; + m_time_t ts = 0, tm = 0; // credentials relevant to a non-TransferSlot scenario (node query) string fileattrstring; @@ -603,7 +603,7 @@ void CommandGetFile::procresult() break; case MAKENAMEID2('t', 'l'): - tl = client->json.getint(); + tl = dstime(client->json.getint()); break; case EOO: @@ -2111,10 +2111,10 @@ void CommandEnumerateQuotaItems::procresult() while (client->json.enterarray()) { if (ISUNDEF((product = client->json.gethandle(8))) - || ((prolevel = client->json.getint()) < 0) - || ((gbstorage = client->json.getint()) < 0) - || ((gbtransfer = client->json.getint()) < 0) - || ((months = client->json.getint()) < 0) + || ((prolevel = int(client->json.getint())) < 0) + || ((gbstorage = int(client->json.getint())) < 0) + || ((gbtransfer = int(client->json.getint())) < 0) + || ((months = int(client->json.getint())) < 0) || !(a = client->json.getvalue()) || !(c = client->json.getvalue()) || !(d = client->json.getvalue()) @@ -3188,7 +3188,7 @@ void CommandGetUserQuota::procresult() td = client->json.getint(); if (td != -1) { - details->transfer_hist_starttime = time(NULL) - td; + details->transfer_hist_starttime = m_time() - td; } break; @@ -3251,8 +3251,8 @@ void CommandGetUserQuota::procresult() ns = &details->storage[h]; ns->bytes = client->json.getint(); - ns->files = client->json.getint(); - ns->folders = client->json.getint(); + ns->files = uint32_t(client->json.getint()); + ns->folders = uint32_t(client->json.getint()); ns->version_bytes = client->json.getint(); ns->version_files = client->json.getint(); @@ -3405,7 +3405,7 @@ void CommandQueryTransferQuota::procresult() return client->app->querytransferquota_result(0); } - return client->app->querytransferquota_result(client->json.getint()); + return client->app->querytransferquota_result(int(client->json.getint())); } CommandGetUserTransactions::CommandGetUserTransactions(MegaClient* client, AccountDetails* ad) @@ -3423,7 +3423,7 @@ void CommandGetUserTransactions::procresult() while (client->json.enterarray()) { const char* handle = client->json.getvalue(); - time_t ts = client->json.getint(); + m_time_t ts = client->json.getint(); const char* delta = client->json.getvalue(); const char* cur = client->json.getvalue(); @@ -3462,7 +3462,7 @@ void CommandGetUserPurchases::procresult() while (client->json.enterarray()) { const char* handle = client->json.getvalue(); - const time_t ts = client->json.getint(); + const m_time_t ts = client->json.getint(); const char* amount = client->json.getvalue(); const char* cur = client->json.getvalue(); int method = (int)client->json.getint(); @@ -3770,7 +3770,7 @@ void CommandWhyAmIblocked::procresult() { if (client->json.isnumeric()) { - return client->app->whyamiblocked_result(client->json.getint()); + return client->app->whyamiblocked_result(int(client->json.getint())); } client->json.storeobject(); @@ -4138,7 +4138,7 @@ void CommandCreditCardQuerySubscriptions::procresult() int number = 0; if (client->json.isnumeric()) { - number = client->json.getint(); + number = int(client->json.getint()); if(number >= 0) { client->app->creditcardquerysubscriptions_result(number, API_OK); @@ -4250,7 +4250,7 @@ void CommandGetPaymentMethods::procresult() do { - int value = client->json.getint(); + int value = int(client->json.getint()); if(value < 0) { client->app->getpaymentmethods_result(methods, (error)value); @@ -4382,10 +4382,10 @@ void CommandQueryRecoveryLink::procresult() int type = API_EINTERNAL; string email; string ip; - time_t ts; + m_time_t ts; handle uh; - if (!client->json.isnumeric() || ((type = client->json.getint()) < 0)) // error + if (!client->json.isnumeric() || ((type = int(client->json.getint())) < 0)) // error { return client->app->queryrecoverylink_result((error)type); } @@ -4419,7 +4419,7 @@ void CommandQueryRecoveryLink::procresult() return client->app->queryrecoverylink_result(API_EINTERNAL); } - return client->app->queryrecoverylink_result(type, email.c_str(), ip.c_str(), ts, uh, &emails); + return client->app->queryrecoverylink_result(type, email.c_str(), ip.c_str(), time_t(ts), uh, &emails); } CommandGetPrivateKey::CommandGetPrivateKey(MegaClient *client, const char *code) @@ -4643,7 +4643,7 @@ void CommandGetVersion::procresult() switch (client->json.getnameid()) { case 'c': - versioncode = client->json.getint(); + versioncode = int(client->json.getint()); break; case 's': @@ -4786,7 +4786,7 @@ void CommandChatCreate::procresult() break; case MAKENAMEID2('c','s'): - shard = client->json.getint(); + shard = int(client->json.getint()); break; case 'g': @@ -5424,7 +5424,7 @@ void CommandRichLink::procresult() switch (client->json.getnameid()) { case MAKENAMEID5('e', 'r', 'r', 'o', 'r'): - errCode = client->json.getint(); + errCode = int(client->json.getint()); break; case MAKENAMEID6('r', 'e', 's', 'u', 'l', 't'): @@ -5514,7 +5514,7 @@ void CommandGetMegaAchievements::procresult() { for (;;) { - achievement_class_id id = client->json.getnameid(); + achievement_class_id id = achievement_class_id(client->json.getnameid()); if (id == EOO) { break; @@ -5573,10 +5573,10 @@ void CommandGetMegaAchievements::procresult() switch (client->json.getnameid()) { case 'a': - award.achievement_class = client->json.getint(); + award.achievement_class = achievement_class_id(client->json.getint()); break; case 'r': - award.award_id = client->json.getint(); + award.award_id = int(client->json.getint()); break; case MAKENAMEID2('t', 's'): award.ts = client->json.getint(); @@ -5633,7 +5633,7 @@ void CommandGetMegaAchievements::procresult() } Reward reward; - reward.award_id = id - '0'; // convert to number + reward.award_id = int(id - '0'); // convert to number client->json.enterarray(); diff --git a/src/crypto/sodium.cpp b/src/crypto/sodium.cpp index 140851073c..039de90653 100644 --- a/src/crypto/sodium.cpp +++ b/src/crypto/sodium.cpp @@ -130,7 +130,7 @@ void EdDSA::signKey(const unsigned char *key, const unsigned long long keyLength { if (!ts) { - ts = (uint64_t) time(NULL); + ts = (uint64_t) m_time(); } string tsstr; diff --git a/src/filefingerprint.cpp b/src/filefingerprint.cpp index 981f785a89..397b9b930e 100644 --- a/src/filefingerprint.cpp +++ b/src/filefingerprint.cpp @@ -162,7 +162,7 @@ bool FileFingerprint::genfingerprint(FileAccess* fa, bool ignoremtime) for (unsigned i = 0; i < sizeof crc / sizeof *crc; i++) { - int begin = i * size / (sizeof crc / sizeof *crc); + int begin = int(i * size / (sizeof crc / sizeof *crc)); int end = (i + 1) * size / (sizeof crc / sizeof *crc); crc32.add(buf + begin, end - begin); @@ -257,7 +257,7 @@ bool FileFingerprint::genfingerprint(InputStreamAccess *is, m_time_t cmtime, boo HashCRC32 crc32; byte buf[MAXFULL]; - if (!is->read(buf, size)) + if (!is->read(buf, int(size))) { size = -1; return true; @@ -265,8 +265,8 @@ bool FileFingerprint::genfingerprint(InputStreamAccess *is, m_time_t cmtime, boo for (unsigned i = 0; i < sizeof crc / sizeof *crc; i++) { - int begin = i * size / (sizeof crc / sizeof *crc); - int end = (i + 1) * size / (sizeof crc / sizeof *crc); + int begin = int(i * size / (sizeof crc / sizeof *crc)); + int end = int((i + 1) * size / (sizeof crc / sizeof *crc)); crc32.add(buf + begin, end - begin); crc32.get((byte*)&crcval); @@ -291,11 +291,17 @@ bool FileFingerprint::genfingerprint(InputStreamAccess *is, m_time_t cmtime, boo / (sizeof crc / sizeof *crc * blocks - 1); //Seek - if (!is->read(NULL, offset - current)) + for (m_off_t fullstep = offset - current; fullstep > 0; ) // 500G or more and the step doesn't fit in 32 bits { - size = -1; - return true; + unsigned step = fullstep > UINT_MAX ? UINT_MAX : unsigned(fullstep); + if (!is->read(NULL, step)) + { + size = -1; + return true; + } + fullstep -= (uint64_t)step; } + current += (offset - current); if (!is->read(block, sizeof block)) diff --git a/src/mediafileattribute.cpp b/src/mediafileattribute.cpp index 0a3fdc0a9b..874a1b691a 100644 --- a/src/mediafileattribute.cpp +++ b/src/mediafileattribute.cpp @@ -590,7 +590,7 @@ bool mediaInfoOpenFileWithLimits(MediaInfoLib::MediaInfo& mi, std::string filena size_t totalBytesRead = 0, jumps = 0; mi.Open_Buffer_Init(filesize, 0); m_off_t readpos = 0; - time_t startTime = 0; + m_time_t startTime = 0; for (;;) { @@ -602,7 +602,7 @@ bool mediaInfoOpenFileWithLimits(MediaInfoLib::MediaInfo& mi, std::string filena break; } - if (totalBytesRead > maxBytesToRead || (startTime != 0 && ((time(NULL) - startTime) > maxSeconds))) + if (totalBytesRead > maxBytesToRead || (startTime != 0 && ((m_time() - startTime) > maxSeconds))) { LOG_warn << "could not extract mediainfo data within reasonable limits"; mi.Open_Buffer_Finalize(); @@ -620,7 +620,7 @@ bool mediaInfoOpenFileWithLimits(MediaInfoLib::MediaInfo& mi, std::string filena readpos += n; if (startTime == 0) { - startTime = time(NULL); + startTime = m_time(); } totalBytesRead += n; diff --git a/src/megaapi_impl.cpp b/src/megaapi_impl.cpp index 729b758809..0c523135ed 100644 --- a/src/megaapi_impl.cpp +++ b/src/megaapi_impl.cpp @@ -244,7 +244,7 @@ MegaNodePrivate::MegaNodePrivate(Node *node) { if (node->type == FILENODE) { - duration = Base64::atoi(&it->second); + duration = int(Base64::atoi(&it->second)); } } else if (it->first == AttrMap::string2nameid("l")) @@ -408,11 +408,11 @@ bool MegaNodePrivate::serialize(string *d) unsigned short ll; bool flag; - ll = name ? strlen(name) + 1 : 0; + ll = (unsigned short)(name ? strlen(name) + 1 : 0); d->append((char*)&ll, sizeof(ll)); d->append(name, ll); - ll = fingerprint ? strlen(fingerprint) + 1 : 0; + ll = (unsigned short)(fingerprint ? strlen(fingerprint) + 1 : 0); d->append((char*)&ll, sizeof(ll)); d->append(fingerprint, ll); @@ -1747,22 +1747,22 @@ bool MegaTransferPrivate::serialize(string *d) d->append((const char*)&parentHandle, sizeof(parentHandle)); unsigned short ll; - ll = path ? strlen(path) + 1 : 0; + ll = (unsigned short)(path ? strlen(path) + 1 : 0); d->append((char*)&ll, sizeof(ll)); d->append(path, ll); - ll = parentPath ? strlen(parentPath) + 1 : 0; + ll = (unsigned short)(parentPath ? strlen(parentPath) + 1 : 0); d->append((char*)&ll, sizeof(ll)); d->append(parentPath, ll); - ll = fileName ? strlen(fileName) + 1 : 0; + ll = (unsigned short)(fileName ? strlen(fileName) + 1 : 0); d->append((char*)&ll, sizeof(ll)); d->append(fileName, ll); d->append((const char*)&folderTransferTag, sizeof(folderTransferTag)); d->append("\0\0\0\0\0\0", 7); - ll = appData ? strlen(appData) + 1 : 0; + ll = (unsigned short)(appData ? strlen(appData) + 1 : 0); if (ll) { char hasAppData = 1; @@ -2523,6 +2523,7 @@ MegaRegExp *MegaRequestPrivate::getRegExp() const { return regExp; } + void MegaRequestPrivate::setRegExp(MegaRegExp *regExp) { if (this->regExp) @@ -5201,16 +5202,16 @@ void MegaApiImpl::setNodeCoordinates(MegaNode *node, double latitude, double lon request->setNodeHandle(node->getHandle()); } - int lat = latitude; + int lat = int(latitude); if (latitude != MegaNode::INVALID_COORDINATE) { - lat = ((latitude + 90) / 180) * 0xFFFFFF; + lat = int(((latitude + 90) / 180) * 0xFFFFFF); } - int lon = longitude; + int lon = int(longitude); if (longitude != MegaNode::INVALID_COORDINATE) { - lon = (longitude == 180) ? 0 : ((longitude + 180) / 360) * 0x01000000; + lon = int((longitude == 180) ? 0 : ((longitude + 180) / 360) * 0x01000000); } request->setParamType(MegaApi::NODE_ATTR_COORDINATES); @@ -5937,22 +5938,22 @@ bool MegaApiImpl::setMaxUploadSpeed(m_off_t bpslimit) int MegaApiImpl::getMaxDownloadSpeed() { - return client->getmaxdownloadspeed(); + return int(client->getmaxdownloadspeed()); } int MegaApiImpl::getMaxUploadSpeed() { - return client->getmaxuploadspeed(); + return int(client->getmaxuploadspeed()); } int MegaApiImpl::getCurrentDownloadSpeed() { - return httpio->downloadSpeed; + return int(httpio->downloadSpeed); } int MegaApiImpl::getCurrentUploadSpeed() { - return httpio->uploadSpeed; + return int(httpio->uploadSpeed); } int MegaApiImpl::getCurrentSpeed(int type) @@ -5960,9 +5961,9 @@ int MegaApiImpl::getCurrentSpeed(int type) switch (type) { case MegaTransfer::TYPE_DOWNLOAD: - return httpio->downloadSpeed; + return int(httpio->downloadSpeed); case MegaTransfer::TYPE_UPLOAD: - return httpio->uploadSpeed; + return int(httpio->uploadSpeed); default: return 0; } @@ -10579,7 +10580,7 @@ void MegaApiImpl::fa_complete(handle, fatype, const char* data, uint32_t len) MegaRequestPrivate* request = requestMap.at(tag); if(!request || (request->getType() != MegaRequest::TYPE_GET_ATTR_FILE)) return; - tag = request->getNumber(); + tag = int(request->getNumber()); FileAccess *f = client->fsaccess->newfileaccess(); string filePath(request->getFile()); @@ -10616,7 +10617,7 @@ int MegaApiImpl::fa_failed(handle, fatype, int retries, error e) if(!request || (request->getType() != MegaRequest::TYPE_GET_ATTR_FILE)) return 1; - tag = request->getNumber(); + tag = int(request->getNumber()); if(retries >= 2) { fireOnRequestFinish(request, MegaError(e)); @@ -10732,7 +10733,7 @@ void MegaApiImpl::additem_result(error e) } //MegaRequest::TYPE_UPGRADE_ACCOUNT - int method = request->getNumber(); + int method = int(request->getNumber()); client->purchase_checkout(method); } @@ -11536,7 +11537,7 @@ void MegaApiImpl::getua_result(error e) return; } else if (request->getType() == MegaRequest::TYPE_GET_ATTR_USER - && (time(NULL) - client->accountsince) > User::PWD_SHOW_AFTER_ACCOUNT_AGE) + && (m_time() - client->accountsince) > User::PWD_SHOW_AFTER_ACCOUNT_AGE) { request->setFlag(true); // the password reminder dialog should be shown } @@ -11646,7 +11647,7 @@ void MegaApiImpl::getua_result(byte* data, unsigned len) } else if (attrType == MegaApi::USER_ATTR_PWD_REMINDER) { - time_t currenttime = time(NULL); + m_time_t currenttime = m_time(); if (!User::getPwdReminderData(User::PWD_MK_EXPORTED, (const char*)data, len) && !User::getPwdReminderData(User::PWD_DONT_SHOW, (const char*)data, len) && (currenttime - client->accountsince) > User::PWD_SHOW_AFTER_ACCOUNT_AGE @@ -12912,10 +12913,9 @@ int naturalsorting_compare (const char *i, const char *j) return difference; } - difference = number_i - number_j; - if (difference) + if (number_i != number_j) { - return difference; + return number_i > number_j ? 1 : -1; } stringMode = true; @@ -15165,7 +15165,7 @@ void MegaApiImpl::sendPendingRequests() break; } - prevtag = req->getNumber(); + prevtag = int(req->getNumber()); } if(req) @@ -15460,7 +15460,7 @@ void MegaApiImpl::sendPendingRequests() int type = request->getParamType(); if (type == MegaApi::NODE_ATTR_DURATION) { - int secs = request->getNumber(); + int secs = int(request->getNumber()); if (node->type != FILENODE || secs < MegaNode::INVALID_DURATION) { e = API_EARGS; @@ -15669,7 +15669,7 @@ void MegaApiImpl::sendPendingRequests() { const char *email = request->getEmail(); const char *message = request->getText(); - int action = request->getNumber(); + int action = int(request->getNumber()); MegaHandle contactLink = request->getNodeHandle(); if(client->loggedin() != FULLACCOUNT) @@ -15696,7 +15696,7 @@ void MegaApiImpl::sendPendingRequests() case MegaRequest::TYPE_REPLY_CONTACT_REQUEST: { handle h = request->getNodeHandle(); - int action = request->getNumber(); + int action = int(request->getNumber()); if(h == INVALID_HANDLE || action < 0 || action > MegaContactRequest::REPLY_ACTION_IGNORE) { @@ -16064,7 +16064,7 @@ void MegaApiImpl::sendPendingRequests() case MegaRequest::TYPE_PAUSE_TRANSFERS: { bool pause = request->getFlag(); - int direction = request->getNumber(); + int direction = int(request->getNumber()); if(direction != -1 && direction != MegaTransfer::TYPE_DOWNLOAD && direction != MegaTransfer::TYPE_UPLOAD) @@ -16112,7 +16112,7 @@ void MegaApiImpl::sendPendingRequests() { bool automove = request->getFlag(); int transferTag = request->getTransferTag(); - int number = request->getNumber(); + int number = int(request->getNumber()); if (!transferTag || !number) { @@ -16192,7 +16192,7 @@ void MegaApiImpl::sendPendingRequests() case MegaRequest::TYPE_SET_MAX_CONNECTIONS: { int direction = request->getParamType(); - int connections = request->getNumber(); + int connections = int(request->getNumber()); if (connections <= 0 || (direction != -1 && direction != MegaTransfer::TYPE_DOWNLOAD @@ -16487,7 +16487,7 @@ void MegaApiImpl::sendPendingRequests() case MegaRequest::TYPE_GET_PAYMENT_ID: case MegaRequest::TYPE_UPGRADE_ACCOUNT: { - int method = request->getNumber(); + int method = int(request->getNumber()); if(method != MegaApi::PAYMENT_METHOD_BALANCE && method != MegaApi::PAYMENT_METHOD_CREDIT_CARD) { e = API_EARGS; @@ -16500,7 +16500,7 @@ void MegaApiImpl::sendPendingRequests() case MegaRequest::TYPE_SUBMIT_PURCHASE_RECEIPT: { const char* receipt = request->getText(); - int type = request->getNumber(); + int type = int(request->getNumber()); if(!receipt || (type != MegaApi::PAYMENT_METHOD_GOOGLE_WALLET && type != MegaApi::PAYMENT_METHOD_ITUNES @@ -16556,7 +16556,7 @@ void MegaApiImpl::sendPendingRequests() } case MegaRequest::TYPE_SUBMIT_FEEDBACK: { - int rating = request->getNumber(); + int rating = int(request->getNumber()); const char *message = request->getText(); if(rating < 1 || rating > 5) @@ -16587,7 +16587,7 @@ void MegaApiImpl::sendPendingRequests() } case MegaRequest::TYPE_SEND_EVENT: { - int number = request->getNumber(); + int number = int(request->getNumber()); const char *text = request->getText(); if(number < 99500 || number >= 99600 || !text) @@ -16701,7 +16701,7 @@ void MegaApiImpl::sendPendingRequests() case MegaRequest::TYPE_QUERY_GELB: { const char *service = request->getName(); - int timeoutds = request->getNumber(); + int timeoutds = int(request->getNumber()); int maxretries = request->getNumRetry(); if (!service) { @@ -16881,7 +16881,7 @@ void MegaApiImpl::sendPendingRequests() } case MegaRequest::TYPE_REGISTER_PUSH_NOTIFICATION: { - int deviceType = request->getNumber(); + int deviceType = int(request->getNumber()); const char *token = request->getText(); if ((deviceType != MegaApi::PUSH_NOTIFICATION_ANDROID && @@ -22647,7 +22647,7 @@ int MegaAchievementsDetailsPrivate::getRewardExpire(unsigned int index) long long MegaAchievementsDetailsPrivate::currentStorage() { long long total = 0; - m_time_t ts = time(NULL); + m_time_t ts = m_time(); for (vector::iterator it = details.awards.begin(); it != details.awards.end(); it++) { @@ -22669,7 +22669,7 @@ long long MegaAchievementsDetailsPrivate::currentStorage() long long MegaAchievementsDetailsPrivate::currentTransfer() { long long total = 0; - m_time_t ts = time(NULL); + m_time_t ts = m_time(); for (vector::iterator it = details.awards.begin(); it != details.awards.end(); it++) { @@ -22691,7 +22691,7 @@ long long MegaAchievementsDetailsPrivate::currentTransfer() long long MegaAchievementsDetailsPrivate::currentStorageReferrals() { long long total = 0; - m_time_t ts = time(NULL); + m_time_t ts = m_time(); for (vector::iterator it = details.awards.begin(); it != details.awards.end(); it++) { @@ -22713,7 +22713,7 @@ long long MegaAchievementsDetailsPrivate::currentStorageReferrals() long long MegaAchievementsDetailsPrivate::currentTransferReferrals() { long long total = 0; - m_time_t ts = time(NULL); + m_time_t ts = m_time(); for (vector::iterator it = details.awards.begin(); it != details.awards.end(); it++) { diff --git a/src/megaclient.cpp b/src/megaclient.cpp index b69d4e5afb..c92c602b53 100644 --- a/src/megaclient.cpp +++ b/src/megaclient.cpp @@ -1866,7 +1866,7 @@ void MegaClient::exec() for (it = syncs.begin(); it != syncs.end(); ) { Sync* sync = *it++; - prevpending |= sync->dirnotify->notifyq[q].size(); + prevpending = prevpending || sync->dirnotify->notifyq[q].size(); if (prevpending) { break; @@ -5010,7 +5010,7 @@ void MegaClient::sc_upc() uts = jsonsc.getint(); break; case 's': - s = jsonsc.getint(); + s = int(jsonsc.getint()); break; case 'p': p = jsonsc.gethandle(MegaClient::PCRHANDLE); @@ -5188,7 +5188,7 @@ void MegaClient::sc_se() uh = jsonsc.gethandle(USERHANDLE); break; case 's': - status = jsonsc.getint(); + status = int(jsonsc.getint()); break; case EOO: done = true; @@ -5268,7 +5268,7 @@ void MegaClient::sc_chatupdate() break; case MAKENAMEID2('c','s'): - shard = jsonsc.getint(); + shard = int(jsonsc.getint()); break; case 'n': // the new user, for notification purposes (not used) @@ -5469,7 +5469,7 @@ void MegaClient::sc_chatflags() break; case 'f': - flags = jsonsc.getint(); + flags = byte(jsonsc.getint()); break; case EOO: @@ -6220,7 +6220,7 @@ int MegaClient::readnodes(JSON* j, int notify, putsource_t source, NewNode* nn, break; case 'i': // related source NewNode index - nni = j->getint(); + nni = int(j->getint()); break; case MAKENAMEID2('t', 's'): // actual creation timestamp @@ -6391,7 +6391,7 @@ int MegaClient::readnodes(JSON* j, int notify, putsource_t source, NewNode* nn, // fallback timestamps if (!(ts + 1)) { - ts = time(NULL); + ts = m_time(); } if (!(sts + 1)) @@ -8406,7 +8406,7 @@ void MegaClient::procmcf(JSON *j) break; case MAKENAMEID2('c','s'): - shard = j->getint(); + shard = int(j->getint()); break; case 'u': // list of users participating in the chat (+privileges) @@ -8494,7 +8494,7 @@ void MegaClient::procmcf(JSON *j) while(j->enterobject()) // while there are more chatid/flag tuples to read... { handle chatid = UNDEF; - int flags = 0xFF; + byte flags = 0xFF; bool readingFlags = true; while (readingFlags) @@ -8507,7 +8507,7 @@ void MegaClient::procmcf(JSON *j) break; case 'f': - flags = j->getint(); + flags = byte(j->getint()); break; case EOO: @@ -9439,7 +9439,7 @@ void MegaClient::closetc(bool remove) { transfer_map::iterator it = cachedtransfers[d].begin(); Transfer *transfer = it->second; - if (remove || (purgeOrphanTransfers && (time(NULL) - transfer->lastaccesstime) >= 172500)) + if (remove || (purgeOrphanTransfers && (m_time() - transfer->lastaccesstime) >= 172500)) { LOG_warn << "Purging orphan transfer"; transfer->finished = true; @@ -10137,7 +10137,7 @@ void MegaClient::queueread(handle h, bool p, SymmCipher* key, int64_t ctriv, m_o if (overquotauntil && overquotauntil > Waiter::ds) { - dstime timeleft = overquotauntil - Waiter::ds; + dstime timeleft = dstime(overquotauntil - Waiter::ds); app->pread_failure(API_EOVERQUOTA, 0, appdata, timeleft); it->second->schedule(timeleft); } @@ -10151,7 +10151,7 @@ void MegaClient::queueread(handle h, bool p, SymmCipher* key, int64_t ctriv, m_o it->second->enqueue(offset, count, reqtag, appdata); if (overquotauntil && overquotauntil > Waiter::ds) { - dstime timeleft = overquotauntil - Waiter::ds; + dstime timeleft = dstime(overquotauntil - Waiter::ds); app->pread_failure(API_EOVERQUOTA, 0, appdata, timeleft); it->second->schedule(timeleft); } @@ -11166,7 +11166,7 @@ bool MegaClient::syncup(LocalNode* l, dstime* nds) if (currentVersion) { m_time_t delay = 0; - m_time_t currentTime = time(NULL); + m_time_t currentTime = m_time(); if (currentVersion->ctime > currentTime + 30) { // with more than 30 seconds of detecteed clock drift, @@ -11209,7 +11209,7 @@ bool MegaClient::syncup(LocalNode* l, dstime* nds) m_time_t next = currentVersion->ctime + delay; if (next > currentTime) { - dstime backoffds = (next - currentTime) * 10; + dstime backoffds = dstime((next - currentTime) * 10); ll->nagleds = waiter->ds + backoffds; LOG_debug << "Waiting for the version rate limit delay during " << backoffds << " ds"; @@ -11623,8 +11623,8 @@ void MegaClient::execmovetosyncdebris() Node* tn; node_set::iterator it; - time_t ts; - struct tm* ptm; + m_time_t ts; + struct tm tms; char buf[32]; syncdel_t target; @@ -11642,8 +11642,8 @@ void MegaClient::execmovetosyncdebris() target = SYNCDEL_BIN; - ts = time(NULL); - ptm = localtime(&ts); + ts = m_time(); + struct tm* ptm = m_localtime(ts, &tms); sprintf(buf, "%04d-%02d-%02d", ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday); m_time_t currentminute = ts / 60; @@ -11860,7 +11860,7 @@ bool MegaClient::startxfer(direction_t d, File* f, bool skipdupes) if (overquotauntil && overquotauntil > Waiter::ds) { - dstime timeleft = overquotauntil - Waiter::ds; + dstime timeleft = dstime(overquotauntil - Waiter::ds); t->failed(API_EOVERQUOTA, timeleft); } } @@ -11871,7 +11871,7 @@ bool MegaClient::startxfer(direction_t d, File* f, bool skipdupes) { LOG_debug << "Resumable transfer detected"; t = it->second; - if ((d == GET && !t->pos) || ((time(NULL) - t->lastaccesstime) >= 172500)) + if ((d == GET && !t->pos) || ((m_time() - t->lastaccesstime) >= 172500)) { LOG_warn << "Discarding temporary URL (" << t->pos << ", " << t->lastaccesstime << ")"; t->cachedtempurl.clear(); @@ -11941,7 +11941,7 @@ bool MegaClient::startxfer(direction_t d, File* f, bool skipdupes) *(FileFingerprint*)t = *(FileFingerprint*)f; } - t->lastaccesstime = time(NULL); + t->lastaccesstime = m_time(); t->tag = reqtag; f->tag = reqtag; t->transfers_it = transfers[d].insert(pair((FileFingerprint*)t, t)).first; @@ -11960,7 +11960,7 @@ bool MegaClient::startxfer(direction_t d, File* f, bool skipdupes) if (overquotauntil && overquotauntil > Waiter::ds) { - dstime timeleft = overquotauntil - Waiter::ds; + dstime timeleft = dstime(overquotauntil - Waiter::ds); t->failed(API_EOVERQUOTA, timeleft); } } diff --git a/src/node.cpp b/src/node.cpp index 27e616e3a9..a4db1bb5d4 100644 --- a/src/node.cpp +++ b/src/node.cpp @@ -444,10 +444,10 @@ bool Node::serialize(string* d) d->append((char*)&owner, MegaClient::USERHANDLE); // FIXME: use Serialize64 - time_t ts = 0; + time_t ts = 0; // we don't want to break backward compatibiltiy by changing the size (where m_time_t differs) d->append((char*)&ts, sizeof(ts)); - ts = ctime; + ts = (time_t)ctime; d->append((char*)&ts, sizeof(ts)); d->append(nodekey); @@ -917,7 +917,7 @@ bool PublicLink::isExpired() if (!ets) // permanent link: ets=0 return false; - m_time_t t = time(NULL); + m_time_t t = m_time(); return ets < t; } diff --git a/src/sync.cpp b/src/sync.cpp index aa1f696bab..c38794d456 100644 --- a/src/sync.cpp +++ b/src/sync.cpp @@ -839,7 +839,7 @@ LocalNode* Sync::checkpath(LocalNode* l, string* localpath, string* localname, d // logic to detect files being updated in the local computer moving the original file // to another location as a temporary backup - m_time_t currentsecs = time(NULL); + m_time_t currentsecs = m_time(); if (!updatedfileinitialts) { updatedfileinitialts = currentsecs; @@ -1199,10 +1199,10 @@ bool Sync::movetolocaldebris(string* localpath) { size_t t = localdebris.size(); char buf[32]; - time_t ts = time(NULL); - struct tm* ptm = localtime(&ts); + struct tm tms; string day, localday; bool havedir = false; + struct tm* ptm = m_localtime(m_time(), &tms); for (int i = -3; i < 100; i++) { diff --git a/src/transferslot.cpp b/src/transferslot.cpp index ad97907d44..76150cfc57 100644 --- a/src/transferslot.cpp +++ b/src/transferslot.cpp @@ -380,7 +380,7 @@ void TransferSlot::doio(MegaClient* client) } lastdata = Waiter::ds; - transfer->lastaccesstime = time(NULL); + transfer->lastaccesstime = m_time(); LOG_debug << "Chunk finished OK (" << transfer->type << ") Pos: " << transfer->pos << " Completed: " << (transfer->progresscompleted + reqs[i]->size) << " of " << transfer->size; diff --git a/src/user.cpp b/src/user.cpp index 9402e326b5..050c0e8e90 100644 --- a/src/user.cpp +++ b/src/user.cpp @@ -72,13 +72,13 @@ bool User::serialize(string* d) { d->append((char*)&it->first, sizeof it->first); - ll = it->second.size(); + ll = (unsigned short)it->second.size(); d->append((char*)&ll, sizeof ll); d->append(it->second.data(), ll); if (attrsv.find(it->first) != attrsv.end()) { - ll = attrsv[it->first].size(); + ll = (unsigned short)attrsv[it->first].size(); d->append((char*)&ll, sizeof ll); d->append(attrsv[it->first].data(), ll); } @@ -585,14 +585,14 @@ bool User::mergePwdReminderData(int numDetails, const char *data, unsigned int s bool changed = false; // Timestamp for last successful validation of password in PRD - time_t tsLastSuccess; + long tsLastSuccess; size_t len = oldValue.find(":"); string buf = oldValue.substr(0, len) + "#"; // add character control '#' for conversion oldValue = oldValue.substr(len + 1); // skip ':' if (lastSuccess) { changed = true; - tsLastSuccess = time(NULL); + tsLastSuccess = (long)m_time(); } else { @@ -606,13 +606,13 @@ bool User::mergePwdReminderData(int numDetails, const char *data, unsigned int s } // Timestamp for last time the PRD was skipped - time_t tsLastSkipped; + long tsLastSkipped; len = oldValue.find(":"); buf = oldValue.substr(0, len) + "#"; oldValue = oldValue.substr(len + 1); if (lastSkipped) { - tsLastSkipped = time(NULL); + tsLastSkipped = (long)m_time(); changed = true; } else @@ -685,11 +685,11 @@ bool User::mergePwdReminderData(int numDetails, const char *data, unsigned int s } // Timestamp for last time user logged in - time_t tsLastLogin = 0; + long tsLastLogin = 0; len = oldValue.length(); if (lastLogin) { - tsLastLogin = time(NULL); + tsLastLogin = (long)m_time(); changed = true; } else diff --git a/src/utils.cpp b/src/utils.cpp index bda6bd6476..edfb1f776b 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -1088,5 +1088,62 @@ long long abs(long long n) return n >= 0 ? n : -n; } +struct tm* m_localtime(m_time_t ttime, struct tm *dt) +{ + // works for 32 or 64 bit time_t + time_t t = time_t(ttime); +#if (__cplusplus >= 201103L) && defined (__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__) + localtime_s(&t, dt); +#elif _MSC_VER >= 1400 // MSVCRT (2005+): std::localtime is threadsafe + struct tm *newtm = localtime(&t); + if (newtm) + { + memcpy(dt, newtm, sizeof(struct tm)); + } + else + { + memset(dt, 0, sizeof(struct tm)); + } +#elif _WIN32 + static MegaMutex * mtx = new MegaMutex(); + static bool initiated = false; + if (!initiated) + { + mtx->init(true); + initiated = true; + } + mtx->lock(); + struct tm *newtm = localtime(&t); + if (newtm) + { + memcpy(dt, newtm, sizeof(struct tm)); + } + else + { + memset(dt, 0, sizeof(struct tm)); + } + mtx->unlock(); +#else //POSIX + localtime_r(&t, dt); +#endif + return dt; +} + +m_time_t m_time(m_time_t* tt) +{ + // works for 32 or 64 bit time_t + time_t t = time(NULL); + if (tt) + { + *tt = t; + } + return t; +} + +m_time_t m_mktime(struct tm* stm) +{ + // works for 32 or 64 bit time_t + return mktime(stm); +} } // namespace diff --git a/tests/sdk_test.cpp b/tests/sdk_test.cpp index 9810a064f4..4ce88922ac 100644 --- a/tests/sdk_test.cpp +++ b/tests/sdk_test.cpp @@ -21,6 +21,13 @@ #include "sdk_test.h" +#ifdef WIN32 +void usleep(uint64_t n) +{ + Sleep(n / 1000); +} +#endif + void SdkTest::SetUp() { // do some initialization @@ -2040,7 +2047,7 @@ TEST_F(SdkTest, SdkTestChat) // --- Check list of available chats --- (fetch is done at SetUp()) - uint numChats = chats.size(); // permanent chats cannot be deleted, so they're kept forever + size_t numChats = chats.size(); // permanent chats cannot be deleted, so they're kept forever // --- Create a group chat --- @@ -2122,4 +2129,91 @@ TEST_F(SdkTest, SdkTestChat) } + +class myMIS : public MegaInputStream +{ +public: + int64_t size; + ifstream ifs; + + myMIS(const char* filename) + : ifs(filename, ios::binary) + { + ifs.seekg(0, ios::end); + size = ifs.tellg(); + ifs.seekg(0, ios::beg); + } + virtual int64_t getSize() { return size; } + + virtual bool read(char *buffer, size_t size) { + if (buffer) + { + ifs.read(buffer, size); + } + else + { + ifs.seekg(size, ios::cur); + } + return !ifs.fail(); + } +}; + + +TEST_F(SdkTest, SdkTestFingerprint) +{ + megaApi[0]->log(MegaApi::LOG_LEVEL_INFO, "___TEST fingerprint stream/file___"); + + int filesizes[] = { 10, 100, 1000, 10000, 100000, 10000000 }; + string expected[] = { + "DAQoBAMCAQQDAgEEAwAAAAAAAAQAypo7", + "DAWQjMO2LBXoNwH_agtF8CX73QQAypo7", + "EAugDFlhW_VTCMboWWFb9VMIxugQAypo7", + "EAhAnWCqOGBx0gGOWe7N6wznWRAQAypo7", + "GA6CGAQFLOwb40BGchttx22PvhZ5gQAypo7", + "GA4CWmAdW1TwQ-bddEIKTmSDv0b2QQAypo7", + }; + + FSACCESS_CLASS fsa; + string name = "testfile"; + string localname; + fsa.path2local(&name, &localname); + + int value = 0x01020304; + for (int i = sizeof filesizes / sizeof filesizes[0]; i--; ) + { + + { + ofstream ofs(name.c_str(), ios::binary); + char s[8192]; + ofs.rdbuf()->pubsetbuf(s, sizeof s); + for (int j = filesizes[i] / sizeof(value); j-- ; ) ofs.write((char*)&value, sizeof(value)); + ofs.write((char*)&value, filesizes[i] % sizeof(value)); + } + + { + fsa.setmtimelocal(&localname, 1000000000); + } + + string streamfp, filefp; + { + m_time_t mtime = 0; + { + FileAccess* nfa = fsa.newfileaccess(); + nfa->fopen(&localname); + mtime = nfa->mtime; + delete nfa; + } + + myMIS mis(name.c_str()); + streamfp.assign(megaApi[0]->getFingerprint(&mis, mtime)); + } + + filefp = megaApi[0]->getFingerprint(name.c_str()); + + ASSERT_EQ(streamfp, filefp); + ASSERT_EQ(streamfp, expected[i]); + } +} + + #endif From 4336984a9ed1e8ee633515207933c03c381f1a2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alberto=20Rodr=C3=ADguez?= Date: Fri, 11 May 2018 12:04:08 +0200 Subject: [PATCH 08/17] Fix issue with numDetails request attribute --- src/megaapi_impl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/megaapi_impl.cpp b/src/megaapi_impl.cpp index 729b758809..2c4d860618 100644 --- a/src/megaapi_impl.cpp +++ b/src/megaapi_impl.cpp @@ -2390,7 +2390,7 @@ MegaRequestPrivate::MegaRequestPrivate(MegaRequestPrivate *request) this->setPrivateKey(request->getPrivateKey()); this->setAccess(request->getAccess()); this->setNumRetry(request->getNumRetry()); - this->numDetails = 0; + this->setNumDetails(request->getNumDetails()); this->setFile(request->getFile()); this->setParamType(request->getParamType()); this->setText(request->getText()); From 153534096cdfac5937dfd6d6efb56d3402e588cc Mon Sep 17 00:00:00 2001 From: Carolina Zato Date: Fri, 11 May 2018 12:17:48 +0200 Subject: [PATCH 09/17] Update Android bindings for rich links --- bindings/java/nz/mega/sdk/MegaApiJava.java | 160 ++++++++++++++++++++- 1 file changed, 159 insertions(+), 1 deletion(-) diff --git a/bindings/java/nz/mega/sdk/MegaApiJava.java b/bindings/java/nz/mega/sdk/MegaApiJava.java index 729a3e556c..c3b9720c13 100644 --- a/bindings/java/nz/mega/sdk/MegaApiJava.java +++ b/bindings/java/nz/mega/sdk/MegaApiJava.java @@ -1446,6 +1446,18 @@ public String getMyEmail() { public String getMyUserHandle() { return megaApi.getMyUserHandle(); } + + /** + * Returns the user handle of the currently open account + * + * If the MegaApi object isn't logged in, + * this function returns INVALID_HANDLE + * + * @return User handle of the account + */ + public long getMyUserHandleBinary(){ + return megaApi.getMyUserHandleBinary(); + } /** * Get the MegaUser of the currently open account @@ -1457,7 +1469,6 @@ public String getMyUserHandle() { * @note The visibility of your own user is unhdefined and shouldn't be used. * @return MegaUser of the currently open account, otherwise NULL */ - public MegaUser getMyUser(){ return megaApi.getMyUser(); } @@ -3395,6 +3406,153 @@ public void shouldShowPasswordReminderDialog(boolean atLogout, MegaRequestListen megaApi.shouldShowPasswordReminderDialog(atLogout, createDelegateRequestListener(listener)); } + /** + * Enable or disable the generation of rich previews + * + * The associated request type with this request is MegaRequest::TYPE_SET_ATTR_USER + * Valid data in the MegaRequest object received on callbacks: + * - MegaRequest::getParamType - Returns the attribute type MegaApi::USER_ATTR_RICH_PREVIEWS + * + * @param enable True to enable the generation of rich previews + * @param listener MegaRequestListener to track this request + */ + public void enableRichPreviews(boolean enable, MegaRequestListenerInterface listener){ + megaApi.enableRichPreviews(enable, createDelegateRequestListener(listener)); + } + + /** + * Enable or disable the generation of rich previews + * + * The associated request type with this request is MegaRequest::TYPE_SET_ATTR_USER + * Valid data in the MegaRequest object received on callbacks: + * - MegaRequest::getParamType - Returns the attribute type MegaApi::USER_ATTR_RICH_PREVIEWS + * + * @param enable True to enable the generation of rich previews + */ + public void enableRichPreviews(boolean enable){ + megaApi.enableRichPreviews(enable); + } + + /** + * Check if rich previews are automatically generated + * + * The associated request type with this request is MegaRequest::TYPE_GET_ATTR_USER + * Valid data in the MegaRequest object received on callbacks: + * - MegaRequest::getParamType - Returns the attribute type MegaApi::USER_ATTR_RICH_PREVIEWS + * - MegaRequest::getNumDetails - Returns zero + * + * Valid data in the MegaRequest object received in onRequestFinish when the error code + * is MegaError::API_OK: + * - MegaRequest::getFlag - Returns true if generation of rich previews is enabled + * - MegaRequest::getMegaStringMap - Returns the raw content of the atribute: []* + * + * If the corresponding user attribute is not set yet, the request will fail with the + * error code MegaError::API_ENOENT, but the value of MegaRequest::getFlag will still be valid (false). + * + * @param listener MegaRequestListener to track this request + */ + public void isRichPreviewsEnabled(MegaRequestListenerInterface listener){ + megaApi.isRichPreviewsEnabled(createDelegateRequestListener(listener)); + } + + /** + * Check if rich previews are automatically generated + * + * The associated request type with this request is MegaRequest::TYPE_GET_ATTR_USER + * Valid data in the MegaRequest object received on callbacks: + * - MegaRequest::getParamType - Returns the attribute type MegaApi::USER_ATTR_RICH_PREVIEWS + * - MegaRequest::getNumDetails - Returns zero + * + * Valid data in the MegaRequest object received in onRequestFinish when the error code + * is MegaError::API_OK: + * - MegaRequest::getFlag - Returns true if generation of rich previews is enabled + * - MegaRequest::getMegaStringMap - Returns the raw content of the atribute: []* + * + * If the corresponding user attribute is not set yet, the request will fail with the + * error code MegaError::API_ENOENT, but the value of MegaRequest::getFlag will still be valid (false). + * + */ + public void isRichPreviewsEnabled(){ + megaApi.isRichPreviewsEnabled(); + } + + /** + * Check if the app should show the rich link warning dialog to the user + * + * The associated request type with this request is MegaRequest::TYPE_GET_ATTR_USER + * Valid data in the MegaRequest object received on callbacks: + * - MegaRequest::getParamType - Returns the attribute type MegaApi::USER_ATTR_RICH_PREVIEWS + * - MegaRequest::getNumDetails - Returns one + * + * Valid data in the MegaRequest object received in onRequestFinish when the error code + * is MegaError::API_OK: + * - MegaRequest::getFlag - Returns true if it is necessary to show the rich link warning + * - MegaRequest::getNumber - Returns the number of times that user has indicated that doesn't want + * modify the message with a rich link. If number is bigger than three, the extra option "Never" + * must be added to the warning dialog. + * - MegaRequest::getMegaStringMap - Returns the raw content of the atribute: []* + * + * If the corresponding user attribute is not set yet, the request will fail with the + * error code MegaError::API_ENOENT, but the value of MegaRequest::getFlag will still be valid (true). + * + * @param listener MegaRequestListener to track this request + */ + public void shouldShowRichLinkWarning(MegaRequestListenerInterface listener){ + megaApi.shouldShowRichLinkWarning(createDelegateRequestListener(listener)); + } + + /** + * Check if the app should show the rich link warning dialog to the user + * + * The associated request type with this request is MegaRequest::TYPE_GET_ATTR_USER + * Valid data in the MegaRequest object received on callbacks: + * - MegaRequest::getParamType - Returns the attribute type MegaApi::USER_ATTR_RICH_PREVIEWS + * - MegaRequest::getNumDetails - Returns one + * + * Valid data in the MegaRequest object received in onRequestFinish when the error code + * is MegaError::API_OK: + * - MegaRequest::getFlag - Returns true if it is necessary to show the rich link warning + * - MegaRequest::getNumber - Returns the number of times that user has indicated that doesn't want + * modify the message with a rich link. If number is bigger than three, the extra option "Never" + * must be added to the warning dialog. + * - MegaRequest::getMegaStringMap - Returns the raw content of the atribute: []* + * + * If the corresponding user attribute is not set yet, the request will fail with the + * error code MegaError::API_ENOENT, but the value of MegaRequest::getFlag will still be valid (true). + * + */ + public void shouldShowRichLinkWarning(){ + + megaApi.shouldShowRichLinkWarning(); + } + + /** + * Set the number of times "Not now" option has been selected in the rich link warning dialog + * + * The associated request type with this request is MegaRequest::TYPE_SET_ATTR_USER + * Valid data in the MegaRequest object received on callbacks: + * - MegaRequest::getParamType - Returns the attribute type MegaApi::USER_ATTR_RICH_PREVIEWS + * + * @param value Number of times "Not now" option has been selected + * @param listener MegaRequestListener to track this request + */ + public void setRichLinkWarningCounterValue(int value, MegaRequestListenerInterface listener){ + megaApi.setRichLinkWarningCounterValue(value, createDelegateRequestListener(listener)); + } + + /** + * Set the number of times "Not now" option has been selected in the rich link warning dialog + * + * The associated request type with this request is MegaRequest::TYPE_SET_ATTR_USER + * Valid data in the MegaRequest object received on callbacks: + * - MegaRequest::getParamType - Returns the attribute type MegaApi::USER_ATTR_RICH_PREVIEWS + * + * @param value Number of times "Not now" option has been selected + */ + public void setRichLinkWarningCounterValue(int value){ + megaApi.setRichLinkWarningCounterValue(value); + } + /** * Change the password of the MEGA account * From 5c168150c1791f2038f40309603a08c09bbb5dfb Mon Sep 17 00:00:00 2001 From: Matt Weir Date: Tue, 15 May 2018 10:34:58 +1200 Subject: [PATCH 10/17] reverse change for include <> vs include "" for some files, which may cause problems on iOS. Will investigate further in Visual Studio as to why there were issues, but any change will be for a later PR. --- include/mega.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/mega.h b/include/mega.h index f71dc71040..6842ac5ac0 100644 --- a/include/mega.h +++ b/include/mega.h @@ -72,11 +72,11 @@ #include "mega/thread/win32thread.h" #include "mega/thread/cppthread.h" -#include -#include -#include -#include -#include +#include "megawaiter.h" +#include "meganet.h" +#include "megafs.h" +#include "megaconsole.h" +#include "megaconsolewaiter.h" #include "mega/db/sqlite.h" #include "mega/db/bdb.h" From e7a4bc86fab3a7424246e44011dd41afe9247a7e Mon Sep 17 00:00:00 2001 From: Javier Navarro Date: Wed, 16 May 2018 12:57:18 +0200 Subject: [PATCH 11/17] Documentation minor fixes --- include/mega/utils.h | 5 +---- include/megaapi.h | 19 +++++++++---------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/include/mega/utils.h b/include/mega/utils.h index 428bdcdc16..6645040161 100644 --- a/include/mega/utils.h +++ b/include/mega/utils.h @@ -1,4 +1,4 @@ -/** +/** * @file mega/utils.h * @brief Mega SDK various utilities and helper classes * @@ -238,7 +238,6 @@ struct MEGA_API TLVstore /** * @brief containerToTLVrecords Builds a TLV object with records from an encrypted container * @param data Binary byte array representing the encrypted container - * @param datalen Length of the byte array. * @param key Master key to decrypt the container * @return A new TLVstore object. You take the ownership of the object. */ @@ -247,7 +246,6 @@ struct MEGA_API TLVstore /** * @brief Builds a TLV object with records from a container * @param data Binary byte array representing the TLV records - * @param datalen Length of the byte array. * @return A new TLVstore object. You take the ownership of the object. */ static TLVstore * containerToTLVrecords(const string *data); @@ -303,7 +301,6 @@ struct MEGA_API TLVstore * @brief add Adds a new record to the container * @param type Type for the new value (without scope nor non-historic modifiers). * @param value New value to be set. - * @return */ void set(string type, string value); diff --git a/include/megaapi.h b/include/megaapi.h index 84bc6d8510..95e9b73520 100644 --- a/include/megaapi.h +++ b/include/megaapi.h @@ -991,7 +991,7 @@ class MegaNode * * You take the ownership of the returned value. * - * @param Serialization of a MegaNode object obtained from a chat message (in Base64) + * @param d Serialization of a MegaNode object obtained from a chat message (in Base64) * @return A new MegaNode object, or NULL if error. */ static MegaNode* unserialize(const char *d); @@ -1819,7 +1819,7 @@ class MegaNodeList /** * @brief Add new node to list - * @param MegaNode to be added. The node inserted is a copy from 'node' + * @param node MegaNode to be added. The node inserted is a copy from 'node' */ virtual void addNode(MegaNode* node); }; @@ -5186,7 +5186,7 @@ class MegaApi * You take the ownership of the returned value * You can revert this operation using MegaApi::base64ToUserHandle * - * @param User handle to be converted + * @param handle User handle to be converted * @return Base64-encoded user handle */ static char* userHandleToBase64(MegaHandle handle); @@ -5326,7 +5326,7 @@ class MegaApi * * If you use mega::INVALID_HANDLE, all sessions except the current one will be closed * - * @param Handle of the session. Use mega::INVALID_HANDLE to cancel all sessions except the current one + * @param sessionHandle Handle of the session. Use mega::INVALID_HANDLE to cancel all sessions except the current one * @param listener MegaRequestListener to track this request */ void killSession(MegaHandle sessionHandle, MegaRequestListener *listener = NULL); @@ -6490,7 +6490,7 @@ class MegaApi * - MegaRequest::getFile - Returns the destination path * - MegaRequest::getEmail - Returns the email or the handle of the user (the provided one as parameter) * - * @param user email_or_user Email or user handle (Base64 encoded) to get the avatar. If this parameter is + * @param email_or_user Email or user handle (Base64 encoded) to get the avatar. If this parameter is * set to NULL, the avatar is obtained for the active account * @param dstFilePath Destination path for the avatar. It has to be a path to a file, not to a folder. * If this path is a local folder, it must end with a '\' or '/' character and (email + "0.jpg") @@ -9133,7 +9133,7 @@ class MegaApi * * You take the ownership of the returned value * - * @param parent Parent node + * @param p Parent node * @param order Order for the returned lists * Valid values for this parameter are: * - MegaApi::ORDER_NONE = 0 @@ -10100,7 +10100,7 @@ class MegaApi /** * @brief Set the language code used by the app - * @param Language code used by the app + * @param languageCode Language code used by the app * * @return True if the language code is known for the SDK, otherwise false */ @@ -10566,7 +10566,7 @@ class MegaApi * other configuration options (MegaApi::httpServerEnableFileServer, * MegaApi::httpServerEnableFolderServer) are still applied. * - * @param Required state for the restricted mode of the HTTP proxy server + * @param mode Required state for the restricted mode of the HTTP proxy server */ void httpServerSetRestrictedMode(int mode); @@ -10721,8 +10721,7 @@ class MegaApi * @brief Stops serving a node via webdav. * The webdav link will no longer be valid. * - * @param handle Handle of the node to stop serving - * @return URL to the node in the local HTTP proxy server, otherwise NULL + * @param handle Handle of the node to stop serving */ void httpServerRemoveWebDavAllowedNode(MegaHandle handle); From ce625b964cf04f42c89dae4e2e642914f818c4c4 Mon Sep 17 00:00:00 2001 From: Pablo Martin Date: Fri, 18 May 2018 14:01:15 +0200 Subject: [PATCH 12/17] use isnan instead of std::isnan for mac --- src/gfx/qt.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gfx/qt.cpp b/src/gfx/qt.cpp index 8cf83ecf33..6fb19dd342 100644 --- a/src/gfx/qt.cpp +++ b/src/gfx/qt.cpp @@ -834,7 +834,11 @@ QImageReader *GfxProcQT::readbitmapFfmpeg(int &w, int &h, int &orientation, QStr { double rot = av_display_rotation_get((int32_t*) displaymatrix); #if __cplusplus >= 201103L +#ifndef __APPLE__ if (!std::isnan(rot)) +#else + if (!isnan(rot)) +#endif #else if (!(rot != rot)) #endif From f896db271d66c0f2b8e322cb81675d55c2128080 Mon Sep 17 00:00:00 2001 From: Matt Weir Date: Sat, 19 May 2018 12:56:19 +1200 Subject: [PATCH 13/17] after review: additional conversions to m_time_t for user password management functions; no need to support old pre 2005 MSVC; tidy up new fingerprint test --- contrib/cmake/CMakeLists.txt | 2 +- include/mega/user.h | 2 +- src/user.cpp | 67 +++++++++++++++--------------------- src/utils.cpp | 19 +--------- tests/sdk_test.cpp | 4 +-- 5 files changed, 32 insertions(+), 62 deletions(-) diff --git a/contrib/cmake/CMakeLists.txt b/contrib/cmake/CMakeLists.txt index 56b9901599..bd81e63921 100644 --- a/contrib/cmake/CMakeLists.txt +++ b/contrib/cmake/CMakeLists.txt @@ -215,7 +215,7 @@ add_library(Mega STATIC ${MegaDir}/src/json.cpp ${MegaDir}/src/logging.cpp ${MegaDir}/src/mediafileattribute.cpp - ${MegaDir}/src/mega_ccronexpr.cpp +# ${MegaDir}/src/mega_ccronexpr.cpp ${MegaDir}/src/mega_http_parser.cpp ${MegaDir}/src/mega_utf8proc.cpp ${MegaDir}/src/mega_zxcvbn.cpp diff --git a/include/mega/user.h b/include/mega/user.h index b6b7a98b1c..6b4bd15aff 100644 --- a/include/mega/user.h +++ b/include/mega/user.h @@ -124,7 +124,7 @@ struct MEGA_API User : public Cachable static const int PWD_SHOW_AFTER_LASTSKIP_LOGOUT = 1 * 30 * 24 * 60 * 60; static bool mergePwdReminderData(int numDetails, const char *data, unsigned int size, string *newValue); - static time_t getPwdReminderData(int numDetail, const char *data, unsigned int size); + static m_time_t getPwdReminderData(int numDetail, const char *data, unsigned int size); bool setChanged(attr_t at); diff --git a/src/user.cpp b/src/user.cpp index 050c0e8e90..932ad07c8a 100644 --- a/src/user.cpp +++ b/src/user.cpp @@ -585,20 +585,20 @@ bool User::mergePwdReminderData(int numDetails, const char *data, unsigned int s bool changed = false; // Timestamp for last successful validation of password in PRD - long tsLastSuccess; + m_time_t tsLastSuccess; size_t len = oldValue.find(":"); string buf = oldValue.substr(0, len) + "#"; // add character control '#' for conversion oldValue = oldValue.substr(len + 1); // skip ':' if (lastSuccess) { changed = true; - tsLastSuccess = (long)m_time(); + tsLastSuccess = m_time(); } else { char *pEnd = NULL; - tsLastSuccess = strtol(buf.data(), &pEnd, 10); - if (*pEnd != '#' || tsLastSuccess == LONG_MAX || tsLastSuccess == LONG_MIN) + tsLastSuccess = strtoll(buf.data(), &pEnd, 10); + if (*pEnd != '#' || tsLastSuccess == LLONG_MAX || tsLastSuccess == LLONG_MIN) { tsLastSuccess = 0; changed = true; @@ -606,20 +606,20 @@ bool User::mergePwdReminderData(int numDetails, const char *data, unsigned int s } // Timestamp for last time the PRD was skipped - long tsLastSkipped; + m_time_t tsLastSkipped; len = oldValue.find(":"); buf = oldValue.substr(0, len) + "#"; oldValue = oldValue.substr(len + 1); if (lastSkipped) { - tsLastSkipped = (long)m_time(); + tsLastSkipped = m_time(); changed = true; } else { char *pEnd = NULL; - tsLastSkipped = strtol(buf.data(), &pEnd, 10); - if (*pEnd != '#' || tsLastSkipped == LONG_MAX || tsLastSkipped == LONG_MIN) + tsLastSkipped = strtoll(buf.data(), &pEnd, 10); + if (*pEnd != '#' || tsLastSkipped == LLONG_MAX || tsLastSkipped == LLONG_MIN) { tsLastSkipped = 0; changed = true; @@ -685,11 +685,11 @@ bool User::mergePwdReminderData(int numDetails, const char *data, unsigned int s } // Timestamp for last time user logged in - long tsLastLogin = 0; + m_time_t tsLastLogin = 0; len = oldValue.length(); if (lastLogin) { - tsLastLogin = (long)m_time(); + tsLastLogin = m_time(); changed = true; } else @@ -697,8 +697,8 @@ bool User::mergePwdReminderData(int numDetails, const char *data, unsigned int s buf = oldValue.substr(0, len) + "#"; char *pEnd = NULL; - tsLastLogin = strtol(buf.data(), &pEnd, 10); - if (*pEnd != '#' || tsLastLogin == LONG_MAX || tsLastLogin == LONG_MIN) + tsLastLogin = strtoll(buf.data(), &pEnd, 10); + if (*pEnd != '#' || tsLastLogin == LLONG_MAX || tsLastLogin == LLONG_MIN) { tsLastLogin = 0; changed = true; @@ -714,7 +714,7 @@ bool User::mergePwdReminderData(int numDetails, const char *data, unsigned int s return changed; } -time_t User::getPwdReminderData(int numDetail, const char *data, unsigned int size) +m_time_t User::getPwdReminderData(int numDetail, const char *data, unsigned int size) { if (!numDetail || !data || !size) { @@ -739,15 +739,15 @@ time_t User::getPwdReminderData(int numDetail, const char *data, unsigned int si bool lastLogin = (numDetail & PWD_LAST_LOGIN) != 0; // Timestamp for last successful validation of password in PRD - time_t tsLastSuccess; + m_time_t tsLastSuccess; size_t len = value.find(":"); string buf = value.substr(0, len) + "#"; // add character control '#' for conversion value = value.substr(len + 1); // skip ':' if (lastSuccess) { char *pEnd = NULL; - tsLastSuccess = strtol(buf.data(), &pEnd, 10); - if (*pEnd != '#' || tsLastSuccess == LONG_MAX || tsLastSuccess == LONG_MIN) + tsLastSuccess = strtoll(buf.data(), &pEnd, 10); + if (*pEnd != '#' || tsLastSuccess == LLONG_MAX || tsLastSuccess == LLONG_MIN) { tsLastSuccess = 0; } @@ -755,15 +755,15 @@ time_t User::getPwdReminderData(int numDetail, const char *data, unsigned int si } // Timestamp for last time the PRD was skipped - time_t tsLastSkipped; + m_time_t tsLastSkipped; len = value.find(":"); buf = value.substr(0, len) + "#"; value = value.substr(len + 1); if (lastSkipped) { char *pEnd = NULL; - tsLastSkipped = strtol(buf.data(), &pEnd, 10); - if (*pEnd != '#' || tsLastSkipped == LONG_MAX || tsLastSkipped == LONG_MIN) + tsLastSkipped = strtoll(buf.data(), &pEnd, 10); + if (*pEnd != '#' || tsLastSkipped == LLONG_MAX || tsLastSkipped == LLONG_MIN) { tsLastSkipped = 0; } @@ -771,56 +771,45 @@ time_t User::getPwdReminderData(int numDetail, const char *data, unsigned int si } // Flag for Recovery Key exported - bool flagMkExported; len = value.find(":"); buf = value.substr(0, len) + "#"; value = value.substr(len + 1); if (mkExported) { char *pEnd = NULL; - int tmp = strtol(buf.data(), &pEnd, 10); - if (*pEnd != '#' || (tmp != 0 && tmp != 1)) + m_time_t flagMkExported = strtoll(buf.data(), &pEnd, 10); + if (*pEnd != '#' || (flagMkExported != 0 && flagMkExported != 1)) { - flagMkExported = false; + flagMkExported = 0; } - else - { - flagMkExported = tmp; - } - return flagMkExported; } // Flag for "Don't show again" the PRD - bool flagDontShowAgain; len = value.find(":"); buf = value.substr(0, len) + "#"; value = value.substr(len + 1); if (dontShowAgain) { char *pEnd = NULL; - int tmp = strtol(buf.data(), &pEnd, 10); - if (*pEnd != '#' || (tmp != 0 && tmp != 1)) - { - flagDontShowAgain = false; - } - else + m_time_t flagDontShowAgain = strtoll(buf.data(), &pEnd, 10); + if (*pEnd != '#' || (flagDontShowAgain != 0 && flagDontShowAgain != 1)) { - flagDontShowAgain = tmp; + flagDontShowAgain = 0; } return flagDontShowAgain; } // Timestamp for last time user logged in - time_t tsLastLogin = 0; + m_time_t tsLastLogin = 0; len = value.length(); if (lastLogin) { buf = value.substr(0, len) + "#"; char *pEnd = NULL; - tsLastLogin = strtol(buf.data(), &pEnd, 10); - if (*pEnd != '#' || tsLastLogin == LONG_MAX || tsLastLogin == LONG_MIN) + tsLastLogin = strtoll(buf.data(), &pEnd, 10); + if (*pEnd != '#' || tsLastLogin == LLONG_MAX || tsLastLogin == LLONG_MIN) { tsLastLogin = 0; } diff --git a/src/utils.cpp b/src/utils.cpp index edfb1f776b..f75f1d9613 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -1105,24 +1105,7 @@ struct tm* m_localtime(m_time_t ttime, struct tm *dt) memset(dt, 0, sizeof(struct tm)); } #elif _WIN32 - static MegaMutex * mtx = new MegaMutex(); - static bool initiated = false; - if (!initiated) - { - mtx->init(true); - initiated = true; - } - mtx->lock(); - struct tm *newtm = localtime(&t); - if (newtm) - { - memcpy(dt, newtm, sizeof(struct tm)); - } - else - { - memset(dt, 0, sizeof(struct tm)); - } - mtx->unlock(); +#error "localtime is not thread safe in this compiler; please use a later one" #else //POSIX localtime_r(&t, dt); #endif diff --git a/tests/sdk_test.cpp b/tests/sdk_test.cpp index 4ce88922ac..4a351d1d68 100644 --- a/tests/sdk_test.cpp +++ b/tests/sdk_test.cpp @@ -2190,9 +2190,7 @@ TEST_F(SdkTest, SdkTestFingerprint) ofs.write((char*)&value, filesizes[i] % sizeof(value)); } - { - fsa.setmtimelocal(&localname, 1000000000); - } + fsa.setmtimelocal(&localname, 1000000000); string streamfp, filefp; { From ee890c9ce0d11443ccbcaba76da93d3a8257b057 Mon Sep 17 00:00:00 2001 From: Pablo Martin Date: Mon, 21 May 2018 12:33:12 +0200 Subject: [PATCH 14/17] asume localtime is threadsafe for mingw --- src/utils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils.cpp b/src/utils.cpp index f75f1d9613..e2611188d5 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -1094,7 +1094,7 @@ struct tm* m_localtime(m_time_t ttime, struct tm *dt) time_t t = time_t(ttime); #if (__cplusplus >= 201103L) && defined (__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__) localtime_s(&t, dt); -#elif _MSC_VER >= 1400 // MSVCRT (2005+): std::localtime is threadsafe +#elif _MSC_VER >= 1400 || defined(__MINGW32__) // MSVCRT (2005+): std::localtime is threadsafe struct tm *newtm = localtime(&t); if (newtm) { From 918c0417d739b197c5914fc21326897067aaede3 Mon Sep 17 00:00:00 2001 From: Javier Santana Espejo Date: Tue, 22 May 2018 09:36:56 +0200 Subject: [PATCH 15/17] Updated Objective-C bindings --- bindings/ios/MEGASdk.h | 4 ++-- bindings/ios/MEGASdk.mm | 12 ++++-------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/bindings/ios/MEGASdk.h b/bindings/ios/MEGASdk.h index 3a1362ce7f..55125b7f7b 100644 --- a/bindings/ios/MEGASdk.h +++ b/bindings/ios/MEGASdk.h @@ -2105,7 +2105,7 @@ typedef NS_ENUM(NSUInteger, Retry) { * @param longitude Longitude in signed decimal degrees notation. * @param delegate Delegate to track this request. */ -- (void)setNodeCoordinates:(MEGANode *)node latitude:(NSNumber *)latitude longitude:(NSNumber *)longitude delegate:(id)delegate; +- (void)setNodeCoordinates:(MEGANode *)node latitude:(double)latitude longitude:(double)longitude delegate:(id)delegate; /** * @brief Set the GPS coordinates of image files as a node attribute. @@ -2124,7 +2124,7 @@ typedef NS_ENUM(NSUInteger, Retry) { * @param latitude Latitude in signed decimal degrees notation. * @param longitude Longitude in signed decimal degrees notation. */ -- (void)setNodeCoordinates:(MEGANode *)node latitude:(NSNumber *)latitude longitude:(NSNumber *)longitude; +- (void)setNodeCoordinates:(MEGANode *)node latitude:(double)latitude longitude:(double)longitude; /** * @brief Generate a public link of a file/folder in MEGA. diff --git a/bindings/ios/MEGASdk.mm b/bindings/ios/MEGASdk.mm index 708e756dcd..3b3b11d86a 100644 --- a/bindings/ios/MEGASdk.mm +++ b/bindings/ios/MEGASdk.mm @@ -787,16 +787,12 @@ - (void)publicNodeForMegaFileLink:(NSString *)megaFileLink { self.megaApi->getPublicNode((megaFileLink != nil) ? [megaFileLink UTF8String] : NULL); } -- (void)setNodeCoordinates:(MEGANode *)node latitude:(NSNumber *)latitude longitude:(NSNumber *)longitude delegate:(id)delegate { - double lat = latitude != nil ? latitude.doubleValue : MegaNode::INVALID_COORDINATE; - double lon = longitude != nil ? longitude.doubleValue : MegaNode::INVALID_COORDINATE; - self.megaApi->setNodeCoordinates((node != nil) ? [node getCPtr] : NULL, lat, lon, [self createDelegateMEGARequestListener:delegate singleListener:YES]); +- (void)setNodeCoordinates:(MEGANode *)node latitude:(double)latitude longitude:(double)longitude delegate:(id)delegate { + self.megaApi->setNodeCoordinates(node ? [node getCPtr] : NULL, (latitude ? latitude : MegaNode::INVALID_COORDINATE), (longitude ? longitude : MegaNode::INVALID_COORDINATE), [self createDelegateMEGARequestListener:delegate singleListener:YES]); } -- (void)setNodeCoordinates:(MEGANode *)node latitude:(NSNumber *)latitude longitude:(NSNumber *)longitude { - double lat = latitude != nil ? latitude.doubleValue : MegaNode::INVALID_COORDINATE; - double lon = longitude != nil ? longitude.doubleValue : MegaNode::INVALID_COORDINATE; - self.megaApi->setNodeCoordinates((node != nil) ? [node getCPtr] : NULL, lat, lon); +- (void)setNodeCoordinates:(MEGANode *)node latitude:(double)latitude longitude:(double)longitude { + self.megaApi->setNodeCoordinates(node ? [node getCPtr] : NULL, (latitude ? latitude : MegaNode::INVALID_COORDINATE), (longitude ? longitude : MegaNode::INVALID_COORDINATE)); } - (void)exportNode:(MEGANode *)node delegate:(id)delegate { From 07cefc9736af4b3fc466dfa5a61077f81cfc2a37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20Hern=C3=A1ndez?= Date: Tue, 22 May 2018 10:07:26 +0200 Subject: [PATCH 16/17] Update version number --- include/mega/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mega/version.h b/include/mega/version.h index 6fb3a8e9ea..74884dad75 100644 --- a/include/mega/version.h +++ b/include/mega/version.h @@ -5,5 +5,5 @@ #define MEGA_MINOR_VERSION 3 #endif #ifndef MEGA_MICRO_VERSION -#define MEGA_MICRO_VERSION 7 +#define MEGA_MICRO_VERSION 8 #endif From d8559161e7b87cd718b325e6c7a4473d2f02dfde Mon Sep 17 00:00:00 2001 From: Javier Gomez Date: Tue, 22 May 2018 11:20:52 +0200 Subject: [PATCH 17/17] Fix the compilation for Windows Phone in VS2013 --- include/mega/win32/megasys.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/mega/win32/megasys.h b/include/mega/win32/megasys.h index 84df3bf545..0115a825ef 100644 --- a/include/mega/win32/megasys.h +++ b/include/mega/win32/megasys.h @@ -91,6 +91,9 @@ #define strcasecmp _stricmp #define strncasecmp _strnicmp #define strtoull _strtoui64 +#if _MSC_VER <= 1800 // Visual Studio 2013 +#define strtoll _strtoi64 +#endif #ifndef _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS