diff --git a/build_scripts/Windows-msys2/build/build-webui.bat b/build_scripts/Windows-msys2/build/build-webui.bat new file mode 100644 index 000000000..d561235c1 --- /dev/null +++ b/build_scripts/Windows-msys2/build/build-webui.bat @@ -0,0 +1,37 @@ +@echo off + +setlocal + +:: Initialize environment +call "%~dp0..\env.bat" +if errorlevel 1 goto error_env +call "%EnvPath%\env.bat" +if errorlevel 1 goto error_env +call "%EnvPath%\env.bat" +if errorlevel 1 goto error_env +call "%EnvPath%\env-msys2.bat" +if errorlevel 1 goto error_env + +:: Initialize base environment +call "%~dp0env-base.bat" %* +if errorlevel 2 exit /B 2 +if errorlevel 1 goto error_env + +:: Initialize environment +call "%~dp0env.bat" %* +if errorlevel 2 exit /B 2 +if errorlevel 1 goto error_env + +call "%~dp0..\tools\webui.bat" + +:error + +title %COMSPEC% + +if errorlevel 1 echo.& echo Webui generation failed& echo. +exit /B %ERRORLEVEL% + +:error_env +echo Failed to initialize environment. +endlocal +exit /B 1 diff --git a/build_scripts/Windows-msys2/build/build.bat b/build_scripts/Windows-msys2/build/build.bat index d15e5babc..8ca2f6f1f 100644 --- a/build_scripts/Windows-msys2/build/build.bat +++ b/build_scripts/Windows-msys2/build/build.bat @@ -18,7 +18,7 @@ if errorlevel 2 exit /B 2 if errorlevel 1 goto error_env :: Install needed things -%EnvMSYS2Cmd% "pacman --noconfirm --needed -S make git mingw-w64-%RsMSYS2Architecture%-toolchain mingw-w64-%RsMSYS2Architecture%-qt5 mingw-w64-%RsMSYS2Architecture%-miniupnpc mingw-w64-%RsMSYS2Architecture%-sqlcipher mingw-w64-%RsMSYS2Architecture%-libmicrohttpd mingw-w64-%RsMSYS2Architecture%-xapian-core mingw-w64-%RsMSYS2Architecture%-cmake mingw-w64-%RsMSYS2Architecture%-rapidjson" +%EnvMSYS2Cmd% "pacman --noconfirm --needed -S make git mingw-w64-%RsMSYS2Architecture%-toolchain mingw-w64-%RsMSYS2Architecture%-qt5 mingw-w64-%RsMSYS2Architecture%-miniupnpc mingw-w64-%RsMSYS2Architecture%-sqlcipher mingw-w64-%RsMSYS2Architecture%-xapian-core mingw-w64-%RsMSYS2Architecture%-cmake mingw-w64-%RsMSYS2Architecture%-rapidjson" :: Plugins if "%ParamPlugins%"=="1" %EnvMSYS2Cmd% "pacman --noconfirm --needed -S mingw-w64-%RsMSYS2Architecture%-speex mingw-w64-%RsMSYS2Architecture%-speexdsp mingw-w64-%RsMSYS2Architecture%-curl mingw-w64-%RsMSYS2Architecture%-libxslt mingw-w64-%RsMSYS2Architecture%-opencv mingw-w64-%RsMSYS2Architecture%-ffmpeg" @@ -52,6 +52,12 @@ set RS_QMAKE_CONFIG=%RS_QMAKE_CONFIG% "CONFIG+=%RsBuildConfig%" if "%ParamAutologin%"=="1" set RS_QMAKE_CONFIG=%RS_QMAKE_CONFIG% "CONFIG+=rs_autologin" if "%ParamPlugins%"=="1" set RS_QMAKE_CONFIG=%RS_QMAKE_CONFIG% "CONFIG+=retroshare_plugins" +:: Dump the active build config into a file +echo %RS_QMAKE_CONFIG% > buildinfo.txt +echo %RsBuildConfig% >> buildinfo.txt +echo %RsArchitecture% >> buildinfo.txt +echo Qt %QtVersion% >> buildinfo.txt + call "%ToolsPath%\msys2-path.bat" "%SourcePath%" MSYS2SourcePath call "%ToolsPath%\msys2-path.bat" "%EnvMSYS2Path%" MSYS2EnvMSYS2Path %EnvMSYS2Cmd% "qmake "%MSYS2SourcePath%/RetroShare.pro" -r -spec win32-g++ %RS_QMAKE_CONFIG%" @@ -65,6 +71,11 @@ title Build - %SourceName%-%RsBuildConfig% [make] %EnvMSYS2Cmd% "make -j %NUMBER_OF_PROCESSORS%" +:: Webui +if "%ParamWebui%"=="1" ( + call "%~dp0..\tools\webui.bat" +) + :error popd diff --git a/build_scripts/Windows-msys2/build/env-base.bat b/build_scripts/Windows-msys2/build/env-base.bat index 0140196ec..8f80e8681 100644 --- a/build_scripts/Windows-msys2/build/env-base.bat +++ b/build_scripts/Windows-msys2/build/env-base.bat @@ -6,6 +6,7 @@ set ParamDebug=0 set ParamAutologin=0 set ParamPlugins=0 set ParamTor=0 +set ParamWebui=0 set RS_QMAKE_CONFIG= :parameter_loop @@ -25,6 +26,8 @@ if "%~1" NEQ "" ( set ParamPlugins=1 ) else if "%%~a"=="tor" ( set ParamTor=1 + ) else if "%%~a"=="webui" ( + set ParamWebui=1 ) else if "%%~a"=="CONFIG+" ( set RS_QMAKE_CONFIG=%RS_QMAKE_CONFIG% %1 ) else ( @@ -75,12 +78,15 @@ if "%ParamTor%"=="1" ( set RsType= ) +if "%ParamWebui%"=="1" ( + set RS_QMAKE_CONFIG=%RS_QMAKE_CONFIG% "CONFIG+=rs_jsonapi" "CONFIG+=rs_webui" +) exit /B 0 :usage echo. -echo Usage: 32^|64 release^|debug [version autologin plugins] +echo Usage: 32^|64 release^|debug [version autologin plugins webui] echo. echo Mandatory parameter echo 32^|64 32-bit or 64-bit Version @@ -89,6 +95,7 @@ echo. echo Optional parameter (need clean when changed) echo autologin Build with autologin echo plugins Build plugins +echo webui Enable JsonAPI and pack webui files echo. echo Parameter for pack echo tor Pack tor version diff --git a/build_scripts/Windows-msys2/build/env.bat b/build_scripts/Windows-msys2/build/env.bat index d7dcdf130..8443d6218 100644 --- a/build_scripts/Windows-msys2/build/env.bat +++ b/build_scripts/Windows-msys2/build/env.bat @@ -20,6 +20,7 @@ set RsBuildPath=%BuildPath%\Qt-%QtVersion%-%RsArchitecture%-%RsBuildConfig% set RsDeployPath=%DeployPath%\Qt-%QtVersion%%RsType%-%RsArchitecture%-%RsBuildConfig% set RsPackPath=%DeployPath% set RsArchiveAdd= +set RsWebuiPath=%RootPath%\%SourceName%-webui if not exist "%~dp0env-mod.bat" goto no_mod call "%~dp0env-mod.bat" diff --git a/build_scripts/Windows-msys2/build/git-log.bat b/build_scripts/Windows-msys2/build/git-log.bat index e3b42bf80..010ff190b 100644 --- a/build_scripts/Windows-msys2/build/git-log.bat +++ b/build_scripts/Windows-msys2/build/git-log.bat @@ -23,7 +23,7 @@ call "%ToolsPath%\find-in-path.bat" GitPath git.exe if "%GitPath%"=="" echo Git executable not found in PATH.& exit /B 1 :: Get compiled revision -set GetRsVersion=%SourcePath%\build_scripts\Windows\tools\get-rs-version.bat +set GetRsVersion=%SourcePath%\build_scripts\Windows-msys2\tools\get-rs-version.bat if not exist "%GetRsVersion%" ( echo File not found echo %GetRsVersion% diff --git a/build_scripts/Windows-msys2/build/pack.bat b/build_scripts/Windows-msys2/build/pack.bat index e8c9761bc..e759b7980 100644 --- a/build_scripts/Windows-msys2/build/pack.bat +++ b/build_scripts/Windows-msys2/build/pack.bat @@ -17,6 +17,9 @@ call "%~dp0env.bat" %* if errorlevel 2 exit /B 2 if errorlevel 1 goto error_env +:: Install ntldd +%EnvMSYS2Cmd% "pacman --noconfirm --needed -S make git mingw-w64-%RsMSYS2Architecture%-ntldd-git" + :: Remove deploy path if exist "%RsDeployPath%" rmdir /S /Q "%RsDeployPath%" @@ -24,7 +27,7 @@ if exist "%RsDeployPath%" rmdir /S /Q "%RsDeployPath%" if not exist "%RsBuildPath%\Makefile" echo Project is not compiled.& goto error :: Get compiled revision -set GetRsVersion=%SourcePath%\build_scripts\Windows\tools\get-rs-version.bat +set GetRsVersion=%SourcePath%\build_scripts\Windows-msys2\tools\get-rs-version.bat if not exist "%GetRsVersion%" ( %cecho% error "File not found" echo %GetRsVersion% @@ -100,16 +103,13 @@ echo copy binaries copy "%RsBuildPath%\retroshare-gui\src\%RsBuildConfig%\RetroShare*.exe" "%RsDeployPath%" %Quite% copy "%RsBuildPath%\retroshare-nogui\src\%RsBuildConfig%\retroshare*-nogui.exe" "%RsDeployPath%" %Quite% copy "%RsBuildPath%\retroshare-service\src\%RsBuildConfig%\retroshare*-service.exe" "%RsDeployPath%" %Quite% +copy "%RsBuildPath%\supportlibs\cmark\build\src\libcmark.dll" "%RsDeployPath%" %Quite% echo copy extensions for /D %%D in ("%RsBuildPath%\plugins\*") do ( call :copy_extension "%%D" "%RsDeployPath%\Data\%Extensions%" - call :copy_dependencies "%RsDeployPath%\Data\%Extensions%\%%~nxD.dll" "%RsDeployPath%" ) -echo copy dependencies -call :copy_dependencies "%RsDeployPath%\retroshare.exe" "%RsDeployPath%" - echo copy Qt DLL's copy "%RsMinGWPath%\bin\Qt%QtMainVersion1%Svg%QtMainVersion2%.dll" "%RsDeployPath%" %Quite% @@ -128,7 +128,9 @@ if exist "%QtSharePath%\plugins\styles\qwindowsvistastyle.dll" ( copy "%QtSharePath%\plugins\imageformats\*.dll" "%RsDeployPath%\imageformats" %Quite% del /Q "%RsDeployPath%\imageformats\*d?.dll" %Quite% -for %%D in ("%RsDeployPath%\imageformats\*.dll") do ( + +echo copy dependencies +for /R "%RsDeployPath%" %%D in (*.dll, *.exe) do ( call :copy_dependencies "%%D" "%RsDeployPath%" ) @@ -161,10 +163,18 @@ copy "%SourcePath%\libbitdht\src\bitdht\bdboot.txt" "%RsDeployPath%" %Quite% echo copy changelog.txt copy "%SourcePath%\retroshare-gui\src\changelog.txt" "%RsDeployPath%" %Quite% -if exist "%SourcePath%\libresapi\src\webui" ( - echo copy webui - mkdir "%RsDeployPath%\webui" - xcopy /S "%SourcePath%\libresapi\src\webui" "%RsDeployPath%\webui" %Quite% +echo copy buildinfo.txt +copy "%RsBuildPath%\buildinfo.txt" "%RsDeployPath%" %Quite% + +if "%ParamWebui%"=="1" ( + if exist "%RsWebuiPath%\webui" ( + echo copy webui + mkdir "%RsDeployPath%\webui" + xcopy /S "%RsWebuiPath%\webui" "%RsDeployPath%\webui" %Quite% + ) else ( + %cecho% error "Webui is enabled, but no webui data found at %RsWebuiPath%\webui" + goto error + ) ) if "%ParamTor%"=="1" ( @@ -204,14 +214,11 @@ if exist "%~1\%RsBuildConfig%\%~n1.dll" ( goto :EOF :copy_dependencies -set CopyDependenciesCopiedSomething=0 -for /F "usebackq" %%A in (`%ToolsPath%\depends.bat list %1`) do ( +for /F "usebackq" %%A in (`%ToolsPath%\depends.bat %1`) do ( if not exist "%~2\%%A" ( if exist "%RsMinGWPath%\bin\%%A" ( - set CopyDependenciesCopiedSomething=1 copy "%RsMinGWPath%\bin\%%A" %2 %Quite% ) ) ) -if "%CopyDependenciesCopiedSomething%"=="1" goto copy_dependencies goto :EOF diff --git a/build_scripts/Windows-msys2/env/env.bat b/build_scripts/Windows-msys2/env/env.bat index 810715ad2..1d2f9c2e4 100644 --- a/build_scripts/Windows-msys2/env/env.bat +++ b/build_scripts/Windows-msys2/env/env.bat @@ -7,9 +7,7 @@ set EnvToolsPath=%EnvRootPath%\tools set EnvTempPath=%EnvRootPath%\tmp set EnvDownloadPath=%EnvRootPath%\download -set EnvWgetExe=%EnvToolsPath%\wget.exe set EnvSevenZipExe=%EnvToolsPath%\7z.exe -set EnvDependsExe=%EnvToolsPath%\depends.exe set EnvCEchoExe=%EnvToolsPath%\cecho.exe set cecho=call "%ToolsPath%\cecho.bat" diff --git a/build_scripts/Windows-msys2/env/tools/prepare-tools.bat b/build_scripts/Windows-msys2/env/tools/prepare-tools.bat index d2014a7f1..c6b14a787 100644 --- a/build_scripts/Windows-msys2/env/tools/prepare-tools.bat +++ b/build_scripts/Windows-msys2/env/tools/prepare-tools.bat @@ -6,22 +6,6 @@ set CEchoUrl=https://github.com/lordmulder/cecho/releases/download/2015-10-10/ce set CEchoInstall=cecho.2015-10-10.zip set SevenZipUrl=https://sourceforge.net/projects/sevenzip/files/7-Zip/18.05/7z1805.msi/download set SevenZipInstall=7z1805.msi -set WgetUrl=https://eternallybored.org/misc/wget/1.19.4/32/wget.exe -set WgetInstall=wget.exe -set DependsUrl=http://www.dependencywalker.com/depends22_x86.zip -set DependsInstall=depends22_x86.zip -set SigcheckInstall=Sigcheck.zip -set SigcheckUrl=https://download.sysinternals.com/files/%SigcheckInstall% - -if not exist "%EnvToolsPath%\wget.exe" ( - echo Download Wget installation - - if not exist "%EnvDownloadPath%\%WgetInstall%" call "%ToolsPath%\winhttpjs.bat" %WgetUrl% -saveTo "%EnvDownloadPath%\%WgetInstall%" - if not exist "%EnvDownloadPath%\%WgetInstall%" %cecho% error "Cannot download Wget installation" & goto error - - echo Copy Wget - copy "%EnvDownloadPath%\wget.exe" "%EnvToolsPath%" -) if not exist "%EnvToolsPath%\7z.exe" ( call "%ToolsPath%\remove-dir.bat" "%EnvTempPath%" @@ -56,32 +40,6 @@ if not exist "%EnvToolsPath%\cecho.exe" ( call "%ToolsPath%\remove-dir.bat" "%EnvTempPath%" ) -if not exist "%EnvToolsPath%\depends.exe" ( - call "%ToolsPath%\remove-dir.bat" "%EnvTempPath%" - mkdir "%EnvTempPath%" - - %cecho% info "Download Dependency Walker installation" - - if not exist "%EnvDownloadPath%\%DependsInstall%" call "%ToolsPath%\winhttpjs.bat" %DependsUrl% -saveTo "%EnvDownloadPath%\%DependsInstall%" - if not exist "%EnvDownloadPath%\%DependsInstall%" %cecho% error "Cannot download Dependendy Walker installation" & goto error - - %cecho% info "Unpack Dependency Walker" - "%EnvSevenZipExe%" x -o"%EnvTempPath%" "%EnvDownloadPath%\%DependsInstall%" - copy "%EnvTempPath%\*" "%EnvToolsPath%" - - call "%ToolsPath%\remove-dir.bat" "%EnvTempPath%" -) - -if not exist "%EnvToolsPath%\sigcheck.exe" ( - %cecho% info "Download Sigcheck installation" - - if not exist "%EnvDownloadPath%\%SigcheckInstall%" call "%ToolsPath%\download-file.bat" "%SigcheckUrl%" "%EnvDownloadPath%\%SigcheckInstall%" - if not exist "%EnvDownloadPath%\%SigcheckInstall%" %cecho% error "Cannot download Sigcheck installation" & goto error - - %cecho% info "Unpack Sigcheck" - "%EnvSevenZipExe%" x -o"%EnvToolsPath%" "%EnvDownloadPath%\%SigcheckInstall%" sigcheck.exe -) - :exit endlocal exit /B 0 diff --git a/build_scripts/Windows-msys2/tools/depends.bat b/build_scripts/Windows-msys2/tools/depends.bat index a5295ccb1..a92fd3364 100644 --- a/build_scripts/Windows-msys2/tools/depends.bat +++ b/build_scripts/Windows-msys2/tools/depends.bat @@ -1,40 +1,22 @@ :: Usage: -:: call depends.bat [list^|missing] file +:: call depends.bat file -if "%2"=="" ( - echo Usage: %~nx0 [list^|missing] File +if "%1"=="" ( + echo Usage: %~nx0 File exit /B 1 ) setlocal +pushd %~dp1 -if not exist "%EnvDependsExe%" echo depends.exe not found in %EnvToolsPath%.& exit /B 1 +%EnvMSYS2Cmd% "ntldd --recursive $0 | cut -f1 -d"=" | awk '{$1=$1};1'" %~nx1 > %~sdp0depends.tmp -set CutPath= -call "%ToolsPath%\find-in-path.bat" CutPath cut.exe -if "%CutPath%"=="" echo cut.exe not found in PATH.& exit /B 1 - -start /wait "" "%EnvDependsExe%" /c /oc:"%~dp0depends.tmp" %2 -if "%1"=="missing" ( - cut.exe --delimiter=, --fields=1,2 "%~dp0depends.tmp" >"%~dp0depends1.tmp" - for /F "tokens=1,2 delims=," %%A in (%~sdp0depends1.tmp) do ( - if "%%A"=="?" ( - echo %%~B - ) - ) -) - -if "%1"=="list" ( - cut.exe --delimiter=, --fields=2 "%~dp0depends.tmp" >"%~dp0depends1.tmp" - for /F "tokens=1 delims=," %%A in (%~sdp0depends1.tmp) do ( - if "%%A" NEQ "Module" ( - echo %%~A - ) - ) +for /F %%A in (%~sdp0depends.tmp) do ( + echo %%~A ) if exist "%~dp0depends.tmp" del /Q "%~dp0depends.tmp" -if exist "%~dp0depends1.tmp" del /Q "%~dp0depends1.tmp" +popd endlocal exit /B 0 \ No newline at end of file diff --git a/build_scripts/Windows-msys2/tools/download-file.bat b/build_scripts/Windows-msys2/tools/download-file.bat index 62720c393..dbcecdcbb 100644 --- a/build_scripts/Windows-msys2/tools/download-file.bat +++ b/build_scripts/Windows-msys2/tools/download-file.bat @@ -7,7 +7,6 @@ if "%~2"=="" ( exit /B 1 ) -::"%EnvCurlExe%" -L -k "%~1" -o "%~2" -"%EnvWgetExe%" --no-check-certificate --continue "%~1" --output-document="%~2" +powershell -NoLogo -NoProfile -Command (New-Object System.Net.WebClient).DownloadFile(\""%~1\"", \""%~2\"") exit /B %ERRORLEVEL% diff --git a/build_scripts/Windows-msys2/tools/get-rs-version.bat b/build_scripts/Windows-msys2/tools/get-rs-version.bat index 2398baf93..cc4e53ff8 100644 --- a/build_scripts/Windows-msys2/tools/get-rs-version.bat +++ b/build_scripts/Windows-msys2/tools/get-rs-version.bat @@ -27,7 +27,7 @@ set VersionMinor= set VersionMini= set VersionExtra= -for /F "tokens=1,2,3,* delims=.-" %%A in ('%EnvToolsPath%\sigcheck.exe -nobanner -n %Executable%') do ( +for /F "USEBACKQ tokens=1,2,3,* delims=.-" %%A in (`powershell -NoLogo -NoProfile -Command ^(Get-Item "%Executable%"^).VersionInfo.FileVersion`) do ( set VersionMajor=%%A set VersionMinor=%%B set VersionMini=%%C diff --git a/build_scripts/Windows-msys2/tools/webui.bat b/build_scripts/Windows-msys2/tools/webui.bat new file mode 100644 index 000000000..f39da666a --- /dev/null +++ b/build_scripts/Windows-msys2/tools/webui.bat @@ -0,0 +1,20 @@ +setlocal + +echo. +echo === webui +echo. +title Build webui + +if not exist "%RsWebuiPath%" ( + echo Checking out webui source into %RsWebuiPath% + %EnvMSYS2Cmd% "pacman --noconfirm --needed -S git" + git clone https://github.com/RetroShare/RSNewWebUI.git "%RsWebuiPath%" +) else ( + echo Webui source found at %RsWebuiPath% +) + +pushd "%RsWebuiPath%\webui-src\make-src" +%EnvMSYS2Cmd% "sh build.sh" +popd + +endlocal \ No newline at end of file diff --git a/build_scripts/Windows-msys2/tools/winhttpjs.bat b/build_scripts/Windows-msys2/tools/winhttpjs.bat deleted file mode 100644 index cdea152eb..000000000 --- a/build_scripts/Windows-msys2/tools/winhttpjs.bat +++ /dev/null @@ -1,584 +0,0 @@ -@if (@X) == (@Y) @end /* JScript comment - @echo off - - rem :: the first argument is the script name as it will be used for proper help message - cscript //E:JScript //nologo "%~f0" "%~nx0" %* - - exit /b %errorlevel% - -@if (@X)==(@Y) @end JScript comment */ - -// used resources - -// update 12.10.15 -// osvikvi(https://github.com/osvikvi) has nodited that the -password option is not set , so this is fixed - -//https://msdn.microsoft.com/en-us/library/windows/desktop/aa384058(v=vs.85).aspx -//https://msdn.microsoft.com/en-us/library/windows/desktop/aa384055(v=vs.85).aspx -//https://msdn.microsoft.com/en-us/library/windows/desktop/aa384059(v=vs.85).aspx - -// global variables and constants - - -// ---------------------------------- -// -- asynch requests not included -- -// ---------------------------------- - - -//todo - save responceStream instead of responceBody !! -//todo - set all winthttp options ->//https://msdn.microsoft.com/en-us/library/windows/desktop/aa384108(v=vs.85).aspx -//todo - log all options -//todo - improve help message . eventual verbose option - - -var ARGS = WScript.Arguments; -var scriptName = ARGS.Item(0); - -var url = ""; -var saveTo = ""; - -var user = 0; -var pass = 0; - -var proxy = 0; -var bypass = 0; -var proxy_user = 0; -var proxy_pass = 0; - -var certificate = 0; - -var force = true; - -var body = ""; - -//ActiveX objects -var WinHTTPObj = new ActiveXObject("WinHttp.WinHttpRequest.5.1"); -var FileSystemObj = new ActiveXObject("Scripting.FileSystemObject"); -var AdoDBObj = new ActiveXObject("ADODB.Stream"); - -// HttpRequest SetCredentials flags. -var proxy_settings = 0; - -// -HTTPREQUEST_SETCREDENTIALS_FOR_SERVER = 0; -HTTPREQUEST_SETCREDENTIALS_FOR_PROXY = 1; - -//timeouts and their default values -var RESOLVE_TIMEOUT = 0; -var CONNECT_TIMEOUT = 90000; -var SEND_TIMEOUT = 90000; -var RECEIVE_TIMEOUT = 90000; - -//HttpRequestMethod -var http_method = 'GET'; - -//header -var header_file = ""; - -//report -var reportfile = ""; - -//test-this: -var use_stream = false; - -//autologon policy -var autologon_policy = 1; //0,1,2 - - -//headers will be stored as multi-dimensional array -var headers = []; - -//user-agent -var ua = ""; - -//escape URL -var escape = false; - -function printHelp() { - WScript.Echo(scriptName + " - sends HTTP request and saves the request body as a file and/or a report of the sent request"); - WScript.Echo(scriptName + " url [-force yes|no] [-user username -password password] [-proxy proxyserver:port] [-bypass bypass_list]"); - WScript.Echo(" [-proxyuser proxy_username -proxypassword proxy_password] [-certificate certificateString]"); - WScript.Echo(" [-method GET|POST|PATCH|DELETE|HEAD|OPTIONS|CONNECT]"); - WScript.Echo(" [-saveTo file] - to print response to console use con"); - - WScript.Echo(" [-sendTimeout int(milliseconds)]"); - WScript.Echo(" [-resolveTimeout int(milliseconds)]"); - WScript.Echo(" [-connectTimeout int(milliseconds)]"); - WScript.Echo(" [-receiveTimeout int(milliseconds)]"); - - WScript.Echo(" [-autologonPolicy 1|2|3]"); - WScript.Echo(" [-proxySettings 1|2|3] (https://msdn.microsoft.com/en-us/library/windows/desktop/aa384059(v=vs.85).aspx)"); - - //header - WScript.Echo(" [-headers-file header_file]"); - //reportfile - WScript.Echo(" [-reportfile reportfile]"); - WScript.Echo(" [-ua user-agent]"); - WScript.Echo(" [-ua-file user-agent-file]"); - - WScript.Echo(" [-escape yes|no]"); - - WScript.Echo(" [-body body-string]"); - WScript.Echo(" [-body-file body-file]"); - - WScript.Echo("-force - decide to not or to overwrite if the local files exists"); - - WScript.Echo("proxyserver:port - the proxy server"); - WScript.Echo("bypass- bypass list"); - WScript.Echo("proxy_user , proxy_password - credentials for proxy server"); - WScript.Echo("user , password - credentials for the server"); - WScript.Echo("certificate - location of SSL certificate"); - WScript.Echo("method - what HTTP method will be used.Default is GET"); - WScript.Echo("saveTo - save the responce as binary file"); - WScript.Echo(" "); - WScript.Echo("Header file should contain key:value pairs.Lines starting with \"#\" will be ignored."); - WScript.Echo("value should NOT be enclosed with quotes"); - WScript.Echo(" "); - WScript.Echo("Examples:"); - - WScript.Echo(scriptName + " http://somelink.com/somefile.zip -saveTo c:\\somefile.zip -certificate \"LOCAL_MACHINE\\Personal\\My Middle-Tier Certificate\""); - WScript.Echo(scriptName + " http://somelink.com/something.html -method POST -certificate \"LOCAL_MACHINE\\Personal\\My Middle-Tier Certificate\" -header c:\\header_file -reportfile c:\\reportfile.txt"); - WScript.Echo(scriptName + "\"http://somelink\" -method POST -header hdrs.txt -reportfile reportfile2.txt -saveTo responsefile2 -ua \"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36\" -body-file some.json"); - -} - -function parseArgs() { - // - if (ARGS.Length < 2) { - WScript.Echo("insufficient arguments"); - printHelp(); - WScript.Quit(43); - } - // !!! - url = ARGS.Item(1); - // !!! - if (ARGS.Length % 2 != 0) { - WScript.Echo("illegal arguments"); - printHelp(); - WScript.Quit(44); - } - - for (var i = 2; i < ARGS.Length - 1; i = i + 2) { - var arg = ARGS.Item(i).toLowerCase(); - var next = ARGS.Item(i + 1); - - - try { - switch (arg) { // the try-catch is set mainly because of the parseInts - case "-force": - if (next == "no") { - force = false; - } - break; - case "-escape": - if (next == "yes") { - escape = true; - } - break; - case "-saveto": - saveTo = next; - break; - case "-user": - case "-u": - user = next; - break; - case "-pass": - case "-password": - case "-p": - pass = next; - break; - case "-proxy": - proxy = next; - break; - case "-bypass": - bypass = next; - break; - case "-proxyuser": - case "-pu": - proxy_user = next; - break; - case "-proxypassword": - case "-pp": - proxy_pass = next; - break; - case "-ua": - ua = next; - break; - case "-ua-file": - ua = readFile(next); - break; - case "-body": - body = next; - break; - case "-usestream": - //WScript.Echo("~~"); - if (next.toLowerCase() === "yes") { - use_stream = true - }; - break; - case "-body-file": - body = readFile(next); - break; - case "-certificate": - certificate = next; - break; - case "-method": - switch (next.toLowerCase()) { - case "post": - http_method = 'POST'; - break; - case "get": - http_method = 'GET'; - break; - case "head": - http_method = 'HEAD'; - break; - case "put": - http_method = 'PUT'; - break; - case "options": - http_method = 'OPTIONS'; - break; - case "connect": - http_method = 'CONNECT'; - break; - case "patch": - http_method = 'PATCH'; - break; - case "delete": - http_method = 'DELETE'; - break; - default: - WScript.Echo("Invalid http method passed " + next); - WScript.Echo("possible values are GET,POST,DELETE,PUT,CONNECT,PATCH,HEAD,OPTIONS"); - WScript.Quit(1326); - break; - } - break; - case "-headers-file": - case "-header": - headers = readPropFile(next); - break; - case "-reportfile": - reportfile = next; - break; - //timeouts - case "-sendtimeout": - SEND_TIMEOUT = parseInt(next); - break; - case "-connecttimeout": - CONNECT_TIMEOUT = parseint(next); - break; - case "-resolvetimeout": - RESOLVE_TIMEOUT = parseInt(next); - break; - case "-receivetimeout": - RECEIVE_TIMEOUT = parseInt(next); - break; - - case "-autologonpolicy": - autologon_policy = parseInt(next); - if (autologon_policy > 2 || autologon_policy < 0) { - WScript.Echo("out of autologon policy range"); - WScript.Quit(87); - }; - break; - case "-proxysettings": - proxy_settings = parseInt(next); - if (proxy_settings > 2 || proxy_settings < 0) { - WScript.Echo("out of proxy settings range"); - WScript.Quit(87); - }; - break; - default: - WScript.Echo("Invalid command line switch: " + arg); - WScript.Quit(1405); - break; - } - } catch (err) { - WScript.Echo(err.message); - WScript.Quit(1348); - } - } -} - -stripTrailingSlash = function(path) { - while (path.substr(path.length - 1, path.length) == '\\') { - path = path.substr(0, path.length - 1); - } - return path; -} - -function existsItem(path) { - return FileSystemObj.FolderExists(path) || FileSystemObj.FileExists(path); -} - -function deleteItem(path) { - if (FileSystemObj.FileExists(path)) { - FileSystemObj.DeleteFile(path); - return true; - } else if (FileSystemObj.FolderExists(path)) { - FileSystemObj.DeleteFolder(stripTrailingSlash(path)); - return true; - } else { - return false; - } -} - -//------------------------------- -//---------------------- -//---------- -//----- -//-- -function request(url) { - - try { - - WinHTTPObj.Open(http_method, url, false); - if (proxy != 0 && bypass != 0) { - WinHTTPObj.SetProxy(proxy_settings, proxy, bypass); - } - - if (proxy != 0) { - WinHTTPObj.SetProxy(proxy_settings, proxy); - } - - if (user != 0 && pass != 0) { - WinHTTPObj.SetCredentials(user, pass, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER); - } - - if (proxy_user != 0 && proxy_pass != 0) { - WinHTTPObj.SetCredentials(proxy_user, proxy_pass, HTTPREQUEST_SETCREDENTIALS_FOR_PROXY); - } - - if (certificate != 0) { - WinHTTPObj.SetClientCertificate(certificate); - } - - //set autologin policy - WinHTTPObj.SetAutoLogonPolicy(autologon_policy); - //set timeouts - WinHTTPObj.SetTimeouts(RESOLVE_TIMEOUT, CONNECT_TIMEOUT, SEND_TIMEOUT, RECEIVE_TIMEOUT); - - if (headers.length !== 0) { - WScript.Echo("Sending with headers:"); - for (var i = 0; i < headers.length; i++) { - WinHTTPObj.SetRequestHeader(headers[i][0], headers[i][1]); - WScript.Echo(headers[i][0] + ":" + headers[i][1]); - } - WScript.Echo(""); - } - - if (ua !== "") { - //user-agent option from: - //WinHttpRequestOption enumeration - // other options can be added like bellow - //https://msdn.microsoft.com/en-us/library/windows/desktop/aa384108(v=vs.85).aspx - WinHTTPObj.Option(0) = ua; - } - if (escape) { - WinHTTPObj.Option(3) = true; - } - if (trim(body) === "") { - WinHTTPObj.Send(); - } else { - WinHTTPObj.Send(body); - } - - var status = WinHTTPObj.Status - } catch (err) { - WScript.Echo(err.message); - WScript.Quit(666); - } - - //////////////////////// - // report // - //////////////////////// - - if (reportfile != "") { - - //var report_string=""; - var n = "\r\n"; - var report_string = "Status:" + n; - report_string = report_string + " " + WinHTTPObj.Status; - report_string = report_string + " " + WinHTTPObj.StatusText + n; - report_string = report_string + " " + n; - report_string = report_string + "Response:" + n; - report_string = report_string + WinHTTPObj.ResponseText + n; - report_string = report_string + " " + n; - report_string = report_string + "Headers:" + n; - report_string = report_string + WinHTTPObj.GetAllResponseHeaders() + n; - - WinHttpRequestOption_UserAgentString = 0; // Name of the user agent - WinHttpRequestOption_URL = 1; // Current URL - WinHttpRequestOption_URLCodePage = 2; // Code page - WinHttpRequestOption_EscapePercentInURL = 3; // Convert percents - // in the URL - // rest of the options can be seen and eventually added using this as reference - // https://msdn.microsoft.com/en-us/library/windows/desktop/aa384108(v=vs.85).aspx - - report_string = report_string + "URL:" + n; - report_string = report_string + WinHTTPObj.Option(WinHttpRequestOption_URL) + n; - - report_string = report_string + "URL Code Page:" + n; - report_string = report_string + WinHTTPObj.Option(WinHttpRequestOption_URLCodePage) + n; - - report_string = report_string + "User Agent:" + n; - report_string = report_string + WinHTTPObj.Option(WinHttpRequestOption_UserAgentString) + n; - - report_string = report_string + "Escapped URL:" + n; - report_string = report_string + WinHTTPObj.Option(WinHttpRequestOption_EscapePercentInURL) + n; - - prepareateFile(force, reportfile); - - WScript.Echo("Writing report to " + reportfile); - - writeFile(reportfile, report_string); - - } - - switch (status) { - case 200: - WScript.Echo("Status: 200 OK"); - break; - default: - WScript.Echo("Status: " + status); - WScript.Echo("Status was not OK. More info -> https://en.wikipedia.org/wiki/List_of_HTTP_status_codes"); - } - - //if as binary - if (saveTo.toLowerCase() === "con") { - WScript.Echo(WinHTTPObj.ResponseText); - } - if (saveTo !== "" && saveTo.toLowerCase() !== "con") { - prepareateFile(force, saveTo); - try { - - if (use_stream) { - writeBinFile(saveTo, WinHTTPObj.ResponseStream); - } else { - writeBinFile(saveTo, WinHTTPObj.ResponseBody); - } - - } catch (err) { - WScript.Echo("Failed to save the file as binary.Attempt to save it as text"); - AdoDBObj.Close(); - prepareateFile(true, saveTo); - writeFile(saveTo, WinHTTPObj.ResponseText); - } - } - WScript.Quit(status); -} - -//-- -//----- -//---------- -//---------------------- -//------------------------------- - -function prepareateFile(force, file) { - if (force && existsItem(file)) { - if (!deleteItem(file)) { - WScript.Echo("Unable to delete " + file); - WScript.Quit(8); - } - } else if (existsItem(file)) { - WScript.Echo("Item " + file + " already exist"); - WScript.Quit(9); - } -} - -function writeBinFile(fileName, data) { - AdoDBObj.Type = 1; - AdoDBObj.Open(); - AdoDBObj.Position = 0; - AdoDBObj.Write(data); - AdoDBObj.SaveToFile(fileName, 2); - AdoDBObj.Close(); -} - -function writeFile(fileName, data) { - AdoDBObj.Type = 2; - AdoDBObj.CharSet = "iso-8859-1"; - AdoDBObj.Open(); - AdoDBObj.Position = 0; - AdoDBObj.WriteText(data); - AdoDBObj.SaveToFile(fileName, 2); - AdoDBObj.Close(); -} - - -function readFile(fileName) { - //check existence - try { - if (!FileSystemObj.FileExists(fileName)) { - WScript.Echo("file " + fileName + " does not exist!"); - WScript.Quit(13); - } - if (FileSystemObj.GetFile(fileName).Size === 0) { - return ""; - } - var fileR = FileSystemObj.OpenTextFile(fileName, 1); - var content = fileR.ReadAll(); - fileR.Close(); - return content; - } catch (err) { - WScript.Echo("Error while reading file: " + fileName); - WScript.Echo(err.message); - WScript.Echo("Will return empty string"); - return ""; - } -} - -function readPropFile(fileName) { - //check existence - resultArray = []; - if (!FileSystemObj.FileExists(fileName)) { - WScript.Echo("(headers)file " + fileName + " does not exist!"); - WScript.Quit(15); - } - if (FileSystemObj.GetFile(fileName).Size === 0) { - return resultArray; - } - var fileR = FileSystemObj.OpenTextFile(fileName, 1); - var line = ""; - var k = ""; - var v = ""; - var lineN = 0; - var index = 0; - try { - WScript.Echo("parsing headers form " + fileName + " property file "); - while (!fileR.AtEndOfStream) { - line = fileR.ReadLine(); - lineN++; - index = line.indexOf(":"); - if (line.indexOf("#") === 0 || trim(line) === "") { - continue; - } - if (index === -1 || index === line.length - 1 || index === 0) { - WScript.Echo("Invalid line " + lineN); - WScript.Quit(93); - } - k = trim(line.substring(0, index)); - v = trim(line.substring(index + 1, line.length)); - resultArray.push([k, v]); - } - fileR.Close(); - return resultArray; - } catch (err) { - WScript.Echo("Error while reading headers file: " + fileName); - WScript.Echo(err.message); - WScript.Echo("Will return empty array"); - return resultArray; - } -} - -function trim(str) { - return str.replace(/^\s+/, '').replace(/\s+$/, ''); -} - -function main() { - parseArgs(); - request(url); -} -main(); diff --git a/libretroshare/src/file_sharing/p3filelists.cc b/libretroshare/src/file_sharing/p3filelists.cc index c7db78b0f..55a28dec6 100644 --- a/libretroshare/src/file_sharing/p3filelists.cc +++ b/libretroshare/src/file_sharing/p3filelists.cc @@ -1424,9 +1424,15 @@ int p3FileDatabase::SearchBoolExp(RsRegularExpression::Expression *exp, std::lis return !results.empty() ; } -bool p3FileDatabase::search(const RsFileHash &hash, FileSearchFlags hintflags, FileInfo &info) const + +bool p3FileDatabase::search( + const RsFileHash &hash, FileSearchFlags hintflags, FileInfo &info) const { - RS_STACK_MUTEX(mFLSMtx) ; + RS_STACK_MUTEX(mFLSMtx); + + if( (hintflags & RS_FILE_HINTS_EXTRA) && + mExtraFiles->search(hash, hintflags, info) ) + return true; if(hintflags & RS_FILE_HINTS_LOCAL) { diff --git a/libretroshare/src/ft/ftextralist.cc b/libretroshare/src/ft/ftextralist.cc index ccefe810d..a4a1245e0 100644 --- a/libretroshare/src/ft/ftextralist.cc +++ b/libretroshare/src/ft/ftextralist.cc @@ -4,7 +4,7 @@ * libretroshare: retroshare core library * * * * Copyright (C) 2008 Robert Fernie * - * Copyright (C) 2018-2019 Gioacchino Mazzurco * + * Copyright (C) 2018-2020 Gioacchino Mazzurco * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * @@ -21,6 +21,9 @@ * * *******************************************************************************/ +#include +#include + #ifdef WINDOWS_SYS #include "util/rswin.h" #endif @@ -245,12 +248,8 @@ bool ftExtraList::cleanupOldFiles() /* remove items */ for(std::list::iterator rit = toRemove.begin(); rit != toRemove.end(); ++rit) { - if (mFiles.end() != (it = mFiles.find(*rit))) - { - cleanupEntry(it->second.info.path, it->second.info.transfer_info_flags); - mFiles.erase(it); - } - mHashOfHash.erase(makeEncryptedHash(*rit)) ; + if (mFiles.end() != (it = mFiles.find(*rit))) mFiles.erase(it); + mHashOfHash.erase(makeEncryptedHash(*rit)); } IndicateConfigChanged(); @@ -258,46 +257,39 @@ bool ftExtraList::cleanupOldFiles() return true; } - -bool ftExtraList::cleanupEntry(std::string /*path*/, TransferRequestFlags /*flags*/) -{ -// if (flags & RS_FILE_CONFIG_CLEANUP_DELETE) -// { -// /* Delete the file? - not yet! */ -// } - return true; -} - - /*** - * Hash file, and add to the files, - * file is removed after period. - **/ - bool ftExtraList::hashExtraFile( std::string path, uint32_t period, TransferRequestFlags flags ) { -#ifdef DEBUG_ELIST - std::cerr << "ftExtraList::hashExtraFile() path: " << path; - std::cerr << " period: " << period; - std::cerr << " flags: " << flags; + constexpr rstime_t max_int = std::numeric_limits::max(); + const rstime_t now = time(nullptr); + const rstime_t timeOut = now + period; - std::cerr << std::endl; -#endif - - auto failure = [](std::string errMsg) + if(timeOut > max_int) { - RsErr() << __PRETTY_FUNCTION__ << " " << errMsg << std::endl; + /* Under the hood period is stored as int FileInfo::age so we do this + * check here to detect 2038 year problem + * https://en.wikipedia.org/wiki/Year_2038_problem */ + RsErr() << __PRETTY_FUNCTION__ << " period: " << period << " > " + << max_int - now << std::errc::value_too_large << std::endl; return false; - }; + } if(!RsDirUtil::fileExists(path)) - return failure("file: " + path + "not found"); + { + RsErr() << __PRETTY_FUNCTION__ << " path: " << path + << std::errc::no_such_file_or_directory << std::endl; + return false; + } if(RsDirUtil::checkDirectory(path)) - return failure("Cannot add a directory: " + path + "as extra file"); + { + RsErr() << __PRETTY_FUNCTION__ << " path: " << path + << std::errc::is_a_directory << std::endl; + return false; + } FileDetails details(path, period, flags); - details.info.age = static_cast(time(nullptr) + period); + details.info.age = static_cast(timeOut); { RS_STACK_MUTEX(extMutex); @@ -492,8 +484,7 @@ bool ftExtraList::loadList(std::list& load) if (ts > (rstime_t)fi->file.age) { - /* to old */ - cleanupEntry(fi->file.path, TransferRequestFlags(fi->flags)); + /* too old */ delete (*it); continue ; } diff --git a/libretroshare/src/ft/ftextralist.h b/libretroshare/src/ft/ftextralist.h index 52bc87c98..229c0fe3c 100644 --- a/libretroshare/src/ft/ftextralist.h +++ b/libretroshare/src/ft/ftextralist.h @@ -60,7 +60,7 @@ #include "pqi/p3cfgmgr.h" #include "util/rstime.h" -class FileDetails +class RS_DEPRECATED_FOR(FileInfo) FileDetails { public: FileDetails() @@ -130,7 +130,11 @@ public: * file is removed after period. **/ - bool hashExtraFile(std::string path, uint32_t period, TransferRequestFlags flags); + /** + * Hash file, and add to the files, file is removed after period. + */ + bool hashExtraFile( + std::string path, uint32_t period, TransferRequestFlags flags ); bool hashExtraFileDone(std::string path, FileInfo &info); /*** @@ -165,7 +169,6 @@ private: /* Worker Functions */ void hashAFile(); bool cleanupOldFiles(); - bool cleanupEntry(std::string path, TransferRequestFlags flags); mutable RsMutex extMutex; diff --git a/libretroshare/src/ft/ftserver.cc b/libretroshare/src/ft/ftserver.cc index 3ae1af491..0f42b8437 100644 --- a/libretroshare/src/ft/ftserver.cc +++ b/libretroshare/src/ft/ftserver.cc @@ -22,6 +22,8 @@ #include #include +#include +#include #include "crypto/chacha20.h" //const int ftserverzone = 29539; @@ -293,7 +295,8 @@ bool ftServer::getFileData(const RsFileHash& hash, uint64_t offset, uint32_t& re bool ftServer::alreadyHaveFile(const RsFileHash& hash, FileInfo &info) { - return mFileDatabase->search(hash, RS_FILE_HINTS_LOCAL, info); + return mFileDatabase->search( + hash, RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_LOCAL, info ); } bool ftServer::FileRequest( @@ -819,6 +822,14 @@ bool ftServer::ExtraFileRemove(const RsFileHash& hash) bool ftServer::ExtraFileHash( std::string localpath, rstime_t period, TransferRequestFlags flags ) { + constexpr rstime_t uintmax = std::numeric_limits::max(); + if(period > uintmax) + { + RsErr() << __PRETTY_FUNCTION__ << " period: " << period << " > " + << uintmax << std::errc::value_too_large << std::endl; + return false; + } + return mFtExtra->hashExtraFile( localpath, static_cast(period), flags ); } diff --git a/libretroshare/src/libretroshare.pro b/libretroshare/src/libretroshare.pro index c7b38ce0b..3f9dde680 100644 --- a/libretroshare/src/libretroshare.pro +++ b/libretroshare/src/libretroshare.pro @@ -870,7 +870,7 @@ rs_jsonapi { genrestbedheader.name = Generating restbed header. genrestbedheader.input = genrestbedlib.output genrestbedheader.output = $${RESTBED_HEADER_FILE} - genrestbedheader.CONFIG += target_predeps combine no_link + genrestbedheader.CONFIG += target_predeps no_link genrestbedheader.variable_out = HEADERS genrestbedheader.commands = cd $${RESTBED_BUILD_PATH} && $(MAKE) install QMAKE_EXTRA_COMPILERS += genrestbedheader diff --git a/libretroshare/src/retroshare/rsfiles.h b/libretroshare/src/retroshare/rsfiles.h index 64563f621..92c017cef 100644 --- a/libretroshare/src/retroshare/rsfiles.h +++ b/libretroshare/src/retroshare/rsfiles.h @@ -658,7 +658,8 @@ public: * @brief Get file details * @jsonapi{development} * @param[in] hash file identifier - * @param[in] hintflags filtering hint (RS_FILE_HINTS_EXTRA|...|RS_FILE_HINTS_LOCAL) + * @param[in] hintflags filtering hint ( RS_FILE_HINTS_UPLOAD|...| + * RS_FILE_HINTS_EXTRA|RS_FILE_HINTS_LOCAL ) * @param[out] info storage for file information * @return true if file found, false otherwise */ diff --git a/libretroshare/src/retroshare/rsgxschannels.h b/libretroshare/src/retroshare/rsgxschannels.h index bef322a4a..4b188ad01 100644 --- a/libretroshare/src/retroshare/rsgxschannels.h +++ b/libretroshare/src/retroshare/rsgxschannels.h @@ -310,6 +310,7 @@ public: * @param[in] channelId id of the channel of which the content is requested * @param[out] posts storage for posts * @param[out] comments storage for the comments + * @param[out] votes storage for votes * @return false if something failed, true otherwhise */ virtual bool getChannelAllContent( const RsGxsGroupId& channelId, diff --git a/libretroshare/src/serialiser/rstypeserializer.cc b/libretroshare/src/serialiser/rstypeserializer.cc index 1ea3add9a..7cf799d0f 100644 --- a/libretroshare/src/serialiser/rstypeserializer.cc +++ b/libretroshare/src/serialiser/rstypeserializer.cc @@ -503,8 +503,16 @@ bool RsTypeSerializer::from_JSON( const std::string& /*memberName*/, // Binary blocks // //============================================================================// +#if __cplusplus < 201703L +/* Solve weird undefined reference error with C++ < 17 see: + * https://stackoverflow.com/questions/8016780/undefined-reference-to-static-constexpr-char + */ +/*static*/ decltype(RsTypeSerializer::RawMemoryWrapper::base64_key) constexpr +RsTypeSerializer::RawMemoryWrapper::base64_key; + /*static*/ /* without this Android compilation breaks */ constexpr uint32_t RsTypeSerializer::RawMemoryWrapper::MAX_SERIALIZED_CHUNK_SIZE; +#endif /*static*/ void RsTypeSerializer::RawMemoryWrapper::serial_process( @@ -542,18 +550,7 @@ void RsTypeSerializer::RawMemoryWrapper::serial_process( ctx.mOffset += second; break; case RsGenericSerializer::DESERIALIZE: - if(first || second) - { - /* Items are created anew before deserialization so buffer pointer - * must be null and size 0 at this point */ - - RsWarn() << __PRETTY_FUNCTION__ << " DESERIALIZE got uninitialized " - << " or pre-allocated buffer! Buffer pointer: " << first - << " must be null and size: " << second << " must be 0 at " - << "this point. Does your item costructor initialize them " - << "properly?" << std::endl; - print_stacktrace(); - } + freshMemCheck(); RS_SERIAL_PROCESS(second); if(!ctx.mOk) break; @@ -597,44 +594,33 @@ void RsTypeSerializer::RawMemoryWrapper::serial_process( if(!ctx.mOk) break; std::string encodedValue; RsBase64::encode(first, second, encodedValue, true, false); - ctx.mJson.SetString( - encodedValue.data(), - static_cast(encodedValue.length()), - ctx.mJson.GetAllocator()); + ctx.mOk = ctx.mOk && + RsTypeSerializer::to_JSON(base64_key, encodedValue, ctx.mJson); break; } case RsGenericSerializer::FROM_JSON: { - const bool yelding = !!( - RsSerializationFlags::YIELDING & ctx.mFlags ); - if(!(ctx.mOk || yelding)) - { - clear(); - break; - } - if(!ctx.mJson.IsString()) - { - RsErr() << __PRETTY_FUNCTION__ << " " - << std::errc::invalid_argument << std::endl; - print_stacktrace(); + freshMemCheck(); - ctx.mOk = false; - clear(); - break; - } - if( ctx.mJson.GetStringLength() > + const auto failure = [&]() -> void { ctx.mOk = false; clear(); }; + const bool yielding = !!( + RsSerializationFlags::YIELDING & ctx.mFlags ); + if(!(ctx.mOk || yielding)) return failure(); + + std::string encodedValue; + if(!RsTypeSerializer::from_JSON( + base64_key, encodedValue, ctx.mJson )) return failure(); + + if( encodedValue.length() > RsBase64::encodedSize(MAX_SERIALIZED_CHUNK_SIZE, true) ) { RsErr() << __PRETTY_FUNCTION__ << " " << std::errc::message_size << std::endl; print_stacktrace(); - ctx.mOk = false; - clear(); - break; + return failure(); } - std::string encodedValue = ctx.mJson.GetString(); std::vector decoded; auto ec = RsBase64::decode(encodedValue, decoded); if(ec) @@ -642,9 +628,7 @@ void RsTypeSerializer::RawMemoryWrapper::serial_process( RsErr() << __PRETTY_FUNCTION__ << " " << ec << std::endl; print_stacktrace(); - ctx.mOk = false; - clear(); - break; + return failure(); } const auto decodedSize = decoded.size(); @@ -655,11 +639,8 @@ void RsTypeSerializer::RawMemoryWrapper::serial_process( break; } - if(decodedSize != second) - { - first = reinterpret_cast(realloc(first, decodedSize)); - second = static_cast(decodedSize); - } + first = reinterpret_cast(malloc(decodedSize)); + second = static_cast(decodedSize); memcpy(first, decoded.data(), second); break; @@ -675,6 +656,24 @@ void RsTypeSerializer::RawMemoryWrapper::clear() second = 0; } +bool RsTypeSerializer::RawMemoryWrapper::freshMemCheck() +{ + if(first || second) + { + /* Items are created anew before deserialization so buffer pointer + * must be null and size 0 at this point */ + + RsWarn() << __PRETTY_FUNCTION__ << " got uninitialized " + << " or pre-allocated buffer! Buffer pointer: " << first + << " must be null and size: " << second << " must be 0 at " + << "this point. Does your item costructor initialize them " + << "properly?" << std::endl; + print_stacktrace(); + return false; + } + return true; +} + //============================================================================// // std::error_condition // //============================================================================// diff --git a/libretroshare/src/serialiser/rstypeserializer.h b/libretroshare/src/serialiser/rstypeserializer.h index d72280bb3..3c8af510e 100644 --- a/libretroshare/src/serialiser/rstypeserializer.h +++ b/libretroshare/src/serialiser/rstypeserializer.h @@ -59,12 +59,17 @@ struct RsTypeSerializer /// Maximum supported size 10MB static constexpr uint32_t MAX_SERIALIZED_CHUNK_SIZE = 10*1024*1024; + /** Key used for JSON serialization. + * @note Changing this value breaks JSON API retro-compatibility */ + static constexpr char base64_key[] = "base64"; + /// @see RsSerializable void serial_process( RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext& ctx ) override; private: void clear(); + bool freshMemCheck(); }; /// Most types are not valid sequence containers @@ -777,9 +782,9 @@ struct RsTypeSerializer { if(!yielding) { - std::cerr << __PRETTY_FUNCTION__ << " \"" << memberName - << "\" not found in JSON:" << std::endl - << jDoc << std::endl << std::endl; + RsErr() << __PRETTY_FUNCTION__ << " \"" << memberName + << "\" not found in JSON:" << std::endl + << jDoc << std::endl << std::endl; print_stacktrace(); } ctx.mOk = false; @@ -790,9 +795,9 @@ struct RsTypeSerializer if(!v.IsObject()) { - std::cerr << __PRETTY_FUNCTION__ << " \"" << memberName - << "\" has wrong type in JSON, object expected, got:" - << std::endl << jDoc << std::endl << std::endl; + RsErr() << __PRETTY_FUNCTION__ << " \"" << memberName + << "\" has wrong type in JSON, object expected, got:" + << std::endl << jDoc << std::endl << std::endl; print_stacktrace(); ctx.mOk = false; break; diff --git a/libretroshare/src/services/p3msgservice.cc b/libretroshare/src/services/p3msgservice.cc index 01a825bb3..83c1c8e88 100644 --- a/libretroshare/src/services/p3msgservice.cc +++ b/libretroshare/src/services/p3msgservice.cc @@ -1187,11 +1187,15 @@ bool p3MsgService::MessageSend(MessageInfo &info) /* use processMsg to get the new msgId */ msg->recvTime = time(NULL); msg->msgId = getNewUniqueMsgId(); - + msg->msgFlags |= RS_MSG_OUTGOING; imsg[msg->msgId] = msg; + // Update info for caller + info.msgId = std::to_string(msg->msgId); + info .msgflags = msg->msgFlags; + RsServer::notify()->notifyListChange(NOTIFY_LIST_MESSAGELIST,NOTIFY_TYPE_ADD); } diff --git a/libretroshare/src/services/p3photoservice.cc b/libretroshare/src/services/p3photoservice.cc index 014c0d319..1547e5a7d 100644 --- a/libretroshare/src/services/p3photoservice.cc +++ b/libretroshare/src/services/p3photoservice.cc @@ -117,11 +117,7 @@ void p3PhotoService::groupsChanged(std::list& grpIds) while(!mGroupChange.empty()) { RsGxsGroupChange* gc = mGroupChange.back(); - std::list& gList = gc->mGrpIdList; - std::list::iterator lit = gList.begin(); - for(; lit != gList.end(); ++lit) { - grpIds.push_back(*lit); - } + grpIds.push_back(gc->mGroupId); mGroupChange.pop_back(); delete gc; @@ -136,7 +132,8 @@ void p3PhotoService::msgsChanged(GxsMsgIdResult& msgs) while(!mMsgChange.empty()) { RsGxsMsgChange* mc = mMsgChange.back(); - msgs = mc->msgChangeMap; + + msgs[mc->mGroupId].insert(mc->mMsgId); mMsgChange.pop_back(); delete mc; } diff --git a/libretroshare/src/util/rsbase64.cc b/libretroshare/src/util/rsbase64.cc index 6b856888e..f62c40cef 100644 --- a/libretroshare/src/util/rsbase64.cc +++ b/libretroshare/src/util/rsbase64.cc @@ -21,8 +21,6 @@ * * *******************************************************************************/ -#include - #include "util/rsbase64.h" #include "util/rsdebug.h" @@ -40,6 +38,12 @@ rs_view_ptr data, size_t len, std::string& outString, bool padding, bool urlSafe ) { + if(!data || !len) + { + outString.clear(); + return; + } + const char* sDict = urlSafe ? uDict : bDict; // Workaround if input and output are the same buffer. @@ -137,9 +141,11 @@ /*static*/ size_t RsBase64::encodedSize(size_t decodedSize, bool padding) { - if(padding) return 4 * (decodedSize + 2) / 3; - return static_cast( - std::ceil(4L * static_cast(decodedSize) / 3L) ); + if(!decodedSize) return 0; + + // Thanks https://stackoverflow.com/a/45401395 + if(padding) return ceilDivision(decodedSize, 3) * 4; + return ceilDivision(decodedSize * 8, 6); } /*static*/ std::tuple RsBase64::decodedSize( diff --git a/libretroshare/src/util/rsbase64.h b/libretroshare/src/util/rsbase64.h index 0715b15ae..819870089 100644 --- a/libretroshare/src/util/rsbase64.h +++ b/libretroshare/src/util/rsbase64.h @@ -137,4 +137,8 @@ private: */ static inline bool isBase64Char(char c) { return rDict[static_cast(c)] >= 0; } + + /** Perform ceil division without floating point operations */ + static inline size_t ceilDivision(size_t dividend, size_t divisor) + { return (dividend + divisor - 1) / divisor; } }; diff --git a/libretroshare/src/util/rsdebug.h b/libretroshare/src/util/rsdebug.h index c333bd255..73d5a2132 100644 --- a/libretroshare/src/util/rsdebug.h +++ b/libretroshare/src/util/rsdebug.h @@ -32,6 +32,8 @@ std::ostream &operator<<(std::ostream& out, const std::error_condition& err); # include # include +# include "util/rsjson.h" + enum class RsLoggerCategories { DEBUG = ANDROID_LOG_DEBUG, @@ -46,6 +48,18 @@ struct t_RsLogger { inline t_RsLogger() = default; + /** Offer variadic style too, as a benefit this has better atomicity then + * << style, but doesn't supports manipulators and things like std::endl + * @see https://stackoverflow.com/a/27375675 */ + template + inline t_RsLogger(Arg&& arg, Args&&... args) + { + ostr << std::forward(arg); + using expander = int[]; + (void)expander{0, (void(ostr << std::forward(args)), 0)...}; + mFlush(); + } + /** On other platforms expose the type of underlying stream. * On Android it cannot work like that so return the class type itself * just for code compatibility with other platforms */ @@ -55,17 +69,16 @@ struct t_RsLogger inline stream_type& operator<<(const T& val) { ostr << val; return *this; } + template + inline stream_type& operator<<(const RsJson& val) + { ostr << val; return *this; } + /// needed for manipulators and things like std::endl stream_type& operator<<(std::ostream& (*pf)(std::ostream&)) { if(pf == static_cast( &std::endl< char, std::char_traits > )) - { - __android_log_write( - static_cast(CATEGORY), - "RetroShare", ostr.str().c_str() ); - ostr.str() = ""; - } + mFlush(); else ostr << pf; return *this; @@ -78,6 +91,14 @@ struct t_RsLogger private: std::ostringstream ostr; + + void mFlush() + { + __android_log_write( + static_cast(CATEGORY), + "RetroShare", ostr.str().c_str() ); + ostr.str() = ""; + } }; #else // def __ANDROID__ @@ -99,38 +120,56 @@ enum class RsLoggerCategories template struct t_RsLogger { - inline t_RsLogger() = default; - /// Expose the type of underlying stream using stream_type = decltype(std::cerr); + /// Return underlying stream to write avoiding additional prefixes + static inline stream_type& uStream() { return std::cerr; } + + inline t_RsLogger() = default; + + /** Offer variadic style too, as a benefit this has better atomicity then + * << style, but doesn't supports manipulators and things like std::endl + * @see https://stackoverflow.com/a/27375675 */ + template + inline t_RsLogger(Arg&& arg, Args&&... args) + { + std::ostringstream ostr; + ostr << getPrefix() << std::forward(arg); + using expander = int[]; + (void)expander{0, (void(ostr << std::forward(args)), 0)...}; + ostr << std::endl; + uStream() << ostr.str(); + } + template inline stream_type& operator<<(const T& val) + { return uStream() << getPrefix() << val; } + + /// needed for manipulators and things like std::endl + stream_type& operator<<(std::ostream& (*pf)(std::ostream&)) + { return uStream() << pf; } + +private: + std::string getPrefix() { using namespace std::chrono; const auto now = system_clock::now(); const auto sec = time_point_cast(now); const auto msec = duration_cast(now - sec); - std::stringstream tstream; + std::ostringstream tstream; tstream << static_cast(CATEGORY) << " " << sec.time_since_epoch().count() << "." << std::setfill('0') << std::setw(3) << msec.count() - << " " << val; - return std::cerr << tstream.str(); + << " "; + return tstream.str(); } - - /// needed for manipulators and things like std::endl - stream_type& operator<<(std::ostream& (*pf)(std::ostream&)) - { return std::cerr << pf; } - - /// Return underlying stream to write avoiding additional prefixes - inline stream_type& uStream() const { return std::cerr; } }; #endif // def __ANDROID__ /** - * Comfortable debug message loggin, supports chaining like std::cerr but can + * Comfortable debug message logging, supports chaining like std::cerr but can * be easly and selectively disabled at compile time to reduce generated binary * size and performance impact without too many \#ifdef around. * @@ -190,6 +229,8 @@ struct RsNoDbg { inline RsNoDbg() = default; + template inline RsNoDbg(T, Args...) {} + /** Defined as the type itself just for code compatibility with other * logging classes */ using stream_type = RsNoDbg; diff --git a/libretroshare/src/util/rsjson.h b/libretroshare/src/util/rsjson.h index db864a73f..13073f3b2 100644 --- a/libretroshare/src/util/rsjson.h +++ b/libretroshare/src/util/rsjson.h @@ -29,7 +29,7 @@ typedef rapidjson::Document RsJson; /** - * Print out RsJson to a stream, use std::stringstream to get the string + * Print out RsJson to a stream, use std::ostringstream to get the string * @param[out] out output stream * @param[in] jDoc JSON document to print * @return same output stream passed as out parameter diff --git a/retroshare-gui/src/gui/chat/ChatWidget.cpp b/retroshare-gui/src/gui/chat/ChatWidget.cpp index 2cf0e1edf..6c36a392b 100644 --- a/retroshare-gui/src/gui/chat/ChatWidget.cpp +++ b/retroshare-gui/src/gui/chat/ChatWidget.cpp @@ -115,6 +115,7 @@ ChatWidget::ChatWidget(QWidget *parent) //ui->sendButton->setFixedHeight(iconHeight); ui->sendButton->setIconSize(iconSize); ui->typingLabel->setMaximumHeight(QFontMetricsF(font()).height()*1.2); + ui->fontcolorButton->setIconSize(iconSize); //Initialize search iCharToStartSearch=Settings->getChatSearchCharToStartSearch(); @@ -189,7 +190,7 @@ ChatWidget::ChatWidget(QWidget *parent) ui->hashBox->setDropWidget(this); ui->hashBox->setAutoHide(true); - QMenu *fontmenu = new QMenu(tr("Set text font & color")); + QMenu *fontmenu = new QMenu(); fontmenu->addAction(ui->actionChooseFont); fontmenu->addAction(ui->actionChooseColor); fontmenu->addAction(ui->actionResetFont); @@ -198,10 +199,10 @@ ChatWidget::ChatWidget(QWidget *parent) #ifdef USE_CMARK fontmenu->addAction(ui->actionSend_as_CommonMark); #endif + ui->fontcolorButton->setMenu(fontmenu); QMenu *menu = new QMenu(); menu->addAction(ui->actionMessageHistory); - menu->addMenu(fontmenu); menu->addSeparator(); menu->addAction(ui->actionSaveChatHistory); menu->addAction(ui->actionClearChatHistory); diff --git a/retroshare-gui/src/gui/chat/ChatWidget.ui b/retroshare-gui/src/gui/chat/ChatWidget.ui index 4a191f80c..f4d070c11 100644 --- a/retroshare-gui/src/gui/chat/ChatWidget.ui +++ b/retroshare-gui/src/gui/chat/ChatWidget.ui @@ -455,13 +455,13 @@ border-image: url(:/images/closepressed.png) - - - Qt::NoFocus + + + Set font & color - :/icons/png/chat-bubble-notify.png:/icons/png/chat-bubble-notify.png + :/icons/png/font.png:/icons/png/font.png @@ -469,6 +469,9 @@ border-image: url(:/images/closepressed.png) 28 + + QToolButton::InstantPopup + true @@ -769,6 +772,26 @@ border-image: url(:/images/closepressed.png) + + + + Qt::NoFocus + + + + :/icons/png/chat-bubble-notify.png:/icons/png/chat-bubble-notify.png + + + + 28 + 28 + + + + true + + + diff --git a/retroshare-gui/src/gui/common/RSElidedItemDelegate.cpp b/retroshare-gui/src/gui/common/RSElidedItemDelegate.cpp index 89a2ebe8a..3fa95f898 100644 --- a/retroshare-gui/src/gui/common/RSElidedItemDelegate.cpp +++ b/retroshare-gui/src/gui/common/RSElidedItemDelegate.cpp @@ -39,19 +39,19 @@ //#define DEBUG_EID_PAINT 1 /* To test it you can make an empty.qss file with: -QTreeView::item, QTreeWidget::item{ +QTreeView::item, QTreeWidget::item, QListWidget::item{ color: #AB0000; background-color: #00DC00; } -QTreeView::item:selected, QTreeWidget::item:selected{ +QTreeView::item:selected, QTreeWidget::item:selected, QListWidget::item:selected{ color: #00CD00; background-color: #0000BA; } -QTreeView::item:hover, QTreeWidget::item:hover{ +QTreeView::item:hover, QTreeWidget::item:hover, QListWidget::item:hover{ color: #0000EF; background-color: #FEDCBA; } -QQTreeView::item:selected:hover, TreeWidget::item:selected:hover{ +QQTreeView::item:selected:hover, TreeWidget::item:selected:hover, QListWidget::item:selected:hover{ color: #ABCDEF; background-color: #FE0000; } diff --git a/retroshare-gui/src/gui/elastic/elnode.h b/retroshare-gui/src/gui/elastic/elnode.h index 1e0edd1a8..33043ddab 100644 --- a/retroshare-gui/src/gui/elastic/elnode.h +++ b/retroshare-gui/src/gui/elastic/elnode.h @@ -23,6 +23,10 @@ #ifndef ELNODE_H #define ELNODE_H +#include "graphwidget.h" + +#include + #include #if QT_VERSION >= 0x040600 #include @@ -30,9 +34,7 @@ #include #endif #include - -#include -#include "graphwidget.h" +#include class Edge; QT_BEGIN_NAMESPACE diff --git a/retroshare-gui/src/gui/emojione.qrc b/retroshare-gui/src/gui/emojione.qrc index fdbfc58aa..b636f7b09 100644 --- a/retroshare-gui/src/gui/emojione.qrc +++ b/retroshare-gui/src/gui/emojione.qrc @@ -937,5 +937,7 @@ emojione/1F1FF-1F1FC.png emojione/flags.png emojione/flags2.png + emojione/man-facepalming.png + emojione/woman-facepalming.png diff --git a/retroshare-gui/src/gui/emojione/emotes.acs b/retroshare-gui/src/gui/emojione/emotes.acs index 6e9007948..26af35787 100644 --- a/retroshare-gui/src/gui/emojione/emotes.acs +++ b/retroshare-gui/src/gui/emojione/emotes.acs @@ -113,6 +113,8 @@ "emojione/people2.png"|":man_with_gua_pi_mao:":"emojione/1F472.png"; "emojione/people2.png"|":levitate:|:man_in_business_suit_levitating:":"emojione/1F574.png"; "emojione/people2.png"|":dancer:":"emojione/1F483.png"; +"emojione/people2.png"|":man_facepalming:":"emojione/man-facepalming.png"; +"emojione/people2.png"|":woman_facepalming:":"emojione/woman-facepalming.png"; "emojione/people2.png"|":bust_in_silhouette:":"emojione/1F464.png"; "emojione/people2.png"|":busts_in_silhouette:":"emojione/1F465.png"; "emojione/people2.png"|":family:":"emojione/1F46A.png"; diff --git a/retroshare-gui/src/gui/emojione/man-facepalming.png b/retroshare-gui/src/gui/emojione/man-facepalming.png new file mode 100644 index 000000000..d0594eefd Binary files /dev/null and b/retroshare-gui/src/gui/emojione/man-facepalming.png differ diff --git a/retroshare-gui/src/gui/emojione/woman-facepalming.png b/retroshare-gui/src/gui/emojione/woman-facepalming.png new file mode 100644 index 000000000..10346185e Binary files /dev/null and b/retroshare-gui/src/gui/emojione/woman-facepalming.png differ diff --git a/retroshare-gui/src/gui/feeds/GxsChannelPostItem.cpp b/retroshare-gui/src/gui/feeds/GxsChannelPostItem.cpp index 25b93ac8d..aa35fc0cc 100644 --- a/retroshare-gui/src/gui/feeds/GxsChannelPostItem.cpp +++ b/retroshare-gui/src/gui/feeds/GxsChannelPostItem.cpp @@ -141,7 +141,7 @@ GxsChannelPostItem::~GxsChannelPostItem() bool GxsChannelPostItem::isUnread() const { - return IS_MSG_UNREAD(mPost.mMeta.mMsgStatus) ; + return IS_MSG_UNREAD(mPost.mMeta.mMsgStatus) ; } void GxsChannelPostItem::setup() @@ -427,7 +427,7 @@ void GxsChannelPostItem::fill() QString title; - float f = QFontMetricsF(font()).height()/14.0 ; + //float f = QFontMetricsF(font()).height()/14.0 ; if(mPost.mThumbnail.mData != NULL) { @@ -629,14 +629,21 @@ QString GxsChannelPostItem::messageName() void GxsChannelPostItem::setReadStatus(bool isNew, bool isUnread) { + if (isNew) + mPost.mMeta.mMsgStatus |= GXS_SERV::GXS_MSG_STATUS_GUI_NEW; + else + mPost.mMeta.mMsgStatus &= ~GXS_SERV::GXS_MSG_STATUS_GUI_NEW; + if (isUnread) { - ui->readButton->setChecked(true); + mPost.mMeta.mMsgStatus |= GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD; + whileBlocking(ui->readButton)->setChecked(true); ui->readButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/message-state-unread.png")); } else { - ui->readButton->setChecked(false); + mPost.mMeta.mMsgStatus &= ~GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD; + whileBlocking(ui->readButton)->setChecked(false); ui->readButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/message-state-read.png")); } @@ -835,7 +842,7 @@ void GxsChannelPostItem::play() } } -void GxsChannelPostItem::readToggled(bool checked) +void GxsChannelPostItem::readToggled(bool /*checked*/) { if (mInFill) { return; @@ -845,10 +852,9 @@ void GxsChannelPostItem::readToggled(bool checked) RsGxsGrpMsgIdPair msgPair = std::make_pair(groupId(), messageId()); - uint32_t token; - rsGxsChannels->setMessageReadStatus(token, msgPair, !checked); + rsGxsChannels->markRead(msgPair, isUnread()); - setReadStatus(false, checked); + //setReadStatus(false, checked); // Updated by events } void GxsChannelPostItem::makeDownVote() diff --git a/retroshare-gui/src/gui/feeds/GxsChannelPostItem.h b/retroshare-gui/src/gui/feeds/GxsChannelPostItem.h index 86aa20371..315972bb1 100644 --- a/retroshare-gui/src/gui/feeds/GxsChannelPostItem.h +++ b/retroshare-gui/src/gui/feeds/GxsChannelPostItem.h @@ -62,10 +62,13 @@ public: QString getMsgLabel(); const std::list &getFileItems() {return mFileItems; } - bool isUnread() const ; - const std::set& olderVersions() const { return mPost.mOlderVersions; } + bool isLoaded() const {return mLoaded;}; + bool isUnread() const ; + void setReadStatus(bool isNew, bool isUnread); - static uint64_t computeIdentifier(const RsGxsMessageId& msgid) { return hash64("GxsChannelPostItem " + msgid.toStdString()) ; } + const std::set& olderVersions() const { return mPost.mOlderVersions; } + + static uint64_t computeIdentifier(const RsGxsMessageId& msgid) { return hash64("GxsChannelPostItem " + msgid.toStdString()) ; } protected: //void init(const RsGxsMessageId& messageId,const std::set& older_versions); @@ -112,7 +115,6 @@ private: void setup(); void fill(); void fillExpandFrame(); - void setReadStatus(bool isNew, bool isUnread); private: bool mInFill; diff --git a/retroshare-gui/src/gui/feeds/GxsCircleItem.cpp b/retroshare-gui/src/gui/feeds/GxsCircleItem.cpp index 8c355de35..18997a084 100644 --- a/retroshare-gui/src/gui/feeds/GxsCircleItem.cpp +++ b/retroshare-gui/src/gui/feeds/GxsCircleItem.cpp @@ -129,7 +129,7 @@ void GxsCircleItem::setup() { if(circleDetails.mAmIAdmin) { - ui->titleLabel->setText(idName + tr(" which you invited, has join this circle you're administrating.")); + ui->titleLabel->setText(idName + tr(" which you invited, has joined this circle you're administrating.")); ui->inviteeButton->setHidden(false); ui->inviteeButton->setText(tr("Revoke membership")); ui->inviteeButton->setToolTip(tr("Revoke membership for that identity")); @@ -137,7 +137,7 @@ void GxsCircleItem::setup() else { ui->inviteeButton->setHidden(true); - ui->titleLabel->setText(idName + tr(" has join this circle.")); + ui->titleLabel->setText(idName + tr(" has joined this circle.")); } ui->iconLabel->setPixmap(pixmap); diff --git a/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.cpp b/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.cpp index 14413963f..a1f824e9a 100644 --- a/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.cpp +++ b/retroshare-gui/src/gui/gxs/GxsCommentTreeWidget.cpp @@ -18,6 +18,14 @@ * * *******************************************************************************/ +#include "GxsCommentTreeWidget.h" + +#include "gui/common/FilesDefs.h" +#include "gui/common/RSElidedItemDelegate.h" +#include "gui/common/RSTreeWidgetItem.h" +#include "gui/gxs/GxsCreateCommentDialog.h" +#include "gui/gxs/GxsIdTreeWidgetItem.h" + #include #include #include @@ -25,15 +33,9 @@ #include #include #include +#include #include -#include "gui/common/RSElidedItemDelegate.h" -#include "gui/common/FilesDefs.h" -#include "gui/gxs/GxsCommentTreeWidget.h" -#include "gui/gxs/GxsCreateCommentDialog.h" -#include "gui/gxs/GxsIdTreeWidgetItem.h" -#include "gui/common/RSTreeWidgetItem.h" - #include #define PCITEM_COLUMN_COMMENT 0 diff --git a/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp b/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp index 22469575f..701a9153d 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp +++ b/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp @@ -18,21 +18,23 @@ * * *******************************************************************************/ -#include -#include -#include -#include - -#include -#include -#include "gui/common/AvatarDialog.h" #include "GxsIdDetails.h" + +#include "gui/common/AvatarDialog.h" #include "retroshare-gui/RsAutoUpdatePage.h" #include +#include + +#include +#include +#include +#include +#include +#include #include -#include +#include /* Images for tag icons */ #define IMAGE_LOADING ":/images/folder-draft.png" diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidget.cpp b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidget.cpp index 48b620775..d4e6192e2 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidget.cpp +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidget.cpp @@ -144,18 +144,24 @@ void GxsChannelPostsWidget::handleEvent_main_thread(std::shared_ptrmChannelEventCode) - { - case RsChannelEventCode::UPDATED_CHANNEL: - case RsChannelEventCode::NEW_CHANNEL: - case RsChannelEventCode::UPDATED_MESSAGE: - case RsChannelEventCode::NEW_MESSAGE: - if(e->mChannelGroupId == groupId()) + switch(e->mChannelEventCode) + { + case RsChannelEventCode::NEW_CHANNEL: // [[fallthrough]]; + case RsChannelEventCode::UPDATED_CHANNEL: // [[fallthrough]]; + case RsChannelEventCode::NEW_MESSAGE: // [[fallthrough]]; + case RsChannelEventCode::UPDATED_MESSAGE: + if(e->mChannelGroupId == groupId()) updateDisplay(true); - break; - default: - break; - } + break; + case RsChannelEventCode::READ_STATUS_CHANGED: + if (FeedItem *feedItem = ui->feedWidget->findFeedItem(GxsChannelPostItem::computeIdentifier(e->mChannelMsgId))) + if (GxsChannelPostItem *channelPostItem = dynamic_cast(feedItem)) + channelPostItem->setReadStatus(false,!channelPostItem->isUnread()); + //channelPostItem->setReadStatus(false,e->Don't get read status. Will be more easier and accurate); + break; + default: + break; + } } GxsChannelPostsWidget::~GxsChannelPostsWidget() @@ -909,9 +915,9 @@ static void setAllMessagesReadCallback(FeedItem *feedItem, void *data) } GxsChannelPostsReadData *readData = (GxsChannelPostsReadData*) data; - bool is_not_new = !channelPostItem->isUnread() ; + bool isRead = !channelPostItem->isUnread() ; - if(is_not_new == readData->mRead) + if(channelPostItem->isLoaded() && (isRead == readData->mRead)) return ; RsGxsGrpMsgIdPair msgPair = std::make_pair(channelPostItem->groupId(), channelPostItem->messageId()); diff --git a/retroshare-gui/src/gui/icons.qrc b/retroshare-gui/src/gui/icons.qrc index 311530b03..6e4bd7569 100644 --- a/retroshare-gui/src/gui/icons.qrc +++ b/retroshare-gui/src/gui/icons.qrc @@ -301,6 +301,7 @@ icons/png/arrow-left.png icons/png/next-unread.png icons/mail/compose.png + icons/mail/downloadall.png icons/mail/delete.png icons/mail/tags.png icons/mail/quote.png diff --git a/retroshare-gui/src/gui/icons/mail/downloadall.png b/retroshare-gui/src/gui/icons/mail/downloadall.png new file mode 100644 index 000000000..b4d31d3d0 Binary files /dev/null and b/retroshare-gui/src/gui/icons/mail/downloadall.png differ diff --git a/retroshare-gui/src/gui/icons/png/font.png b/retroshare-gui/src/gui/icons/png/font.png index 3c71acc5f..f9b3dd48c 100644 Binary files a/retroshare-gui/src/gui/icons/png/font.png and b/retroshare-gui/src/gui/icons/png/font.png differ diff --git a/retroshare-gui/src/gui/msgs/MessageComposer.cpp b/retroshare-gui/src/gui/msgs/MessageComposer.cpp index 6d33e6ca6..92f4de457 100644 --- a/retroshare-gui/src/gui/msgs/MessageComposer.cpp +++ b/retroshare-gui/src/gui/msgs/MessageComposer.cpp @@ -1206,6 +1206,12 @@ MessageComposer *MessageComposer::replyMsg(const std::string &msgId, bool all) // needed to send system flags with reply msgComposer->msgFlags = (msgInfo.msgflags & RS_MSG_SYSTEM); + MsgTagInfo tagInfo; + rsMail->getMessageTag(msgId, tagInfo); + + msgComposer->m_tagIds = tagInfo.tagIds; + msgComposer->showTagLabels(); + msgComposer->calculateTitle(); /* window will destroy itself! */ diff --git a/retroshare-gui/src/gui/msgs/MessageWidget.cpp b/retroshare-gui/src/gui/msgs/MessageWidget.cpp index 3c085c3c8..086986230 100644 --- a/retroshare-gui/src/gui/msgs/MessageWidget.cpp +++ b/retroshare-gui/src/gui/msgs/MessageWidget.cpp @@ -36,6 +36,7 @@ #include "gui/common/TagDefs.h" #include "gui/common/PeerDefs.h" #include "gui/common/Emoticons.h" +#include "gui/common/FilesDefs.h" #include "gui/settings/rsharesettings.h" #include "MessageComposer.h" #include "MessageWidget.h" @@ -51,8 +52,8 @@ #include /* Images for context menu icons */ -#define IMAGE_DOWNLOAD ":/images/start.png" -#define IMAGE_DOWNLOADALL ":/images/startall.png" +#define IMAGE_DOWNLOAD ":/icons/png/download.png" +#define IMAGE_DOWNLOADALL ":/icons/mail/downloadall.png" #define COLUMN_FILE_NAME 0 #define COLUMN_FILE_SIZE 1 @@ -555,6 +556,7 @@ void MessageWidget::fill(const std::string &msgId) for (it = recList.begin(); it != recList.end(); ++it) { QTreeWidgetItem *item = new QTreeWidgetItem; item->setText(COLUMN_FILE_NAME, QString::fromUtf8(it->fname.c_str())); + item->setIcon(COLUMN_FILE_NAME, FilesDefs::getIconFromFileType(it->fname.c_str())); item->setText(COLUMN_FILE_SIZE, misc::friendlyUnit(it->size)); item->setData(COLUMN_FILE_SIZE, Qt::UserRole, QVariant(qulonglong(it->size)) ); item->setText(COLUMN_FILE_HASH, QString::fromStdString(it->hash.toStdString())); @@ -667,10 +669,14 @@ void MessageWidget::fill(const std::string &msgId) } ui.subjectText->setText(QString::fromUtf8(msgInfo.title.c_str())); + + unsigned int formatTextFlag = RSHTML_FORMATTEXT_EMBED_LINKS ; - // emoticons disabled because of crazy cost. - //text = RsHtmlMsg(msgInfo.msgflags).formatText(ui.msgText->document(), QString::fromUtf8(msgInfo.msg.c_str()), RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS); - text = RsHtmlMsg(msgInfo.msgflags).formatText(ui.msgText->document(), QString::fromUtf8(msgInfo.msg.c_str()), RSHTML_FORMATTEXT_EMBED_LINKS); + // embed smileys ? + if (Settings->valueFromGroup(QString("Messages"), QString::fromUtf8("Emoticons"), true).toBool()) { + formatTextFlag |= RSHTML_FORMATTEXT_EMBED_SMILEYS ; + } + text = RsHtmlMsg(msgInfo.msgflags).formatText(ui.msgText->document(), QString::fromUtf8(msgInfo.msg.c_str()), formatTextFlag); ui.msgText->resetImagesStatus(Settings->getMsgLoadEmbeddedImages() || (msgInfo.msgflags & RS_MSG_LOAD_EMBEDDED_IMAGES)); ui.msgText->setHtml(text); diff --git a/retroshare-gui/src/gui/msgs/MessagesDialog.cpp b/retroshare-gui/src/gui/msgs/MessagesDialog.cpp index 37a6ee319..40b61739a 100644 --- a/retroshare-gui/src/gui/msgs/MessagesDialog.cpp +++ b/retroshare-gui/src/gui/msgs/MessagesDialog.cpp @@ -53,6 +53,7 @@ #include /* Images for context menu icons */ +#define IMAGE_MAIL ":/icons/png/message.png" #define IMAGE_MESSAGE ":/icons/mail/compose.png" #define IMAGE_MESSAGEREMOVE ":/icons/mail/delete.png" #define IMAGE_STAR_ON ":/images/star-on-16.png" @@ -766,7 +767,7 @@ void MessagesDialog::openAsTab() return; } - ui.tabWidget->addTab(msgWidget, msgWidget->subject(true)); + ui.tabWidget->addTab(msgWidget,QIcon(IMAGE_MAIL), msgWidget->subject(true)); ui.tabWidget->setCurrentWidget(msgWidget); connect(msgWidget, SIGNAL(messageRemoved()), this, SLOT(messageRemoved())); @@ -1104,7 +1105,10 @@ void MessagesDialog::removemessage() void MessagesDialog::messageRemoved() { - ui.messageTreeWidget->setCurrentIndex(lastSelectedIndex); + if (lastSelectedIndex.isValid()) + ui.messageTreeWidget->setCurrentIndex(lastSelectedIndex); + else + insertMsgTxtAndFiles(QModelIndex()); } void MessagesDialog::undeletemessage() diff --git a/retroshare-gui/src/gui/qss/stylesheet/Standard.qss b/retroshare-gui/src/gui/qss/stylesheet/Standard.qss index 19c6eece1..00569eef2 100644 --- a/retroshare-gui/src/gui/qss/stylesheet/Standard.qss +++ b/retroshare-gui/src/gui/qss/stylesheet/Standard.qss @@ -904,6 +904,16 @@ MessagesDialog QWidget#messageTreeWidget::item { padding: 2px; } +MessagesDialog QWidget#messageTreeWidget::item:selected { + background-color: #cde8ff; + color: black; +} + +MessagesDialog QWidget#messageTreeWidget::item:hover { + background-color: #e5f3ff; + color: black; +} + GxsForumThreadWidget QWidget#threadTreeWidget::item { padding: 2px; } diff --git a/retroshare-gui/src/gui/settings/MessagePage.cpp b/retroshare-gui/src/gui/settings/MessagePage.cpp index eb0eabccc..91a24ab02 100644 --- a/retroshare-gui/src/gui/settings/MessagePage.cpp +++ b/retroshare-gui/src/gui/settings/MessagePage.cpp @@ -39,7 +39,6 @@ MessagePage::MessagePage(QWidget * parent, Qt::WindowFlags flags) connect (ui.editpushButton, SIGNAL(clicked(bool)), this, SLOT (editTag())); connect (ui.deletepushButton, SIGNAL(clicked(bool)), this, SLOT (deleteTag())); connect (ui.defaultTagButton, SIGNAL(clicked(bool)), this, SLOT (defaultTag())); - //connect (ui.encryptedMsgs_CB, SIGNAL(toggled(bool)), this, SLOT (toggleEnableEncryptedDistantMsgs(bool))); connect (ui.tags_listWidget, SIGNAL(currentRowChanged(int)), this, SLOT(currentRowChangedTag(int))); @@ -54,6 +53,7 @@ MessagePage::MessagePage(QWidget * parent, Qt::WindowFlags flags) connect(ui.setMsgToReadOnActivate,SIGNAL(toggled(bool)), this,SLOT(updateMsgToReadOnActivate())); connect(ui.loadEmbeddedImages, SIGNAL(toggled(bool)), this,SLOT(updateLoadEmbededImages() )); connect(ui.openComboBox, SIGNAL(currentIndexChanged(int)),this,SLOT(updateMsgOpen() )); + connect(ui.emoticonscheckBox, SIGNAL(toggled(bool)), this,SLOT(updateLoadEmoticons() )); } MessagePage::~MessagePage() @@ -84,6 +84,7 @@ void MessagePage::updateMsgToReadOnActivate() { Settings->setMsgSetToReadOnActiv void MessagePage::updateLoadEmbededImages() { Settings->setMsgLoadEmbeddedImages(ui.loadEmbeddedImages->isChecked()); } void MessagePage::updateMsgOpen() { Settings->setMsgOpen( static_cast(ui.openComboBox->itemData(ui.openComboBox->currentIndex()).toInt()) ); } void MessagePage::updateDistantMsgs() { Settings->setValue("DistantMessages", ui.comboBox->currentIndex()); } +void MessagePage::updateLoadEmoticons() { Settings->setValueToGroup("Messages", "Emoticons", ui.emoticonscheckBox->isChecked()); } void MessagePage::updateMsgTags() { @@ -110,9 +111,12 @@ void MessagePage::updateMsgTags() void MessagePage::load() { + Settings->beginGroup(QString("Messages")); whileBlocking(ui.setMsgToReadOnActivate)->setChecked(Settings->getMsgSetToReadOnActivate()); whileBlocking(ui.loadEmbeddedImages)->setChecked(Settings->getMsgLoadEmbeddedImages()); whileBlocking(ui.openComboBox)->setCurrentIndex(ui.openComboBox->findData(Settings->getMsgOpen())); + whileBlocking(ui.emoticonscheckBox)->setChecked(Settings->value("Emoticons", true).toBool()); + Settings->endGroup(); // state of filter combobox @@ -267,3 +271,4 @@ void MessagePage::currentRowChangedTag(int row) ui.editpushButton->setEnabled(bEditEnable); ui.deletepushButton->setEnabled(bDeleteEnable); } + diff --git a/retroshare-gui/src/gui/settings/MessagePage.h b/retroshare-gui/src/gui/settings/MessagePage.h index b4c2e9c67..6dd6f87df 100644 --- a/retroshare-gui/src/gui/settings/MessagePage.h +++ b/retroshare-gui/src/gui/settings/MessagePage.h @@ -58,6 +58,7 @@ private slots: void updateMsgOpen() ; void updateDistantMsgs() ; void updateMsgTags() ; + void updateLoadEmoticons(); private: void fillTags(); diff --git a/retroshare-gui/src/gui/settings/MessagePage.ui b/retroshare-gui/src/gui/settings/MessagePage.ui index 57d801bed..58da48b9f 100644 --- a/retroshare-gui/src/gui/settings/MessagePage.ui +++ b/retroshare-gui/src/gui/settings/MessagePage.ui @@ -65,14 +65,7 @@ - - - - Load embedded images - - - - + @@ -86,6 +79,20 @@ + + + + Load embedded images + + + + + + + Load Emoticons + + + diff --git a/retroshare-gui/src/gui/settings/rsharesettings.cpp b/retroshare-gui/src/gui/settings/rsharesettings.cpp index 2d4a33c7b..ea0bbcb69 100644 --- a/retroshare-gui/src/gui/settings/rsharesettings.cpp +++ b/retroshare-gui/src/gui/settings/rsharesettings.cpp @@ -1157,7 +1157,7 @@ void RshareSettings::setWebinterfaceEnabled(bool enabled) QString RshareSettings::getWebinterfaceFilesDirectory() { #ifdef WINDOWS_SYS - return valueFromGroup("Webinterface","directory","data/webui/").toString(); + return valueFromGroup("Webinterface","directory","./webui/").toString(); #else return valueFromGroup("Webinterface","directory","/usr/share/retroshare/webui/").toString(); #endif diff --git a/retroshare-gui/src/qss/blacknight.qss b/retroshare-gui/src/qss/blacknight.qss index 3f08e0aa8..62adfe013 100644 --- a/retroshare-gui/src/qss/blacknight.qss +++ b/retroshare-gui/src/qss/blacknight.qss @@ -51,6 +51,10 @@ background: black; color: lightgray; border-color: transparent; } +QTreeView::item, QTreeWidget::item, QListWidget::item{ + color: lightgray; +} + QDialog, QMainWindow{ background-color: qlineargradient(spread:reflect, x1:0, y1:0, x2:0, y2:1, stop:0 rgb(25, 25, 25), stop:0.05 rgb(0, 0, 0), stop:0.95 rgb(0, 0, 0), stop:1 rgb(25, 25, 25)); } @@ -255,6 +259,12 @@ QTextEdit { color: white; } +RSTextBrowser, MimeTextEdit +{ + /*qproperty-textColorQuote: rgb(125, 125, 255);*/ + qproperty-textColorQuotes: ColorList(#789922 #039bd5 #800000 #800080 #008080 #b10dc9 #85144b #3d9970); +} + /* OpModeStatus need to be at end to overload other values*/ OpModeStatus { qproperty-opMode_Full_Color: #007000; diff --git a/retroshare-gui/src/qss/qdarkstyle-v2.qss b/retroshare-gui/src/qss/qdarkstyle-v2.qss index 97a331ac9..cb573d765 100644 --- a/retroshare-gui/src/qss/qdarkstyle-v2.qss +++ b/retroshare-gui/src/qss/qdarkstyle-v2.qss @@ -51,6 +51,9 @@ QWidget { selection-background-color: #1464A0; selection-color: #F0F0F0; } +QTreeView::item, QTreeWidget::item, QListWidget::item{ + color: #F0F0F0; +} QWidget:disabled { background-color: #19232D; @@ -2152,5 +2155,5 @@ GxsChannelDialog GroupTreeWidget QTreeWidget#treeWidget::item{ RSTextBrowser, MimeTextEdit { /*qproperty-textColorQuote: rgb(125, 125, 255);*/ - qproperty-textColorQuotes: ColorList(#0000ff #00ff00 #00ffff #ff0000 #ff00ff #ffff00 #ffffff); + qproperty-textColorQuotes: ColorList(#789922 #039bd5 #800000 #800080 #008080 #b10dc9 #85144b #3d9970); } diff --git a/retroshare-gui/src/qss/qdarkstyle.qss b/retroshare-gui/src/qss/qdarkstyle.qss index 059c87f9d..b50eb9aa1 100644 --- a/retroshare-gui/src/qss/qdarkstyle.qss +++ b/retroshare-gui/src/qss/qdarkstyle.qss @@ -60,6 +60,9 @@ QWidget border-image: none; outline: 0; } +QTreeView::item, QTreeWidget::item, QListWidget::item{ + color: silver; +} QWidget:item:hover { @@ -1299,7 +1302,7 @@ WireGroupItem QFrame#frame{ RSTextBrowser, MimeTextEdit { /*qproperty-textColorQuote: rgb(125, 125, 255);*/ - qproperty-textColorQuotes: ColorList(#0000ff #00ff00 #00ffff #ff0000 #ff00ff #ffff00 #ffffff); + qproperty-textColorQuotes: ColorList(#789922 #039bd5 #800000 #800080 #008080 #b10dc9 #85144b #3d9970); } ChatWidget QFrame#pluginTitleFrame diff --git a/retroshare-gui/src/util/HandleRichText.cpp b/retroshare-gui/src/util/HandleRichText.cpp index d8870eb50..466e540de 100644 --- a/retroshare-gui/src/util/HandleRichText.cpp +++ b/retroshare-gui/src/util/HandleRichText.cpp @@ -31,6 +31,8 @@ #include "gui/RetroShareLink.h" #include "util/ObjectPainter.h" #include "util/imageutil.h" + +#include "util/rsdebug.h" #include "util/rstime.h" #ifdef USE_CMARK @@ -40,6 +42,8 @@ #include +//#define DEBUG_SAVESPACE 1 + /** * The type of embedding we'd like to do */ @@ -554,18 +558,24 @@ static QString saveSpace(const QString text) if(cursChar==QLatin1Char('>')) { if(!echapChar && i>0) {outBrackets=true; firstOutBracket=true;} } else if(cursChar==QLatin1Char('\t')) { - if(outBrackets && firstOutBracket && (keyName!="style")) savedSpaceText.replace(i, 1, "  "); + if(outBrackets && firstOutBracket && (keyName!="style")) { savedSpaceText.replace(i, 1, "  "); i+= 11; } } else if(cursChar==QLatin1Char(' ')) { - if(outBrackets && firstOutBracket && (keyName!="style")) savedSpaceText.replace(i, 1, " "); + if(outBrackets && firstOutBracket && (keyName!="style")) { savedSpaceText.replace(i, 1, " "); i+= 5; } } else if(cursChar==QChar(0xA0)) { - if(outBrackets && firstOutBracket && (keyName!="style")) savedSpaceText.replace(i, 1, " "); + if(outBrackets && firstOutBracket && (keyName!="style")) { savedSpaceText.replace(i, 1, " "); i+= 5; } } else if(cursChar==QLatin1Char('<')) { if(!echapChar) {outBrackets=false; getKeyName=true; keyName.clear();} } else firstOutBracket=false; echapChar=(cursChar==QLatin1Char('\\')); } - +#ifdef DEBUG_SAVESPACE + RsDbg() << __PRETTY_FUNCTION__ << "Text to save:" << std::endl + << text.toStdString() << std::endl + << "---------------------- Saved Text:" << std::endl + << savedSpaceText.toStdString() << std::endl; +#endif + return savedSpaceText; }