mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-06-21 21:04:32 -04:00
merged upstream/master
This commit is contained in:
commit
6419b03a2a
131 changed files with 6081 additions and 1473 deletions
|
@ -22,7 +22,7 @@ before_install:
|
||||||
- if [ $TRAVIS_OS_NAME == osx ]; then brew install ccach; export PATH="/usr/local/opt/ccache/libexec:$PATH" ; fi
|
- if [ $TRAVIS_OS_NAME == osx ]; then brew install ccach; export PATH="/usr/local/opt/ccache/libexec:$PATH" ; fi
|
||||||
- if [ $TRAVIS_OS_NAME == osx ]; then brew install qt5; fi
|
- if [ $TRAVIS_OS_NAME == osx ]; then brew install qt5; fi
|
||||||
- if [ $TRAVIS_OS_NAME == osx ]; then brew link --force qt5 ; fi
|
- if [ $TRAVIS_OS_NAME == osx ]; then brew link --force qt5 ; fi
|
||||||
- if [ $TRAVIS_OS_NAME == osx ]; then brew install openssl miniupnpc libmicrohttpd sqlcipher xapian; fi
|
- if [ $TRAVIS_OS_NAME == osx ]; then brew install openssl miniupnpc libmicrohttpd sqlcipher xapian cmark; fi
|
||||||
- if [ $TRAVIS_OS_NAME == osx ]; then brew install p7zip; fi
|
- if [ $TRAVIS_OS_NAME == osx ]; then brew install p7zip; fi
|
||||||
- if [ $TRAVIS_OS_NAME == osx ]; then npm install -g appdmg; fi
|
- if [ $TRAVIS_OS_NAME == osx ]; then npm install -g appdmg; fi
|
||||||
|
|
||||||
|
|
16
appveyor.yml
16
appveyor.yml
|
@ -90,7 +90,7 @@ install:
|
||||||
# Configuring MSys2
|
# Configuring MSys2
|
||||||
- set PATH=C:\msys64\usr\bin;%PATH%
|
- set PATH=C:\msys64\usr\bin;%PATH%
|
||||||
- set PATH=C:\msys64\mingw32\bin;%PATH%
|
- set PATH=C:\msys64\mingw32\bin;%PATH%
|
||||||
- pacman --noconfirm -S mingw-w64-i686-qt5 mingw-w64-i686-miniupnpc mingw-w64-i686-sqlcipher mingw-w64-i686-libmicrohttpd mingw-w64-i686-xapian-core
|
- pacman --noconfirm -S mingw-w64-i686-qt5 mingw-w64-i686-miniupnpc mingw-w64-i686-sqlcipher mingw-w64-i686-libmicrohttpd mingw-w64-i686-xapian-core mingw-w64-i686-cmark
|
||||||
#- pacman --noconfirm -S mingw-w64-i686-qt5-static mingw-w64-i686-miniupnpc mingw-w64-i686-sqlcipher mingw-w64-i686-libmicrohttpd
|
#- pacman --noconfirm -S mingw-w64-i686-qt5-static mingw-w64-i686-miniupnpc mingw-w64-i686-sqlcipher mingw-w64-i686-libmicrohttpd
|
||||||
#- set PATH=C:\msys64\mingw32\qt5-static\bin\;%PATH%
|
#- set PATH=C:\msys64\mingw32\qt5-static\bin\;%PATH%
|
||||||
|
|
||||||
|
@ -105,6 +105,15 @@ install:
|
||||||
- copy C:\msys64\mingw64\x86_64-w64-mingw32\bin\ranlib.exe C:\msys64\mingw64\bin\x86_64-w64-mingw32-ranlib.exe
|
- copy C:\msys64\mingw64\x86_64-w64-mingw32\bin\ranlib.exe C:\msys64\mingw64\bin\x86_64-w64-mingw32-ranlib.exe
|
||||||
- copy C:\msys64\mingw64\bin\windres.exe C:\msys64\mingw64\bin\x86_64-w64-mingw32-windres.exe
|
- copy C:\msys64\mingw64\bin\windres.exe C:\msys64\mingw64\bin\x86_64-w64-mingw32-windres.exe
|
||||||
|
|
||||||
|
# Work-around linker looking for Qt dll in wrong place
|
||||||
|
- copy C:\msys64\mingw32\bin\Qt5PrintSupport.dll C:\msys64\mingw32\lib\Qt5PrintSupport.dll
|
||||||
|
- copy C:\msys64\mingw32\bin\Qt5Widgets.dll C:\msys64\mingw32\lib\Qt5Widgets.dll
|
||||||
|
- copy C:\msys64\mingw32\bin\Qt5Multimedia.dll C:\msys64\mingw32\lib\Qt5Multimedia.dll
|
||||||
|
- copy C:\msys64\mingw32\bin\Qt5Gui.dll C:\msys64\mingw32\lib\Qt5Gui.dll
|
||||||
|
- copy C:\msys64\mingw32\bin\Qt5Network.dll C:\msys64\mingw32\lib\Qt5Network.dll
|
||||||
|
- copy C:\msys64\mingw32\bin\Qt5Xml.dll C:\msys64\mingw32\lib\Qt5Xml.dll
|
||||||
|
- copy C:\msys64\mingw32\bin\Qt5Core.dll C:\msys64\mingw32\lib\Qt5Core.dll
|
||||||
|
|
||||||
|
|
||||||
#---------------------------------#
|
#---------------------------------#
|
||||||
# build configuration #
|
# build configuration #
|
||||||
|
@ -137,6 +146,7 @@ before_package:
|
||||||
# to run your custom scripts instead of automatic MSBuild
|
# to run your custom scripts instead of automatic MSBuild
|
||||||
build_script:
|
build_script:
|
||||||
- env
|
- env
|
||||||
|
- git submodule update --init
|
||||||
- qmake -Wall -spec win32-g++ "CONFIG=debug"
|
- qmake -Wall -spec win32-g++ "CONFIG=debug"
|
||||||
- mingw32-make -j3
|
- mingw32-make -j3
|
||||||
|
|
||||||
|
@ -236,6 +246,10 @@ after_build:
|
||||||
- copy C:\msys64\mingw32\bin\libunistring*.dll %RS_DEPLOY%\
|
- copy C:\msys64\mingw32\bin\libunistring*.dll %RS_DEPLOY%\
|
||||||
- copy C:\msys64\mingw32\bin\libffi*.dll %RS_DEPLOY%\
|
- copy C:\msys64\mingw32\bin\libffi*.dll %RS_DEPLOY%\
|
||||||
|
|
||||||
|
## Needed for cmark
|
||||||
|
- copy C:\msys64\mingw32\bin\libcmark*.dll %RS_DEPLOY%\
|
||||||
|
- copy C:\msys64\mingw32\bin\libdouble-conversion*.dll %RS_DEPLOY%\
|
||||||
|
|
||||||
- find C:\projects\RetroShare >> filelist.txt
|
- find C:\projects\RetroShare >> filelist.txt
|
||||||
|
|
||||||
# to disable automatic builds
|
# to disable automatic builds
|
||||||
|
|
|
@ -21,15 +21,15 @@ define_default_value HOST_NUM_CPU $(nproc)
|
||||||
define_default_value BZIP2_SOURCE_VERSION "1.0.6"
|
define_default_value BZIP2_SOURCE_VERSION "1.0.6"
|
||||||
define_default_value BZIP2_SOURCE_SHA256 a2848f34fcd5d6cf47def00461fcb528a0484d8edef8208d6d2e2909dc61d9cd
|
define_default_value BZIP2_SOURCE_SHA256 a2848f34fcd5d6cf47def00461fcb528a0484d8edef8208d6d2e2909dc61d9cd
|
||||||
|
|
||||||
define_default_value OPENSSL_SOURCE_VERSION "1.1.1"
|
define_default_value OPENSSL_SOURCE_VERSION "1.1.1c"
|
||||||
define_default_value OPENSSL_SOURCE_SHA256 2836875a0f89c03d0fdf483941512613a50cfb421d6fd94b9f41d7279d586a3d
|
define_default_value OPENSSL_SOURCE_SHA256 f6fb3079ad15076154eda9413fed42877d668e7069d9b87396d0804fdb3f4c90
|
||||||
|
|
||||||
define_default_value SQLITE_SOURCE_YEAR "2018"
|
define_default_value SQLITE_SOURCE_YEAR "2018"
|
||||||
define_default_value SQLITE_SOURCE_VERSION "3250200"
|
define_default_value SQLITE_SOURCE_VERSION "3250200"
|
||||||
define_default_value SQLITE_SOURCE_SHA256 da9a1484423d524d3ac793af518cdf870c8255d209e369bd6a193e9f9d0e3181
|
define_default_value SQLITE_SOURCE_SHA256 da9a1484423d524d3ac793af518cdf870c8255d209e369bd6a193e9f9d0e3181
|
||||||
|
|
||||||
define_default_value SQLCIPHER_SOURCE_VERSION "3.4.2"
|
define_default_value SQLCIPHER_SOURCE_VERSION "4.2.0"
|
||||||
define_default_value SQLCIPHER_SOURCE_SHA256 69897a5167f34e8a84c7069f1b283aba88cdfa8ec183165c4a5da2c816cfaadb
|
define_default_value SQLCIPHER_SOURCE_SHA256 105c1b813f848da038c03647a8bfc9d42fb46865e6aaf4edfd46ff3b18cdccfc
|
||||||
|
|
||||||
define_default_value LIBUPNP_SOURCE_VERSION "1.8.4"
|
define_default_value LIBUPNP_SOURCE_VERSION "1.8.4"
|
||||||
define_default_value LIBUPNP_SOURCE_SHA256 976c3e4555604cdd8391ed2f359c08c9dead3b6bf131c24ce78e64d6669af2ed
|
define_default_value LIBUPNP_SOURCE_SHA256 976c3e4555604cdd8391ed2f359c08c9dead3b6bf131c24ce78e64d6669af2ed
|
||||||
|
@ -38,7 +38,7 @@ define_default_value INSTALL_QT_ANDROID "false"
|
||||||
define_default_value QT_VERSION "5.12.0"
|
define_default_value QT_VERSION "5.12.0"
|
||||||
define_default_value QT_ANDROID_INSTALLER_SHA256 a214084e2295c9a9f8727e8a0131c37255bf724bfc69e80f7012ba3abeb1f763
|
define_default_value QT_ANDROID_INSTALLER_SHA256 a214084e2295c9a9f8727e8a0131c37255bf724bfc69e80f7012ba3abeb1f763
|
||||||
|
|
||||||
define_default_value RESTBED_SOURCE_VERSION "4.6"
|
define_default_value RESTBED_SOURCE_VERSION f74f9329dac82e662c1d570b7cd72c192b729eb4
|
||||||
|
|
||||||
define_default_value UDP_DISCOVERY_CPP_SOURCE "https://github.com/truvorskameikin/udp-discovery-cpp.git"
|
define_default_value UDP_DISCOVERY_CPP_SOURCE "https://github.com/truvorskameikin/udp-discovery-cpp.git"
|
||||||
define_default_value UDP_DISCOVERY_CPP_VERSION "develop"
|
define_default_value UDP_DISCOVERY_CPP_VERSION "develop"
|
||||||
|
@ -81,15 +81,24 @@ function verified_download()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cArch=""
|
||||||
|
eABI=""
|
||||||
|
|
||||||
|
case "${ANDROID_NDK_ARCH}" in
|
||||||
if [ "${ANDROID_NDK_ARCH}" == "x86" ]; then
|
"arm")
|
||||||
cArch="i686"
|
|
||||||
eABI=""
|
|
||||||
else
|
|
||||||
cArch="${ANDROID_NDK_ARCH}"
|
cArch="${ANDROID_NDK_ARCH}"
|
||||||
eABI="eabi"
|
eABI="eabi"
|
||||||
fi
|
;;
|
||||||
|
"arm64")
|
||||||
|
cArch="aarch64"
|
||||||
|
eABI=""
|
||||||
|
;;
|
||||||
|
"x86")
|
||||||
|
cArch="i686"
|
||||||
|
eABI=""
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
export SYSROOT="${NATIVE_LIBS_TOOLCHAIN_PATH}/sysroot/"
|
export SYSROOT="${NATIVE_LIBS_TOOLCHAIN_PATH}/sysroot/"
|
||||||
export PREFIX="${SYSROOT}/usr/"
|
export PREFIX="${SYSROOT}/usr/"
|
||||||
export CC="${NATIVE_LIBS_TOOLCHAIN_PATH}/bin/${cArch}-linux-android${eABI}-clang"
|
export CC="${NATIVE_LIBS_TOOLCHAIN_PATH}/bin/${cArch}-linux-android${eABI}-clang"
|
||||||
|
@ -101,6 +110,12 @@ export RANLIB="${NATIVE_LIBS_TOOLCHAIN_PATH}/bin/${cArch}-linux-android${eABI}-r
|
||||||
## More information available at https://android.googlesource.com/platform/ndk/+/ics-mr0/docs/STANDALONE-TOOLCHAIN.html
|
## More information available at https://android.googlesource.com/platform/ndk/+/ics-mr0/docs/STANDALONE-TOOLCHAIN.html
|
||||||
build_toolchain()
|
build_toolchain()
|
||||||
{
|
{
|
||||||
|
echo "build_toolchain()
|
||||||
|
################################################################################
|
||||||
|
################################################################################
|
||||||
|
################################################################################
|
||||||
|
"
|
||||||
|
|
||||||
rm -rf ${NATIVE_LIBS_TOOLCHAIN_PATH}
|
rm -rf ${NATIVE_LIBS_TOOLCHAIN_PATH}
|
||||||
${ANDROID_NDK_PATH}/build/tools/make_standalone_toolchain.py --verbose \
|
${ANDROID_NDK_PATH}/build/tools/make_standalone_toolchain.py --verbose \
|
||||||
--arch ${ANDROID_NDK_ARCH} --install-dir ${NATIVE_LIBS_TOOLCHAIN_PATH} \
|
--arch ${ANDROID_NDK_ARCH} --install-dir ${NATIVE_LIBS_TOOLCHAIN_PATH} \
|
||||||
|
@ -111,6 +126,11 @@ build_toolchain()
|
||||||
## This avoid <cmath> include errors due to -isystem and -I ordering issue
|
## This avoid <cmath> include errors due to -isystem and -I ordering issue
|
||||||
delete_copied_includes()
|
delete_copied_includes()
|
||||||
{
|
{
|
||||||
|
echo "delete_copied_includes()
|
||||||
|
################################################################################
|
||||||
|
################################################################################
|
||||||
|
################################################################################
|
||||||
|
"
|
||||||
cat "${NATIVE_LIBS_TOOLCHAIN_PATH}/deletefiles" | while read delFile ; do
|
cat "${NATIVE_LIBS_TOOLCHAIN_PATH}/deletefiles" | while read delFile ; do
|
||||||
rm "$delFile"
|
rm "$delFile"
|
||||||
done
|
done
|
||||||
|
@ -119,6 +139,12 @@ delete_copied_includes()
|
||||||
## More information available at https://gitlab.com/relan/provisioners/merge_requests/1 and http://stackoverflow.com/a/34032216
|
## More information available at https://gitlab.com/relan/provisioners/merge_requests/1 and http://stackoverflow.com/a/34032216
|
||||||
install_qt_android()
|
install_qt_android()
|
||||||
{
|
{
|
||||||
|
echo "install_qt_android()
|
||||||
|
################################################################################
|
||||||
|
################################################################################
|
||||||
|
################################################################################
|
||||||
|
"
|
||||||
|
|
||||||
QT_VERSION_CODE=$(echo $QT_VERSION | tr -d .)
|
QT_VERSION_CODE=$(echo $QT_VERSION | tr -d .)
|
||||||
QT_INSTALL_PATH=${NATIVE_LIBS_TOOLCHAIN_PATH}/Qt
|
QT_INSTALL_PATH=${NATIVE_LIBS_TOOLCHAIN_PATH}/Qt
|
||||||
QT_INSTALLER="qt-unified-linux-x64-3.0.2-online.run"
|
QT_INSTALLER="qt-unified-linux-x64-3.0.2-online.run"
|
||||||
|
@ -202,6 +228,12 @@ QT_QPA_PLATFORM=minimal ./${QT_INSTALLER} --script ${QT_INSTALLER_SCRIPT}
|
||||||
## More information available at retroshare://file?name=Android%20Native%20Development%20Kit%20Cookbook.pdf&size=29214468&hash=0123361c1b14366ce36118e82b90faf7c7b1b136
|
## More information available at retroshare://file?name=Android%20Native%20Development%20Kit%20Cookbook.pdf&size=29214468&hash=0123361c1b14366ce36118e82b90faf7c7b1b136
|
||||||
build_bzlib()
|
build_bzlib()
|
||||||
{
|
{
|
||||||
|
echo "build_bzlib()
|
||||||
|
################################################################################
|
||||||
|
################################################################################
|
||||||
|
################################################################################
|
||||||
|
"
|
||||||
|
|
||||||
B_dir="bzip2-${BZIP2_SOURCE_VERSION}"
|
B_dir="bzip2-${BZIP2_SOURCE_VERSION}"
|
||||||
rm -rf $B_dir
|
rm -rf $B_dir
|
||||||
|
|
||||||
|
@ -226,6 +258,12 @@ build_bzlib()
|
||||||
## More information available at http://doc.qt.io/qt-5/opensslsupport.html
|
## More information available at http://doc.qt.io/qt-5/opensslsupport.html
|
||||||
build_openssl()
|
build_openssl()
|
||||||
{
|
{
|
||||||
|
echo "build_openssl()
|
||||||
|
################################################################################
|
||||||
|
################################################################################
|
||||||
|
################################################################################
|
||||||
|
"
|
||||||
|
|
||||||
B_dir="openssl-${OPENSSL_SOURCE_VERSION}"
|
B_dir="openssl-${OPENSSL_SOURCE_VERSION}"
|
||||||
rm -rf $B_dir
|
rm -rf $B_dir
|
||||||
|
|
||||||
|
@ -243,7 +281,7 @@ build_openssl()
|
||||||
[[ ${ANDROID_NDK_ARCH} =~ .*64.* ]] && oBits=64
|
[[ ${ANDROID_NDK_ARCH} =~ .*64.* ]] && oBits=64
|
||||||
|
|
||||||
ANDROID_NDK="${ANDROID_NDK_PATH}" PATH="${SYSROOT}/bin/:${PATH}" \
|
ANDROID_NDK="${ANDROID_NDK_PATH}" PATH="${SYSROOT}/bin/:${PATH}" \
|
||||||
./Configure linux-generic${oBits} --prefix="${PREFIX}" \
|
./Configure linux-generic${oBits} -fPIC --prefix="${PREFIX}" \
|
||||||
--openssldir="${SYSROOT}/etc/ssl"
|
--openssldir="${SYSROOT}/etc/ssl"
|
||||||
# sed -i 's/LIBNAME=$$i LIBVERSION=$(SHLIB_MAJOR).$(SHLIB_MINOR) \\/LIBNAME=$$i \\/g' Makefile
|
# sed -i 's/LIBNAME=$$i LIBVERSION=$(SHLIB_MAJOR).$(SHLIB_MINOR) \\/LIBNAME=$$i \\/g' Makefile
|
||||||
# sed -i '/LIBCOMPATVERSIONS=";$(SHLIB_VERSION_HISTORY)" \\/d' Makefile
|
# sed -i '/LIBCOMPATVERSIONS=";$(SHLIB_VERSION_HISTORY)" \\/d' Makefile
|
||||||
|
@ -256,14 +294,21 @@ build_openssl()
|
||||||
|
|
||||||
build_sqlite()
|
build_sqlite()
|
||||||
{
|
{
|
||||||
|
echo "build_sqlite()
|
||||||
|
################################################################################
|
||||||
|
################################################################################
|
||||||
|
################################################################################
|
||||||
|
"
|
||||||
|
|
||||||
B_dir="sqlite-autoconf-${SQLITE_SOURCE_VERSION}"
|
B_dir="sqlite-autoconf-${SQLITE_SOURCE_VERSION}"
|
||||||
|
rm -rf $B_dir
|
||||||
|
|
||||||
verified_download $B_dir.tar.gz $SQLITE_SOURCE_SHA256 \
|
verified_download $B_dir.tar.gz $SQLITE_SOURCE_SHA256 \
|
||||||
https://www.sqlite.org/${SQLITE_SOURCE_YEAR}/$B_dir.tar.gz
|
https://www.sqlite.org/${SQLITE_SOURCE_YEAR}/$B_dir.tar.gz
|
||||||
|
|
||||||
tar -xf $B_dir.tar.gz
|
tar -xf $B_dir.tar.gz
|
||||||
cd $B_dir
|
cd $B_dir
|
||||||
./configure --prefix="${PREFIX}" --host=${ANDROID_NDK_ARCH}-linux
|
./configure --with-pic --prefix="${PREFIX}" --host=${cArch}-linux
|
||||||
make -j${HOST_NUM_CPU}
|
make -j${HOST_NUM_CPU}
|
||||||
make install
|
make install
|
||||||
rm -f ${PREFIX}/lib/libsqlite3.so*
|
rm -f ${PREFIX}/lib/libsqlite3.so*
|
||||||
|
@ -274,6 +319,12 @@ build_sqlite()
|
||||||
|
|
||||||
build_sqlcipher()
|
build_sqlcipher()
|
||||||
{
|
{
|
||||||
|
echo "build_sqlcipher()
|
||||||
|
################################################################################
|
||||||
|
################################################################################
|
||||||
|
################################################################################
|
||||||
|
"
|
||||||
|
|
||||||
B_dir="sqlcipher-${SQLCIPHER_SOURCE_VERSION}"
|
B_dir="sqlcipher-${SQLCIPHER_SOURCE_VERSION}"
|
||||||
rm -rf $B_dir
|
rm -rf $B_dir
|
||||||
|
|
||||||
|
@ -284,8 +335,16 @@ build_sqlcipher()
|
||||||
|
|
||||||
tar -xf $T_file
|
tar -xf $T_file
|
||||||
cd $B_dir
|
cd $B_dir
|
||||||
./configure --build=$(sh ./config.guess) \
|
case "${ANDROID_NDK_ARCH}" in
|
||||||
--host=${ANDROID_NDK_ARCH}-linux \
|
"arm64")
|
||||||
|
# SQLCipher config.sub is outdated and doesn't recognize newer architectures
|
||||||
|
rm config.sub
|
||||||
|
autoreconf --verbose --install --force
|
||||||
|
automake --add-missing --copy --force-missing
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
./configure --with-pic --build=$(sh ./config.guess) \
|
||||||
|
--host=${cArch}-linux \
|
||||||
--prefix="${PREFIX}" --with-sysroot="${SYSROOT}" \
|
--prefix="${PREFIX}" --with-sysroot="${SYSROOT}" \
|
||||||
--enable-tempstore=yes \
|
--enable-tempstore=yes \
|
||||||
--disable-tcl --disable-shared \
|
--disable-tcl --disable-shared \
|
||||||
|
@ -297,6 +356,12 @@ build_sqlcipher()
|
||||||
|
|
||||||
build_libupnp()
|
build_libupnp()
|
||||||
{
|
{
|
||||||
|
echo "build_libupnp()
|
||||||
|
################################################################################
|
||||||
|
################################################################################
|
||||||
|
################################################################################
|
||||||
|
"
|
||||||
|
|
||||||
B_dir="pupnp-release-${LIBUPNP_SOURCE_VERSION}"
|
B_dir="pupnp-release-${LIBUPNP_SOURCE_VERSION}"
|
||||||
B_ext=".tar.gz"
|
B_ext=".tar.gz"
|
||||||
B_file="${B_dir}${B_ext}"
|
B_file="${B_dir}${B_ext}"
|
||||||
|
@ -312,9 +377,9 @@ build_libupnp()
|
||||||
## look for libthreadutils.so.6 at runtime that cannot be packaged on android
|
## look for libthreadutils.so.6 at runtime that cannot be packaged on android
|
||||||
## as it supports only libname.so format for libraries, thus resulting in a
|
## as it supports only libname.so format for libraries, thus resulting in a
|
||||||
## crash at startup.
|
## crash at startup.
|
||||||
./configure --enable-static --disable-shared --disable-samples \
|
./configure --with-pic --enable-static --disable-shared --disable-samples \
|
||||||
--disable-largefile \
|
--disable-largefile \
|
||||||
--prefix="${PREFIX}" --host=${ANDROID_NDK_ARCH}-linux
|
--prefix="${PREFIX}" --host=${cArch}-linux
|
||||||
make -j${HOST_NUM_CPU}
|
make -j${HOST_NUM_CPU}
|
||||||
make install
|
make install
|
||||||
cd ..
|
cd ..
|
||||||
|
@ -322,6 +387,12 @@ build_libupnp()
|
||||||
|
|
||||||
build_rapidjson()
|
build_rapidjson()
|
||||||
{
|
{
|
||||||
|
echo "build_rapidjson()
|
||||||
|
################################################################################
|
||||||
|
################################################################################
|
||||||
|
################################################################################
|
||||||
|
"
|
||||||
|
|
||||||
B_dir="rapidjson-${RAPIDJSON_SOURCE_VERSION}"
|
B_dir="rapidjson-${RAPIDJSON_SOURCE_VERSION}"
|
||||||
D_file="${B_dir}.tar.gz"
|
D_file="${B_dir}.tar.gz"
|
||||||
verified_download $D_file $RAPIDJSON_SOURCE_SHA256 \
|
verified_download $D_file $RAPIDJSON_SOURCE_SHA256 \
|
||||||
|
@ -332,17 +403,26 @@ build_rapidjson()
|
||||||
|
|
||||||
build_restbed()
|
build_restbed()
|
||||||
{
|
{
|
||||||
|
echo "build_restbed()
|
||||||
|
################################################################################
|
||||||
|
################################################################################
|
||||||
|
################################################################################
|
||||||
|
"
|
||||||
|
|
||||||
[ -d restbed ] || git clone --depth=2000 https://github.com/Corvusoft/restbed.git
|
[ -d restbed ] || git clone --depth=2000 https://github.com/Corvusoft/restbed.git
|
||||||
cd restbed
|
cd restbed
|
||||||
git fetch --tags
|
# git fetch --tags
|
||||||
git checkout tags/${RESTBED_SOURCE_VERSION}
|
# git checkout tags/${RESTBED_SOURCE_VERSION}
|
||||||
|
git checkout ${RESTBED_SOURCE_VERSION}
|
||||||
git submodule update --init dependency/asio
|
git submodule update --init dependency/asio
|
||||||
git submodule update --init dependency/catch
|
git submodule update --init dependency/catch
|
||||||
git submodule update --init dependency/kashmir
|
git submodule update --init dependency/kashmir
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
rm -rf restbed-build; mkdir restbed-build ; cd restbed-build
|
rm -rf restbed-build; mkdir restbed-build ; cd restbed-build
|
||||||
cmake -DBUILD_SSL=OFF -DCMAKE_INSTALL_PREFIX="${PREFIX}" -B. -H../restbed
|
cmake \
|
||||||
|
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
|
||||||
|
-DBUILD_SSL=OFF -DCMAKE_INSTALL_PREFIX="${PREFIX}" -B. -H../restbed
|
||||||
make -j${HOST_NUM_CPU}
|
make -j${HOST_NUM_CPU}
|
||||||
make install
|
make install
|
||||||
cp "${PREFIX}/library/librestbed.a" "${PREFIX}/lib/"
|
cp "${PREFIX}/library/librestbed.a" "${PREFIX}/lib/"
|
||||||
|
@ -351,6 +431,12 @@ build_restbed()
|
||||||
|
|
||||||
build_udp-discovery-cpp()
|
build_udp-discovery-cpp()
|
||||||
{
|
{
|
||||||
|
echo "build_udp-discovery-cpp()
|
||||||
|
################################################################################
|
||||||
|
################################################################################
|
||||||
|
################################################################################
|
||||||
|
"
|
||||||
|
|
||||||
S_dir="udp-discovery-cpp"
|
S_dir="udp-discovery-cpp"
|
||||||
[ -d $S_dir ] || git clone $UDP_DISCOVERY_CPP_SOURCE $S_dir
|
[ -d $S_dir ] || git clone $UDP_DISCOVERY_CPP_SOURCE $S_dir
|
||||||
cd $S_dir
|
cd $S_dir
|
||||||
|
@ -359,7 +445,9 @@ build_udp-discovery-cpp()
|
||||||
|
|
||||||
B_dir="udp-discovery-cpp-build"
|
B_dir="udp-discovery-cpp-build"
|
||||||
rm -rf ${B_dir}; mkdir ${B_dir}; cd ${B_dir}
|
rm -rf ${B_dir}; mkdir ${B_dir}; cd ${B_dir}
|
||||||
cmake -DCMAKE_INSTALL_PREFIX="${PREFIX}" -B. -H../udp-discovery-cpp
|
cmake \
|
||||||
|
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
|
||||||
|
-DCMAKE_INSTALL_PREFIX="${PREFIX}" -B. -H../udp-discovery-cpp
|
||||||
make -j${HOST_NUM_CPU}
|
make -j${HOST_NUM_CPU}
|
||||||
cp libudp-discovery.a "${PREFIX}/lib/"
|
cp libudp-discovery.a "${PREFIX}/lib/"
|
||||||
cp ../$S_dir/*.hpp "${PREFIX}/include/"
|
cp ../$S_dir/*.hpp "${PREFIX}/include/"
|
||||||
|
@ -368,6 +456,12 @@ build_udp-discovery-cpp()
|
||||||
|
|
||||||
build_xapian()
|
build_xapian()
|
||||||
{
|
{
|
||||||
|
echo "build_xapian()
|
||||||
|
################################################################################
|
||||||
|
################################################################################
|
||||||
|
################################################################################
|
||||||
|
"
|
||||||
|
|
||||||
B_dir="xapian-core-${XAPIAN_SOURCE_VERSION}"
|
B_dir="xapian-core-${XAPIAN_SOURCE_VERSION}"
|
||||||
D_file="$B_dir.tar.xz"
|
D_file="$B_dir.tar.xz"
|
||||||
verified_download $D_file $XAPIAN_SOURCE_SHA256 \
|
verified_download $D_file $XAPIAN_SOURCE_SHA256 \
|
||||||
|
@ -379,9 +473,10 @@ build_xapian()
|
||||||
B_large_file=""
|
B_large_file=""
|
||||||
[ "${ANDROID_PLATFORM_VER}" -lt "24" ] && B_large_file="--disable-largefile"
|
[ "${ANDROID_PLATFORM_VER}" -lt "24" ] && B_large_file="--disable-largefile"
|
||||||
./configure ${B_endiannes_detection_failure_workaround} ${B_large_file} \
|
./configure ${B_endiannes_detection_failure_workaround} ${B_large_file} \
|
||||||
|
--with-pic \
|
||||||
--disable-backend-inmemory --disable-backend-remote \
|
--disable-backend-inmemory --disable-backend-remote \
|
||||||
--disable--backend-chert --enable-backend-glass \
|
--disable--backend-chert --enable-backend-glass \
|
||||||
--host=${ANDROID_NDK_ARCH}-linux --enable-static --disable-shared \
|
--host=${cArch}-linux --enable-static --disable-shared \
|
||||||
--prefix="${PREFIX}" --with-sysroot="${SYSROOT}"
|
--prefix="${PREFIX}" --with-sysroot="${SYSROOT}"
|
||||||
make -j${HOST_NUM_CPU}
|
make -j${HOST_NUM_CPU}
|
||||||
make install
|
make install
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 35923c31918c0497827a6c22381178b63b10f6e0
|
Subproject commit a8c1d3bca9de4c93d0212ed9dcda22fe06c833ec
|
|
@ -18,8 +18,8 @@
|
||||||
* *
|
* *
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
registerHandler("$%apiPath%$",
|
registerHandler( "$%apiPath%$",
|
||||||
[$%captureVars%$](const std::shared_ptr<rb::Session> session)
|
[this](const std::shared_ptr<rb::Session> session)
|
||||||
{
|
{
|
||||||
const std::multimap<std::string, std::string> headers
|
const std::multimap<std::string, std::string> headers
|
||||||
{
|
{
|
||||||
|
@ -29,7 +29,7 @@ registerHandler("$%apiPath%$",
|
||||||
session->yield(rb::OK, headers);
|
session->yield(rb::OK, headers);
|
||||||
|
|
||||||
size_t reqSize = session->get_request()->get_header("Content-Length", 0);
|
size_t reqSize = session->get_request()->get_header("Content-Length", 0);
|
||||||
session->fetch( reqSize, [$%captureVars%$](
|
session->fetch( reqSize, [this](
|
||||||
const std::shared_ptr<rb::Session> session,
|
const std::shared_ptr<rb::Session> session,
|
||||||
const rb::Bytes& body )
|
const rb::Bytes& body )
|
||||||
{
|
{
|
||||||
|
@ -44,17 +44,24 @@ $%paramsDeclaration%$
|
||||||
$%inputParamsDeserialization%$
|
$%inputParamsDeserialization%$
|
||||||
|
|
||||||
const std::weak_ptr<rb::Session> weakSession(session);
|
const std::weak_ptr<rb::Session> weakSession(session);
|
||||||
$%callbackName%$ = [weakSession]($%callbackParams%$)
|
$%callbackName%$ = [this, weakSession]($%callbackParams%$)
|
||||||
{
|
{
|
||||||
auto session = weakSession.lock();
|
auto session = weakSession.lock();
|
||||||
if(!session || session->is_closed()) return;
|
if(!session || session->is_closed()) return;
|
||||||
|
|
||||||
$%callbackParamsSerialization%$
|
$%callbackParamsSerialization%$
|
||||||
|
|
||||||
std::stringstream message;
|
std::stringstream sStream;
|
||||||
message << "data: " << compactJSON << ctx.mJson << "\n\n";
|
sStream << "data: " << compactJSON << ctx.mJson << "\n\n";
|
||||||
session->yield(message.str());
|
const std::string message = sStream.str();
|
||||||
|
|
||||||
|
mService.schedule( [weakSession, message]()
|
||||||
|
{
|
||||||
|
auto session = weakSession.lock();
|
||||||
|
if(!session || session->is_closed()) return;
|
||||||
|
session->yield(message);
|
||||||
$%sessionEarlyClose%$
|
$%sessionEarlyClose%$
|
||||||
|
} );
|
||||||
};
|
};
|
||||||
|
|
||||||
$%functionCall%$
|
$%functionCall%$
|
||||||
|
@ -67,5 +74,4 @@ $%outputParamsSerialization%$
|
||||||
session->yield(message.str());
|
session->yield(message.str());
|
||||||
$%sessionDelayedClose%$
|
$%sessionDelayedClose%$
|
||||||
} );
|
} );
|
||||||
}, $%requiresAuth%$);
|
}, $%requiresAuth%$ );
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,7 @@ int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
QDomDocument hDoc;
|
QDomDocument hDoc;
|
||||||
QString hFilePath(it.next());
|
QString hFilePath(it.next());
|
||||||
QString parseError; int line, column;
|
QString parseError; int line = -1, column = -1;
|
||||||
QFile hFile(hFilePath);
|
QFile hFile(hFilePath);
|
||||||
if (!hFile.open(QIODevice::ReadOnly) ||
|
if (!hFile.open(QIODevice::ReadOnly) ||
|
||||||
!hDoc.setContent(&hFile, &parseError, &line, &column))
|
!hDoc.setContent(&hFile, &parseError, &line, &column))
|
||||||
|
@ -320,18 +320,13 @@ int main(int argc, char *argv[])
|
||||||
"\t\t\tRS_SERIAL_PROCESS(retval);\n";
|
"\t\t\tRS_SERIAL_PROCESS(retval);\n";
|
||||||
if(hasOutput) outputParamsSerialization += "\t\t}\n";
|
if(hasOutput) outputParamsSerialization += "\t\t}\n";
|
||||||
|
|
||||||
QString captureVars;
|
|
||||||
|
|
||||||
QString sessionEarlyClose;
|
QString sessionEarlyClose;
|
||||||
if(hasSingleCallback)
|
if(hasSingleCallback)
|
||||||
sessionEarlyClose = "session->close();";
|
sessionEarlyClose = "session->close();";
|
||||||
|
|
||||||
QString sessionDelayedClose;
|
QString sessionDelayedClose;
|
||||||
if(hasMultiCallback)
|
if(hasMultiCallback)
|
||||||
{
|
sessionDelayedClose = "RsThread::async( [=](){ std::this_thread::sleep_for(std::chrono::seconds(maxWait+120)); mService.schedule( [=](){ auto session = weakSession.lock(); if(session && session->is_open()) session->close(); } ); } );";
|
||||||
sessionDelayedClose = "mService.schedule( [session](){session->close();}, std::chrono::seconds(maxWait+120) );";
|
|
||||||
captureVars = "this";
|
|
||||||
}
|
|
||||||
|
|
||||||
QString callbackParamsSerialization;
|
QString callbackParamsSerialization;
|
||||||
|
|
||||||
|
@ -381,7 +376,6 @@ int main(int argc, char *argv[])
|
||||||
substitutionsMap.insert("apiPath", apiPath);
|
substitutionsMap.insert("apiPath", apiPath);
|
||||||
substitutionsMap.insert("sessionEarlyClose", sessionEarlyClose);
|
substitutionsMap.insert("sessionEarlyClose", sessionEarlyClose);
|
||||||
substitutionsMap.insert("sessionDelayedClose", sessionDelayedClose);
|
substitutionsMap.insert("sessionDelayedClose", sessionDelayedClose);
|
||||||
substitutionsMap.insert("captureVars", captureVars);
|
|
||||||
substitutionsMap.insert("callbackName", callbackName);
|
substitutionsMap.insert("callbackName", callbackName);
|
||||||
substitutionsMap.insert("callbackParams", callbackParams);
|
substitutionsMap.insert("callbackParams", callbackParams);
|
||||||
substitutionsMap.insert("callbackParamsSerialization", callbackParamsSerialization);
|
substitutionsMap.insert("callbackParamsSerialization", callbackParamsSerialization);
|
||||||
|
|
|
@ -18,8 +18,8 @@
|
||||||
* *
|
* *
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
registerHandler("$%apiPath%$",
|
registerHandler( "$%apiPath%$",
|
||||||
[$%captureVars%$](const std::shared_ptr<rb::Session> session)
|
[](const std::shared_ptr<rb::Session> session)
|
||||||
{
|
{
|
||||||
size_t reqSize = session->get_request()->get_header("Content-Length", 0);
|
size_t reqSize = session->get_request()->get_header("Content-Length", 0);
|
||||||
session->fetch( reqSize, [](
|
session->fetch( reqSize, [](
|
||||||
|
@ -46,5 +46,5 @@ $%outputParamsSerialization%$
|
||||||
// return them to the API caller
|
// return them to the API caller
|
||||||
DEFAULT_API_CALL_JSON_RETURN(rb::OK);
|
DEFAULT_API_CALL_JSON_RETURN(rb::OK);
|
||||||
} );
|
} );
|
||||||
}, $%requiresAuth%$);
|
}, $%requiresAuth%$ );
|
||||||
|
|
||||||
|
|
|
@ -933,7 +933,7 @@ void DistributedChatService::sendLobbyStatusPeerChangedNickname(const ChatLobbyI
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DistributedChatService::sendLobbyStatusPeerLiving(const ChatLobbyId& lobby_id)
|
void DistributedChatService::sendLobbyStatusPeerLeaving(const ChatLobbyId& lobby_id)
|
||||||
{
|
{
|
||||||
sendLobbyStatusItem(lobby_id,RS_CHAT_LOBBY_EVENT_PEER_LEFT,std::string()) ;
|
sendLobbyStatusItem(lobby_id,RS_CHAT_LOBBY_EVENT_PEER_LEFT,std::string()) ;
|
||||||
}
|
}
|
||||||
|
@ -990,7 +990,7 @@ bool DistributedChatService::locked_initLobbyBouncableObject(const ChatLobbyId&
|
||||||
while( lobby.msg_cache.find(item.msg_id) != lobby.msg_cache.end() ) ;
|
while( lobby.msg_cache.find(item.msg_id) != lobby.msg_cache.end() ) ;
|
||||||
|
|
||||||
RsIdentityDetails details ;
|
RsIdentityDetails details ;
|
||||||
if(!rsIdentity->getIdDetails(lobby.gxs_id,details))
|
if(!rsIdentity || !rsIdentity->getIdDetails(lobby.gxs_id,details))
|
||||||
{
|
{
|
||||||
std::cerr << "(EE) Cannot send chat lobby object. Signign identity " << lobby.gxs_id << " is unknown." << std::endl;
|
std::cerr << "(EE) Cannot send chat lobby object. Signign identity " << lobby.gxs_id << " is unknown." << std::endl;
|
||||||
return false ;
|
return false ;
|
||||||
|
@ -1580,6 +1580,9 @@ bool DistributedChatService::joinVisibleChatLobby(const ChatLobbyId& lobby_id,co
|
||||||
}
|
}
|
||||||
_chat_lobbys[lobby_id] = entry ;
|
_chat_lobbys[lobby_id] = entry ;
|
||||||
}
|
}
|
||||||
|
setLobbyAutoSubscribe(lobby_id,true);
|
||||||
|
|
||||||
|
triggerConfigSave(); // so that we save the subscribed lobbies
|
||||||
|
|
||||||
for(std::list<RsPeerId>::const_iterator it(invited_friends.begin());it!=invited_friends.end();++it)
|
for(std::list<RsPeerId>::const_iterator it(invited_friends.begin());it!=invited_friends.end();++it)
|
||||||
invitePeerToLobby(lobby_id,*it) ;
|
invitePeerToLobby(lobby_id,*it) ;
|
||||||
|
@ -1629,6 +1632,8 @@ ChatLobbyId DistributedChatService::createChatLobby(const std::string& lobby_nam
|
||||||
|
|
||||||
RsServer::notify()->notifyListChange(NOTIFY_LIST_CHAT_LOBBY_LIST, NOTIFY_TYPE_ADD) ;
|
RsServer::notify()->notifyListChange(NOTIFY_LIST_CHAT_LOBBY_LIST, NOTIFY_TYPE_ADD) ;
|
||||||
|
|
||||||
|
triggerConfigSave();
|
||||||
|
|
||||||
return lobby_id ;
|
return lobby_id ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1666,10 +1671,11 @@ void DistributedChatService::handleFriendUnsubscribeLobby(RsChatLobbyUnsubscribe
|
||||||
void DistributedChatService::unsubscribeChatLobby(const ChatLobbyId& id)
|
void DistributedChatService::unsubscribeChatLobby(const ChatLobbyId& id)
|
||||||
{
|
{
|
||||||
// send AKN item
|
// send AKN item
|
||||||
sendLobbyStatusPeerLiving(id) ;
|
sendLobbyStatusPeerLeaving(id) ;
|
||||||
|
setLobbyAutoSubscribe(id, false);
|
||||||
|
|
||||||
{
|
{
|
||||||
RsStackMutex stack(mDistributedChatMtx); /********** STACK LOCKED MTX ******/
|
RS_STACK_MUTEX(mDistributedChatMtx);
|
||||||
|
|
||||||
std::map<ChatLobbyId,ChatLobbyEntry>::iterator it = _chat_lobbys.find(id) ;
|
std::map<ChatLobbyId,ChatLobbyEntry>::iterator it = _chat_lobbys.find(id) ;
|
||||||
|
|
||||||
|
@ -1704,6 +1710,7 @@ void DistributedChatService::unsubscribeChatLobby(const ChatLobbyId& id)
|
||||||
_chat_lobbys.erase(it) ;
|
_chat_lobbys.erase(it) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
triggerConfigSave(); // so that we save the subscribed lobbies
|
||||||
RsServer::notify()->notifyListChange(NOTIFY_LIST_CHAT_LOBBY_LIST, NOTIFY_TYPE_DEL) ;
|
RsServer::notify()->notifyListChange(NOTIFY_LIST_CHAT_LOBBY_LIST, NOTIFY_TYPE_DEL) ;
|
||||||
|
|
||||||
// done!
|
// done!
|
||||||
|
@ -1826,12 +1833,24 @@ bool DistributedChatService::setIdentityForChatLobby(const ChatLobbyId& lobby_id
|
||||||
|
|
||||||
void DistributedChatService::setLobbyAutoSubscribe(const ChatLobbyId& lobby_id, const bool autoSubscribe)
|
void DistributedChatService::setLobbyAutoSubscribe(const ChatLobbyId& lobby_id, const bool autoSubscribe)
|
||||||
{
|
{
|
||||||
if(autoSubscribe){
|
|
||||||
|
if(autoSubscribe)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(mDistributedChatMtx);
|
||||||
_known_lobbies_flags[lobby_id] |= RS_CHAT_LOBBY_FLAGS_AUTO_SUBSCRIBE;
|
_known_lobbies_flags[lobby_id] |= RS_CHAT_LOBBY_FLAGS_AUTO_SUBSCRIBE;
|
||||||
|
}
|
||||||
RsGxsId gxsId;
|
RsGxsId gxsId;
|
||||||
|
|
||||||
if (getIdentityForChatLobby(lobby_id, gxsId))
|
if (getIdentityForChatLobby(lobby_id, gxsId))
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(mDistributedChatMtx);
|
||||||
_lobby_default_identity[lobby_id] = gxsId;
|
_lobby_default_identity[lobby_id] = gxsId;
|
||||||
} else {
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(mDistributedChatMtx);
|
||||||
_known_lobbies_flags[lobby_id] &= ~RS_CHAT_LOBBY_FLAGS_AUTO_SUBSCRIBE ;
|
_known_lobbies_flags[lobby_id] &= ~RS_CHAT_LOBBY_FLAGS_AUTO_SUBSCRIBE ;
|
||||||
_lobby_default_identity.erase(lobby_id);
|
_lobby_default_identity.erase(lobby_id);
|
||||||
}
|
}
|
||||||
|
@ -1966,6 +1985,15 @@ void DistributedChatService::addToSaveList(std::list<RsItem*>& list) const
|
||||||
list.push_back(clci) ;
|
list.push_back(clci) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for(auto it(_chat_lobbys.begin());it!=_chat_lobbys.end();++it)
|
||||||
|
{
|
||||||
|
RsSubscribedChatLobbyConfigItem *scli = new RsSubscribedChatLobbyConfigItem;
|
||||||
|
|
||||||
|
scli->info = it->second; // copies the ChatLobbyInfo part only
|
||||||
|
|
||||||
|
list.push_back(scli);
|
||||||
|
}
|
||||||
|
|
||||||
/* Save Default Nick Name */
|
/* Save Default Nick Name */
|
||||||
{
|
{
|
||||||
RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ;
|
RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ;
|
||||||
|
@ -2061,6 +2089,59 @@ bool DistributedChatService::processLoadListItem(const RsItem *item)
|
||||||
if(!own_ids.empty())
|
if(!own_ids.empty())
|
||||||
_default_identity = own_ids.front() ;
|
_default_identity = own_ids.front() ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RsSubscribedChatLobbyConfigItem *scli = dynamic_cast<const RsSubscribedChatLobbyConfigItem*>(item);
|
||||||
|
|
||||||
|
if(scli != NULL)
|
||||||
|
{
|
||||||
|
if(_chat_lobbys.find(scli->info.lobby_id) != _chat_lobbys.end()) // do nothing if the lobby is already subscribed
|
||||||
|
return true;
|
||||||
|
|
||||||
|
std::cerr << "Re-subscribing to chat lobby " << (void*)scli->info.lobby_id << ", flags = " << scli->info.lobby_flags << std::endl;
|
||||||
|
|
||||||
|
rstime_t now = time(NULL);
|
||||||
|
|
||||||
|
// Add the chat room into visible chat rooms
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(mDistributedChatMtx); /********** STACK LOCKED MTX ******/
|
||||||
|
|
||||||
|
VisibleChatLobbyRecord& rec(_visible_lobbies[scli->info.lobby_id]) ;
|
||||||
|
|
||||||
|
rec.lobby_id = scli->info.lobby_id ;
|
||||||
|
rec.lobby_name = scli->info.lobby_name ;
|
||||||
|
rec.lobby_topic = scli->info.lobby_topic ;
|
||||||
|
rec.participating_friends = scli->info.participating_friends;
|
||||||
|
rec.total_number_of_peers = 0;
|
||||||
|
rec.last_report_time = now ;
|
||||||
|
rec.lobby_flags = EXTRACT_PRIVACY_FLAGS(scli->info.lobby_flags) ;
|
||||||
|
|
||||||
|
_known_lobbies_flags[scli->info.lobby_id] |= RS_CHAT_LOBBY_FLAGS_AUTO_SUBSCRIBE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the chat room into subscribed chat rooms
|
||||||
|
|
||||||
|
ChatLobbyEntry entry ;
|
||||||
|
(ChatLobbyInfo&)entry = scli->info;
|
||||||
|
|
||||||
|
entry.virtual_peer_id = makeVirtualPeerId(entry.lobby_id) ; // not random, so we keep the same id at restart
|
||||||
|
entry.connexion_challenge_count = 0 ;
|
||||||
|
entry.last_activity = now ;
|
||||||
|
entry.last_connexion_challenge_time = now ;
|
||||||
|
entry.last_keep_alive_packet_time = now ;
|
||||||
|
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(mDistributedChatMtx); /********** STACK LOCKED MTX ******/
|
||||||
|
_chat_lobbys[entry.lobby_id] = entry ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make the UI aware of the existing chat room
|
||||||
|
|
||||||
|
RsServer::notify()->notifyListChange(NOTIFY_LIST_CHAT_LOBBY_LIST, NOTIFY_TYPE_ADD) ;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return false ;
|
return false ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,7 @@ class DistributedChatService
|
||||||
void setLobbyAutoSubscribe(const ChatLobbyId& lobby_id, const bool autoSubscribe);
|
void setLobbyAutoSubscribe(const ChatLobbyId& lobby_id, const bool autoSubscribe);
|
||||||
bool getLobbyAutoSubscribe(const ChatLobbyId& lobby_id);
|
bool getLobbyAutoSubscribe(const ChatLobbyId& lobby_id);
|
||||||
void sendLobbyStatusString(const ChatLobbyId& id,const std::string& status_string) ;
|
void sendLobbyStatusString(const ChatLobbyId& id,const std::string& status_string) ;
|
||||||
|
void sendLobbyStatusPeerLeaving(const ChatLobbyId& lobby_id) ;
|
||||||
|
|
||||||
ChatLobbyId createChatLobby(const std::string& lobby_name,const RsGxsId& lobby_identity,const std::string& lobby_topic, const std::set<RsPeerId>& invited_friends,ChatLobbyFlags flags) ;
|
ChatLobbyId createChatLobby(const std::string& lobby_name,const RsGxsId& lobby_identity,const std::string& lobby_topic, const std::set<RsPeerId>& invited_friends,ChatLobbyFlags flags) ;
|
||||||
|
|
||||||
|
@ -119,7 +120,6 @@ class DistributedChatService
|
||||||
bool bounceLobbyObject(RsChatLobbyBouncingObject *obj, const RsPeerId& peer_id) ;
|
bool bounceLobbyObject(RsChatLobbyBouncingObject *obj, const RsPeerId& peer_id) ;
|
||||||
|
|
||||||
void sendLobbyStatusItem(const ChatLobbyId&, int type, const std::string& status_string) ;
|
void sendLobbyStatusItem(const ChatLobbyId&, int type, const std::string& status_string) ;
|
||||||
void sendLobbyStatusPeerLiving(const ChatLobbyId& lobby_id) ;
|
|
||||||
void sendLobbyStatusPeerChangedNickname(const ChatLobbyId& lobby_id, const std::string& newnick) ;
|
void sendLobbyStatusPeerChangedNickname(const ChatLobbyId& lobby_id, const std::string& newnick) ;
|
||||||
|
|
||||||
void sendLobbyStatusNewPeer(const ChatLobbyId& lobby_id) ;
|
void sendLobbyStatusNewPeer(const ChatLobbyId& lobby_id) ;
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include "retroshare/rsmsgs.h"
|
||||||
#include "util/rstime.h"
|
#include "util/rstime.h"
|
||||||
#include "serialiser/rsbaseserial.h"
|
#include "serialiser/rsbaseserial.h"
|
||||||
#include "serialiser/rstlvbase.h"
|
#include "serialiser/rstlvbase.h"
|
||||||
|
@ -52,6 +53,7 @@ RsItem *RsChatSerialiser::create_item(uint16_t service_id,uint8_t item_sub_id) c
|
||||||
case RS_PKT_SUBTYPE_CHAT_LOBBY_LIST_REQUEST: return new RsChatLobbyListRequestItem();
|
case RS_PKT_SUBTYPE_CHAT_LOBBY_LIST_REQUEST: return new RsChatLobbyListRequestItem();
|
||||||
case RS_PKT_SUBTYPE_CHAT_LOBBY_LIST: return new RsChatLobbyListItem();
|
case RS_PKT_SUBTYPE_CHAT_LOBBY_LIST: return new RsChatLobbyListItem();
|
||||||
case RS_PKT_SUBTYPE_CHAT_LOBBY_CONFIG: return new RsChatLobbyConfigItem();
|
case RS_PKT_SUBTYPE_CHAT_LOBBY_CONFIG: return new RsChatLobbyConfigItem();
|
||||||
|
case RS_PKT_SUBTYPE_SUBSCRIBED_CHAT_LOBBY_CONFIG: return new RsSubscribedChatLobbyConfigItem();
|
||||||
case RS_PKT_SUBTYPE_OUTGOING_MAP: return new PrivateOugoingMapItem();
|
case RS_PKT_SUBTYPE_OUTGOING_MAP: return new PrivateOugoingMapItem();
|
||||||
default:
|
default:
|
||||||
std::cerr << "Unknown packet type in chat!" << std::endl;
|
std::cerr << "Unknown packet type in chat!" << std::endl;
|
||||||
|
@ -172,6 +174,11 @@ void RsChatAvatarItem::serial_process(RsGenericSerializer::SerializeJob j,RsGene
|
||||||
RsTypeSerializer::serial_process(j,ctx,b,"image data") ;
|
RsTypeSerializer::serial_process(j,ctx,b,"image data") ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RsSubscribedChatLobbyConfigItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx)
|
||||||
|
{
|
||||||
|
info.serial_process(j,ctx);
|
||||||
|
}
|
||||||
|
|
||||||
void RsChatLobbyConfigItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx)
|
void RsChatLobbyConfigItem::serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx)
|
||||||
{
|
{
|
||||||
RsTypeSerializer::serial_process<uint64_t>(j,ctx,lobby_Id,"lobby_Id") ;
|
RsTypeSerializer::serial_process<uint64_t>(j,ctx,lobby_Id,"lobby_Id") ;
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
|
|
||||||
#include "serialiser/rstlvidset.h"
|
#include "serialiser/rstlvidset.h"
|
||||||
#include "serialiser/rstlvfileitem.h"
|
#include "serialiser/rstlvfileitem.h"
|
||||||
|
#include "retroshare/rsmsgs.h"
|
||||||
|
|
||||||
/* chat Flags */
|
/* chat Flags */
|
||||||
const uint32_t RS_CHAT_FLAG_PRIVATE = 0x0001;
|
const uint32_t RS_CHAT_FLAG_PRIVATE = 0x0001;
|
||||||
|
@ -82,6 +83,8 @@ const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE_DEPRECATED = 0x1A ; // to be remo
|
||||||
const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE = 0x1B ;
|
const uint8_t RS_PKT_SUBTYPE_CHAT_LOBBY_INVITE = 0x1B ;
|
||||||
const uint8_t RS_PKT_SUBTYPE_OUTGOING_MAP = 0x1C ;
|
const uint8_t RS_PKT_SUBTYPE_OUTGOING_MAP = 0x1C ;
|
||||||
|
|
||||||
|
const uint8_t RS_PKT_SUBTYPE_SUBSCRIBED_CHAT_LOBBY_CONFIG = 0x1D ;
|
||||||
|
|
||||||
typedef uint64_t ChatLobbyId ;
|
typedef uint64_t ChatLobbyId ;
|
||||||
typedef uint64_t ChatLobbyMsgId ;
|
typedef uint64_t ChatLobbyMsgId ;
|
||||||
typedef std::string ChatLobbyNickName ;
|
typedef std::string ChatLobbyNickName ;
|
||||||
|
@ -298,6 +301,19 @@ struct RsPrivateChatMsgConfigItem : RsChatItem
|
||||||
uint32_t recvTime;
|
uint32_t recvTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class RsSubscribedChatLobbyConfigItem: public RsChatItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RsSubscribedChatLobbyConfigItem() :RsChatItem(RS_PKT_SUBTYPE_SUBSCRIBED_CHAT_LOBBY_CONFIG) {}
|
||||||
|
virtual ~RsSubscribedChatLobbyConfigItem() {}
|
||||||
|
|
||||||
|
virtual void clear() { RsChatItem::clear(); info.clear(); }
|
||||||
|
|
||||||
|
void serial_process(RsGenericSerializer::SerializeJob j,RsGenericSerializer::SerializeContext& ctx);
|
||||||
|
|
||||||
|
ChatLobbyInfo info;
|
||||||
|
};
|
||||||
|
|
||||||
class RsChatLobbyConfigItem: public RsChatItem
|
class RsChatLobbyConfigItem: public RsChatItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -968,16 +968,18 @@ int p3FileDatabase::getSharedDirStatistics(const RsPeerId& pid,SharedDirStats& s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void p3FileDatabase::removeExtraFile(const RsFileHash& hash)
|
bool p3FileDatabase::removeExtraFile(const RsFileHash& hash)
|
||||||
{
|
{
|
||||||
|
bool ret = false;
|
||||||
{
|
{
|
||||||
RS_STACK_MUTEX(mFLSMtx) ;
|
RS_STACK_MUTEX(mFLSMtx) ;
|
||||||
|
|
||||||
mExtraFiles->removeExtraFile(hash);
|
ret = mExtraFiles->removeExtraFile(hash);
|
||||||
mLastExtraFilesCacheUpdate = 0 ; // forced cache reload
|
mLastExtraFilesCacheUpdate = 0 ; // forced cache reload
|
||||||
}
|
}
|
||||||
|
|
||||||
RsServer::notify()->notifyListChange(NOTIFY_LIST_DIRLIST_LOCAL, 0);
|
RsServer::notify()->notifyListChange(NOTIFY_LIST_DIRLIST_LOCAL, 0);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void p3FileDatabase::getExtraFilesDirDetails(void *ref,DirectoryStorage::EntryIndex e,DirDetails& d) const
|
void p3FileDatabase::getExtraFilesDirDetails(void *ref,DirectoryStorage::EntryIndex e,DirDetails& d) const
|
||||||
|
|
|
@ -110,7 +110,7 @@ class p3FileDatabase: public p3Service, public p3Config, public ftSearch //, pub
|
||||||
virtual int SearchBoolExp(RsRegularExpression::Expression *exp, std::list<DirDetails>& results,FileSearchFlags flags,const RsPeerId& peer_id) const ;
|
virtual int SearchBoolExp(RsRegularExpression::Expression *exp, std::list<DirDetails>& results,FileSearchFlags flags,const RsPeerId& peer_id) const ;
|
||||||
|
|
||||||
// Extra file list
|
// Extra file list
|
||||||
virtual void removeExtraFile(const RsFileHash& hash);
|
virtual bool removeExtraFile(const RsFileHash& hash);
|
||||||
|
|
||||||
// Interface for browsing dir hierarchy
|
// Interface for browsing dir hierarchy
|
||||||
//
|
//
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
* *
|
* *
|
||||||
* libretroshare: retroshare core library *
|
* libretroshare: retroshare core library *
|
||||||
* *
|
* *
|
||||||
* Copyright 2008 by Robert Fernie <retroshare@lunamutt.com> *
|
* Copyright (C) 2008 Robert Fernie <retroshare@lunamutt.com> *
|
||||||
|
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||||
* *
|
* *
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
|
@ -272,7 +273,8 @@ bool ftExtraList::cleanupEntry(std::string /*path*/, TransferRequestFlags /*flag
|
||||||
* file is removed after period.
|
* file is removed after period.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
bool ftExtraList::hashExtraFile(std::string path, uint32_t period, TransferRequestFlags flags)
|
bool ftExtraList::hashExtraFile(
|
||||||
|
std::string path, uint32_t period, TransferRequestFlags flags )
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_ELIST
|
#ifdef DEBUG_ELIST
|
||||||
std::cerr << "ftExtraList::hashExtraFile() path: " << path;
|
std::cerr << "ftExtraList::hashExtraFile() path: " << path;
|
||||||
|
@ -282,12 +284,25 @@ bool ftExtraList::hashExtraFile(std::string path, uint32_t period, TransferRequ
|
||||||
std::cerr << std::endl;
|
std::cerr << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* add into queue */
|
auto failure = [](std::string errMsg)
|
||||||
RS_STACK_MUTEX(extMutex);
|
{
|
||||||
|
RsErr() << __PRETTY_FUNCTION__ << " " << errMsg << std::endl;
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
if(!RsDirUtil::fileExists(path))
|
||||||
|
return failure("file: " + path + "not found");
|
||||||
|
|
||||||
|
if(RsDirUtil::checkDirectory(path))
|
||||||
|
return failure("Cannot add a directory: " + path + "as extra file");
|
||||||
|
|
||||||
FileDetails details(path, period, flags);
|
FileDetails details(path, period, flags);
|
||||||
details.info.age = time(NULL) + period;
|
details.info.age = static_cast<int>(time(nullptr) + period);
|
||||||
mToHash.push_back(details);
|
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(extMutex);
|
||||||
|
mToHash.push_back(details); /* add into queue */
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -678,14 +678,13 @@ bool ftServer::ExtraFileAdd(std::string fname, const RsFileHash& hash, uint64_t
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ftServer::ExtraFileRemove(const RsFileHash& hash)
|
bool ftServer::ExtraFileRemove(const RsFileHash& hash)
|
||||||
{
|
{ return mFileDatabase->removeExtraFile(hash); }
|
||||||
mFileDatabase->removeExtraFile(hash);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ftServer::ExtraFileHash(std::string localpath, uint32_t period, TransferRequestFlags flags)
|
bool ftServer::ExtraFileHash(
|
||||||
|
std::string localpath, rstime_t period, TransferRequestFlags flags )
|
||||||
{
|
{
|
||||||
return mFtExtra->hashExtraFile(localpath, period, flags);
|
return mFtExtra->hashExtraFile(
|
||||||
|
localpath, static_cast<uint32_t>(period), flags );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ftServer::ExtraFileStatus(std::string localpath, FileInfo &info)
|
bool ftServer::ExtraFileStatus(std::string localpath, FileInfo &info)
|
||||||
|
|
|
@ -181,7 +181,7 @@ public:
|
||||||
***/
|
***/
|
||||||
virtual bool ExtraFileAdd(std::string fname, const RsFileHash& hash, uint64_t size, uint32_t period, TransferRequestFlags flags);
|
virtual bool ExtraFileAdd(std::string fname, const RsFileHash& hash, uint64_t size, uint32_t period, TransferRequestFlags flags);
|
||||||
virtual bool ExtraFileRemove(const RsFileHash& hash);
|
virtual bool ExtraFileRemove(const RsFileHash& hash);
|
||||||
virtual bool ExtraFileHash(std::string localpath, uint32_t period, TransferRequestFlags flags);
|
virtual bool ExtraFileHash(std::string localpath, rstime_t period, TransferRequestFlags flags);
|
||||||
virtual bool ExtraFileStatus(std::string localpath, FileInfo &info);
|
virtual bool ExtraFileStatus(std::string localpath, FileInfo &info);
|
||||||
virtual bool ExtraFileMove(std::string fname, const RsFileHash& hash, uint64_t size, std::string destpath);
|
virtual bool ExtraFileMove(std::string fname, const RsFileHash& hash, uint64_t size, std::string destpath);
|
||||||
|
|
||||||
|
|
|
@ -100,8 +100,9 @@ void DiscPgpInfo::mergeFriendList(const std::set<PGPID> &friends)
|
||||||
p3discovery2::p3discovery2(
|
p3discovery2::p3discovery2(
|
||||||
p3PeerMgr* peerMgr, p3LinkMgr* linkMgr, p3NetMgr* netMgr,
|
p3PeerMgr* peerMgr, p3LinkMgr* linkMgr, p3NetMgr* netMgr,
|
||||||
p3ServiceControl* sc, RsGixs* gixs ) :
|
p3ServiceControl* sc, RsGixs* gixs ) :
|
||||||
p3Service(), mRsEventsHandle(0), mPeerMgr(peerMgr), mLinkMgr(linkMgr), mNetMgr(netMgr),
|
p3Service(), mRsEventsHandle(0), mPeerMgr(peerMgr), mLinkMgr(linkMgr),
|
||||||
mServiceCtrl(sc), mGixs(gixs), mDiscMtx("p3discovery2"), mLastPgpUpdate(0)
|
mNetMgr(netMgr), mServiceCtrl(sc), mGixs(gixs), mDiscMtx("p3discovery2"),
|
||||||
|
mLastPgpUpdate(0)
|
||||||
{
|
{
|
||||||
Dbg3() << __PRETTY_FUNCTION__ << std::endl;
|
Dbg3() << __PRETTY_FUNCTION__ << std::endl;
|
||||||
|
|
||||||
|
@ -111,9 +112,12 @@ p3discovery2::p3discovery2(
|
||||||
// Add self into PGP FriendList.
|
// Add self into PGP FriendList.
|
||||||
mFriendList[AuthGPG::getAuthGPG()->getGPGOwnId()] = DiscPgpInfo();
|
mFriendList[AuthGPG::getAuthGPG()->getGPGOwnId()] = DiscPgpInfo();
|
||||||
|
|
||||||
|
if(rsEvents)
|
||||||
rsEvents->registerEventsHandler(
|
rsEvents->registerEventsHandler(
|
||||||
[this](const RsEvent& event){ rsEventsHandler(event); },
|
[this](std::shared_ptr<const RsEvent> event)
|
||||||
mRsEventsHandle );
|
{
|
||||||
|
rsEventsHandler(*event);
|
||||||
|
}, mRsEventsHandle ); // mRsEventsHandle is zeroed in initializer list
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1240,12 +1244,9 @@ void p3discovery2::recvInvite(
|
||||||
std::unique_ptr<RsGossipDiscoveryInviteItem> inviteItem )
|
std::unique_ptr<RsGossipDiscoveryInviteItem> inviteItem )
|
||||||
{
|
{
|
||||||
typedef RsGossipDiscoveryFriendInviteReceivedEvent Evt_t;
|
typedef RsGossipDiscoveryFriendInviteReceivedEvent Evt_t;
|
||||||
|
if(rsEvents)
|
||||||
// Ensure rsEvents is not deleted while we use it
|
rsEvents->postEvent(
|
||||||
std::shared_ptr<RsEvents> lockedRsEvents = rsEvents;
|
std::shared_ptr<Evt_t>(new Evt_t(inviteItem->mInvite)) );
|
||||||
if(lockedRsEvents)
|
|
||||||
lockedRsEvents->postEvent(
|
|
||||||
std::unique_ptr<Evt_t>(new Evt_t(inviteItem->mInvite)) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void p3discovery2::rsEventsHandler(const RsEvent& event)
|
void p3discovery2::rsEventsHandler(const RsEvent& event)
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* *
|
* *
|
||||||
* libretroshare: retroshare core library *
|
* libretroshare: retroshare core library *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 2016-2017 Gioacchino Mazzurco <gio@eigenlab.org> *
|
* Copyright (C) 2016-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||||
* *
|
* *
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
|
@ -22,12 +22,13 @@
|
||||||
#include "util/rsdir.h"
|
#include "util/rsdir.h"
|
||||||
#include "gxstrans/p3gxstrans.h"
|
#include "gxstrans/p3gxstrans.h"
|
||||||
#include "util/stacktrace.h"
|
#include "util/stacktrace.h"
|
||||||
|
#include "util/rsdebug.h"
|
||||||
|
|
||||||
//#define DEBUG_GXSTRANS 1
|
//#define DEBUG_GXSTRANS 1
|
||||||
|
|
||||||
typedef unsigned int uint;
|
typedef unsigned int uint;
|
||||||
|
|
||||||
RsGxsTrans *rsGxsTrans = NULL ;
|
/*extern*/ RsGxsTrans* rsGxsTrans = nullptr;
|
||||||
|
|
||||||
const uint32_t p3GxsTrans::MAX_DELAY_BETWEEN_CLEANUPS = 900; // every 15 mins. Could be less.
|
const uint32_t p3GxsTrans::MAX_DELAY_BETWEEN_CLEANUPS = 900; // every 15 mins. Could be less.
|
||||||
|
|
||||||
|
@ -240,10 +241,7 @@ void p3GxsTrans::handleResponse(uint32_t token, uint32_t req_type)
|
||||||
if(!have_preferred_group)
|
if(!have_preferred_group)
|
||||||
{
|
{
|
||||||
/* This is true only at first run when we haven't received mail
|
/* This is true only at first run when we haven't received mail
|
||||||
* distribuition groups from friends
|
* distribuition groups from friends */
|
||||||
* TODO: We should check if we have some connected friend too, to
|
|
||||||
* avoid to create yet another never used mail distribution group.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef DEBUG_GXSTRANS
|
#ifdef DEBUG_GXSTRANS
|
||||||
std::cerr << "p3GxsTrans::handleResponse(...) preferredGroupId.isNu"
|
std::cerr << "p3GxsTrans::handleResponse(...) preferredGroupId.isNu"
|
||||||
|
@ -621,9 +619,10 @@ void p3GxsTrans::service_tick()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* TODO: It is a receipt for a message sent by someone else
|
/* It is a receipt for a message sent by someone else
|
||||||
* we can delete original mail from our GXS DB without
|
* we can delete original mail from our GXS DB without
|
||||||
* waiting for GXS_STORAGE_PERIOD */
|
* waiting for GXS_STORAGE_PERIOD, this has been implemented
|
||||||
|
* already by Cyril into GxsTransIntegrityCleanupThread */
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -964,7 +963,7 @@ void p3GxsTrans::locked_processOutgoingRecord(OutgoingRecord& pr)
|
||||||
{
|
{
|
||||||
case RsGxsTransEncryptionMode::CLEAR_TEXT:
|
case RsGxsTransEncryptionMode::CLEAR_TEXT:
|
||||||
{
|
{
|
||||||
std::cerr << "p3GxsTrans::sendMail(...) you are sending a mail "
|
RsWarn() << __PRETTY_FUNCTION__ << " you are sending a mail "
|
||||||
<< "without encryption, everyone can read it!"
|
<< "without encryption, everyone can read it!"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
break;
|
break;
|
||||||
|
@ -986,7 +985,7 @@ void p3GxsTrans::locked_processOutgoingRecord(OutgoingRecord& pr)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cerr << "p3GxsTrans::sendMail(...) RSA encryption failed! "
|
RsErr() << __PRETTY_FUNCTION__ << " RSA encryption failed! "
|
||||||
<< "error_status: " << encryptError << std::endl;
|
<< "error_status: " << encryptError << std::endl;
|
||||||
pr.status = GxsTransSendStatus::FAILED_ENCRYPTION;
|
pr.status = GxsTransSendStatus::FAILED_ENCRYPTION;
|
||||||
goto processingFailed;
|
goto processingFailed;
|
||||||
|
@ -994,7 +993,7 @@ void p3GxsTrans::locked_processOutgoingRecord(OutgoingRecord& pr)
|
||||||
}
|
}
|
||||||
case RsGxsTransEncryptionMode::UNDEFINED_ENCRYPTION:
|
case RsGxsTransEncryptionMode::UNDEFINED_ENCRYPTION:
|
||||||
default:
|
default:
|
||||||
std::cerr << "p3GxsTrans::sendMail(...) attempt to send mail with "
|
RsErr() << __PRETTY_FUNCTION__ << " attempt to send mail with "
|
||||||
<< "wrong EncryptionMode: "
|
<< "wrong EncryptionMode: "
|
||||||
<< static_cast<uint>(pr.mailItem.cryptoType)
|
<< static_cast<uint>(pr.mailItem.cryptoType)
|
||||||
<< " dropping mail!" << std::endl;
|
<< " dropping mail!" << std::endl;
|
||||||
|
@ -1040,7 +1039,8 @@ void p3GxsTrans::locked_processOutgoingRecord(OutgoingRecord& pr)
|
||||||
{
|
{
|
||||||
RS_STACK_MUTEX(mIngoingMutex);
|
RS_STACK_MUTEX(mIngoingMutex);
|
||||||
auto range = mIncomingQueue.equal_range(pr.mailItem.mailId);
|
auto range = mIncomingQueue.equal_range(pr.mailItem.mailId);
|
||||||
bool changed = false ;
|
bool changed = false;
|
||||||
|
bool received = false;
|
||||||
|
|
||||||
for( auto it = range.first; it != range.second; ++it)
|
for( auto it = range.first; it != range.second; ++it)
|
||||||
{
|
{
|
||||||
|
@ -1051,14 +1051,21 @@ void p3GxsTrans::locked_processOutgoingRecord(OutgoingRecord& pr)
|
||||||
mIncomingQueue.erase(it); delete rt;
|
mIncomingQueue.erase(it); delete rt;
|
||||||
pr.status = GxsTransSendStatus::RECEIPT_RECEIVED;
|
pr.status = GxsTransSendStatus::RECEIPT_RECEIVED;
|
||||||
|
|
||||||
changed = true ;
|
changed = true;
|
||||||
|
received = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!received && time(nullptr) - pr.sent_ts > GXS_STORAGE_PERIOD)
|
||||||
|
{
|
||||||
|
changed = true;
|
||||||
|
pr.status = GxsTransSendStatus::FAILED_TIMED_OUT;
|
||||||
|
}
|
||||||
|
|
||||||
if(changed)
|
if(changed)
|
||||||
IndicateConfigChanged();
|
IndicateConfigChanged();
|
||||||
|
|
||||||
// TODO: Resend message if older then treshold
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GxsTransSendStatus::RECEIPT_RECEIVED:
|
case GxsTransSendStatus::RECEIPT_RECEIVED:
|
||||||
|
@ -1067,14 +1074,13 @@ void p3GxsTrans::locked_processOutgoingRecord(OutgoingRecord& pr)
|
||||||
processingFailed:
|
processingFailed:
|
||||||
case GxsTransSendStatus::FAILED_RECEIPT_SIGNATURE:
|
case GxsTransSendStatus::FAILED_RECEIPT_SIGNATURE:
|
||||||
case GxsTransSendStatus::FAILED_ENCRYPTION:
|
case GxsTransSendStatus::FAILED_ENCRYPTION:
|
||||||
|
case GxsTransSendStatus::FAILED_TIMED_OUT:
|
||||||
default:
|
default:
|
||||||
{
|
RsErr() << __PRETTY_FUNCTION__ << " processing:" << pr.mailItem.mailId
|
||||||
std::cout << "p3GxsTrans::processRecord(" << pr.mailItem.mailId
|
<< " failed with: " << static_cast<uint>(pr.status)
|
||||||
<< ") failed with: " << static_cast<uint>(pr.status)
|
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void p3GxsTrans::notifyClientService(const OutgoingRecord& pr)
|
void p3GxsTrans::notifyClientService(const OutgoingRecord& pr)
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* *
|
* *
|
||||||
* libretroshare: retroshare core library *
|
* libretroshare: retroshare core library *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 2016-2017 Gioacchino Mazzurco <gio@eigenlab.org> *
|
* Copyright (C) 2016-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||||
* *
|
* *
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <cstdint>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ struct MsgSizeCount
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief p3GxsTrans is a mail delivery service based on GXS.
|
* @brief p3GxsTrans asyncronous redundant small mail trasport on top of GXS.
|
||||||
* p3GxsTrans is capable of asynchronous mail delivery and acknowledgement.
|
* p3GxsTrans is capable of asynchronous mail delivery and acknowledgement.
|
||||||
* p3GxsTrans is meant to be capable of multiple encryption options,
|
* p3GxsTrans is meant to be capable of multiple encryption options,
|
||||||
* @see RsGxsTransEncryptionMode at moment messages are encrypted using RSA
|
* @see RsGxsTransEncryptionMode at moment messages are encrypted using RSA
|
||||||
|
|
|
@ -289,7 +289,8 @@ JsonApiServer::JsonApiServer(uint16_t port, const std::string& bindAddress,
|
||||||
};
|
};
|
||||||
session->yield(rb::OK, headers);
|
session->yield(rb::OK, headers);
|
||||||
|
|
||||||
size_t reqSize = session->get_request()->get_header("Content-Length", 0);
|
size_t reqSize = static_cast<size_t>(
|
||||||
|
session->get_request()->get_header("Content-Length", 0) );
|
||||||
session->fetch( reqSize, [this](
|
session->fetch( reqSize, [this](
|
||||||
const std::shared_ptr<rb::Session> session,
|
const std::shared_ptr<rb::Session> session,
|
||||||
const rb::Bytes& body )
|
const rb::Bytes& body )
|
||||||
|
@ -302,8 +303,10 @@ JsonApiServer::JsonApiServer(uint16_t port, const std::string& bindAddress,
|
||||||
|
|
||||||
const std::weak_ptr<rb::Session> weakSession(session);
|
const std::weak_ptr<rb::Session> weakSession(session);
|
||||||
RsEventsHandlerId_t hId = rsEvents->generateUniqueHandlerId();
|
RsEventsHandlerId_t hId = rsEvents->generateUniqueHandlerId();
|
||||||
std::function<void(const RsEvent&)> multiCallback =
|
std::function<void(std::shared_ptr<const RsEvent>)> multiCallback =
|
||||||
[weakSession, hId](const RsEvent& event)
|
[this, weakSession, hId](std::shared_ptr<const RsEvent> event)
|
||||||
|
{
|
||||||
|
mService.schedule( [weakSession, hId, event]()
|
||||||
{
|
{
|
||||||
auto session = weakSession.lock();
|
auto session = weakSession.lock();
|
||||||
if(!session || session->is_closed())
|
if(!session || session->is_closed())
|
||||||
|
@ -315,11 +318,13 @@ JsonApiServer::JsonApiServer(uint16_t port, const std::string& bindAddress,
|
||||||
RsGenericSerializer::SerializeContext ctx;
|
RsGenericSerializer::SerializeContext ctx;
|
||||||
RsTypeSerializer::serial_process(
|
RsTypeSerializer::serial_process(
|
||||||
RsGenericSerializer::TO_JSON, ctx,
|
RsGenericSerializer::TO_JSON, ctx,
|
||||||
const_cast<RsEvent&>(event), "event" );
|
*const_cast<RsEvent*>(event.get()), "event" );
|
||||||
|
|
||||||
std::stringstream message;
|
std::stringstream message;
|
||||||
message << "data: " << compactJSON << ctx.mJson << "\n\n";
|
message << "data: " << compactJSON << ctx.mJson << "\n\n";
|
||||||
|
|
||||||
session->yield(message.str());
|
session->yield(message.str());
|
||||||
|
} );
|
||||||
};
|
};
|
||||||
|
|
||||||
bool retval = rsEvents->registerEventsHandler(multiCallback, hId);
|
bool retval = rsEvents->registerEventsHandler(multiCallback, hId);
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include "retroshare/rsids.h"
|
#include "retroshare/rsids.h"
|
||||||
#include "retroshare/rstypes.h"
|
#include "retroshare/rstypes.h"
|
||||||
|
#include "util/rsdeprecate.h"
|
||||||
|
|
||||||
/* This is a small collection of PGP functions that are widely used in libretroshare.
|
/* This is a small collection of PGP functions that are widely used in libretroshare.
|
||||||
* This interface class allows these functions to be easily mocked for testing.
|
* This interface class allows these functions to be easily mocked for testing.
|
||||||
|
@ -40,6 +41,9 @@ class PgpAuxUtils
|
||||||
|
|
||||||
virtual bool parseSignature(unsigned char *sign, unsigned int signlen, RsPgpId& issuer) const =0;
|
virtual bool parseSignature(unsigned char *sign, unsigned int signlen, RsPgpId& issuer) const =0;
|
||||||
virtual bool VerifySignBin(const void *data, uint32_t len, unsigned char *sign, unsigned int signlen, const PGPFingerprintType& withfingerprint) = 0;
|
virtual bool VerifySignBin(const void *data, uint32_t len, unsigned char *sign, unsigned int signlen, const PGPFingerprintType& withfingerprint) = 0;
|
||||||
|
|
||||||
|
/** @deprecated this method depends on retroshare-gui to work */
|
||||||
|
RS_DEPRECATED_FOR("AuthGPG::SignDataBin")
|
||||||
virtual bool askForDeferredSelfSignature(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen,int& signature_result, std::string reason) = 0;
|
virtual bool askForDeferredSelfSignature(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen,int& signature_result, std::string reason) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -311,7 +311,7 @@ bool AuthSSLimpl::active() { return init; }
|
||||||
|
|
||||||
int AuthSSLimpl::InitAuth(
|
int AuthSSLimpl::InitAuth(
|
||||||
const char* cert_file, const char* priv_key_file, const char* passwd,
|
const char* cert_file, const char* priv_key_file, const char* passwd,
|
||||||
std::string /*alternative_location_name*/ )
|
std::string locationName )
|
||||||
{
|
{
|
||||||
/* single call here si don't need to invoke mutex yet */
|
/* single call here si don't need to invoke mutex yet */
|
||||||
static int initLib = 0;
|
static int initLib = 0;
|
||||||
|
@ -520,6 +520,8 @@ int AuthSSLimpl::InitAuth(
|
||||||
else
|
else
|
||||||
std::cerr << std::endl;
|
std::cerr << std::endl;
|
||||||
|
|
||||||
|
mOwnLocationName = locationName;
|
||||||
|
|
||||||
init = 1;
|
init = 1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -575,7 +577,7 @@ const RsPeerId& AuthSSLimpl::OwnId()
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string AuthSSLimpl::getOwnLocation()
|
std::string AuthSSLimpl::getOwnLocation()
|
||||||
{ return RsX509Cert::getCertLocation(*mOwnCert); }
|
{ return mOwnLocationName; }
|
||||||
|
|
||||||
std::string AuthSSLimpl::SaveOwnCertificateToString()
|
std::string AuthSSLimpl::SaveOwnCertificateToString()
|
||||||
{ return saveX509ToPEM(mOwnCert); }
|
{ return saveX509ToPEM(mOwnCert); }
|
||||||
|
|
|
@ -98,7 +98,7 @@ public:
|
||||||
virtual bool active() = 0;
|
virtual bool active() = 0;
|
||||||
virtual int InitAuth(
|
virtual int InitAuth(
|
||||||
const char* srvr_cert, const char* priv_key, const char* passwd,
|
const char* srvr_cert, const char* priv_key, const char* passwd,
|
||||||
std::string alternative_location_name ) = 0;
|
std::string locationName ) = 0;
|
||||||
virtual bool CloseAuth() = 0;
|
virtual bool CloseAuth() = 0;
|
||||||
|
|
||||||
/*********** Overloaded Functions from p3AuthMgr **********/
|
/*********** Overloaded Functions from p3AuthMgr **********/
|
||||||
|
@ -198,7 +198,7 @@ public:
|
||||||
|
|
||||||
bool active() override;
|
bool active() override;
|
||||||
int InitAuth( const char *srvr_cert, const char *priv_key,
|
int InitAuth( const char *srvr_cert, const char *priv_key,
|
||||||
const char *passwd, std::string alternative_location_name )
|
const char *passwd, std::string locationName )
|
||||||
override;
|
override;
|
||||||
|
|
||||||
bool CloseAuth() override;
|
bool CloseAuth() override;
|
||||||
|
@ -278,6 +278,14 @@ private:
|
||||||
RsPeerId mOwnId;
|
RsPeerId mOwnId;
|
||||||
X509* mOwnCert;
|
X509* mOwnCert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the location name is included in SSL certificate it becomes a public
|
||||||
|
* information, because anyone able to open an SSL connection to the host is
|
||||||
|
* able to read it. To avoid that location name is now stored separately and
|
||||||
|
* and not included in the SSL certificate.
|
||||||
|
*/
|
||||||
|
std::string mOwnLocationName;
|
||||||
|
|
||||||
RsMutex sslMtx; /* protects all below */
|
RsMutex sslMtx; /* protects all below */
|
||||||
|
|
||||||
EVP_PKEY* mOwnPrivateKey;
|
EVP_PKEY* mOwnPrivateKey;
|
||||||
|
|
|
@ -477,11 +477,23 @@ void p3LinkMgrIMPL::tickMonitors()
|
||||||
if (peer.actions & RS_PEER_CONNECTED)
|
if (peer.actions & RS_PEER_CONNECTED)
|
||||||
{
|
{
|
||||||
p3Notify *notify = RsServer::notify();
|
p3Notify *notify = RsServer::notify();
|
||||||
|
|
||||||
if (notify)
|
if (notify)
|
||||||
{
|
{
|
||||||
|
// normally these two below should disappear: there's no notion of popup in libretroshare.
|
||||||
|
// all GUI-type display features should be chosen in NotifyQt.
|
||||||
notify->AddPopupMessage(RS_POPUP_CONNECT, peer.id.toStdString(),"", "Online: ");
|
notify->AddPopupMessage(RS_POPUP_CONNECT, peer.id.toStdString(),"", "Online: ");
|
||||||
notify->AddFeedItem(RS_FEED_ITEM_PEER_CONNECT, peer.id.toStdString());
|
notify->AddFeedItem(RS_FEED_ITEM_PEER_CONNECT, peer.id.toStdString());
|
||||||
|
|
||||||
|
notify->notifyPeerConnected(peer.id.toStdString());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (peer.actions & RS_PEER_DISCONNECTED)
|
||||||
|
{
|
||||||
|
p3Notify *notify = RsServer::notify();
|
||||||
|
|
||||||
|
if (notify)
|
||||||
|
notify->notifyPeerDisconnected(peer.id.toStdString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -217,6 +217,8 @@ void p3Notify::notifyChatLobbyEvent(uint64_t lobby_id, uint32_t event_type,const
|
||||||
void p3Notify::notifyListPreChange(int list, int type) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyListPreChange(list,type) ; }
|
void p3Notify::notifyListPreChange(int list, int type) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyListPreChange(list,type) ; }
|
||||||
void p3Notify::notifyListChange (int list, int type) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyListChange (list,type) ; }
|
void p3Notify::notifyListChange (int list, int type) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyListChange (list,type) ; }
|
||||||
|
|
||||||
|
void p3Notify::notifyPeerConnected (const std::string& peer_id) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyPeerConnected(peer_id); }
|
||||||
|
void p3Notify::notifyPeerDisconnected (const std::string& peer_id) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyPeerDisconnected(peer_id); }
|
||||||
void p3Notify::notifyErrorMsg (int list, int sev, std::string msg) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyErrorMsg(list,sev,msg) ; }
|
void p3Notify::notifyErrorMsg (int list, int sev, std::string msg) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyErrorMsg(list,sev,msg) ; }
|
||||||
void p3Notify::notifyChatMessage (const ChatMessage &msg) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyChatMessage(msg) ; }
|
void p3Notify::notifyChatMessage (const ChatMessage &msg) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyChatMessage(msg) ; }
|
||||||
void p3Notify::notifyChatStatus (const ChatId& chat_id, const std::string& status_string) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyChatStatus(chat_id,status_string) ; }
|
void p3Notify::notifyChatStatus (const ChatId& chat_id, const std::string& status_string) { FOR_ALL_NOTIFY_CLIENTS (*it)->notifyChatStatus(chat_id,status_string) ; }
|
||||||
|
|
|
@ -91,6 +91,8 @@ class p3Notify: public RsNotify
|
||||||
|
|
||||||
// Notifications of clients. Can be called from anywhere inside libretroshare.
|
// Notifications of clients. Can be called from anywhere inside libretroshare.
|
||||||
//
|
//
|
||||||
|
void notifyPeerConnected (const std::string& /* peer_id */);
|
||||||
|
void notifyPeerDisconnected (const std::string& /* peer_id */);
|
||||||
void notifyListPreChange (int /* list */, int /* type */) ;
|
void notifyListPreChange (int /* list */, int /* type */) ;
|
||||||
void notifyListChange (int /* list */, int /* type */) ;
|
void notifyListChange (int /* list */, int /* type */) ;
|
||||||
void notifyErrorMsg (int /* list */, int /* sev */, std::string /* msg */) ;
|
void notifyErrorMsg (int /* list */, int /* sev */, std::string /* msg */) ;
|
||||||
|
|
|
@ -46,19 +46,17 @@ extern std::shared_ptr<RsBroadcastDiscovery> rsBroadcastDiscovery;
|
||||||
|
|
||||||
struct RsBroadcastDiscoveryResult : RsSerializable
|
struct RsBroadcastDiscoveryResult : RsSerializable
|
||||||
{
|
{
|
||||||
PGPFingerprintType mPgpFingerprint;
|
|
||||||
RsPeerId mSslId;
|
RsPeerId mSslId;
|
||||||
std::string mProfileName;
|
std::string mProfileName;
|
||||||
RsUrl locator;
|
RsUrl mLocator;
|
||||||
|
|
||||||
/// @see RsSerializable
|
/// @see RsSerializable
|
||||||
void serial_process( RsGenericSerializer::SerializeJob j,
|
void serial_process( RsGenericSerializer::SerializeJob j,
|
||||||
RsGenericSerializer::SerializeContext& ctx) override
|
RsGenericSerializer::SerializeContext& ctx) override
|
||||||
{
|
{
|
||||||
RS_SERIAL_PROCESS(mPgpFingerprint);
|
|
||||||
RS_SERIAL_PROCESS(mSslId);
|
RS_SERIAL_PROCESS(mSslId);
|
||||||
RS_SERIAL_PROCESS(mProfileName);
|
RS_SERIAL_PROCESS(mProfileName);
|
||||||
RS_SERIAL_PROCESS(locator);
|
RS_SERIAL_PROCESS(mLocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
RsBroadcastDiscoveryResult() = default;
|
RsBroadcastDiscoveryResult() = default;
|
||||||
|
|
|
@ -37,7 +37,7 @@ class RsEvents;
|
||||||
* TODO: this should become std::weak_ptr once we have a reasonable services
|
* TODO: this should become std::weak_ptr once we have a reasonable services
|
||||||
* management.
|
* management.
|
||||||
*/
|
*/
|
||||||
extern std::shared_ptr<RsEvents> rsEvents;
|
extern RsEvents* rsEvents;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Events types.
|
* @brief Events types.
|
||||||
|
@ -116,21 +116,20 @@ public:
|
||||||
* @return False on error, true otherwise.
|
* @return False on error, true otherwise.
|
||||||
*/
|
*/
|
||||||
virtual bool postEvent(
|
virtual bool postEvent(
|
||||||
std::unique_ptr<RsEvent> event,
|
std::shared_ptr<const RsEvent> event,
|
||||||
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
|
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
|
||||||
) = 0;
|
) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Send event directly to handlers. Blocking API
|
* @brief Send event directly to handlers. Blocking API
|
||||||
* The handlers get exectuded on the caller thread, ensuring the function
|
* The handlers get exectuded on the caller thread.
|
||||||
* returns only after the event has been handled.
|
|
||||||
* @param[in] event
|
* @param[in] event
|
||||||
* @param[out] errorMessage Optional storage for error messsage, meaningful
|
* @param[out] errorMessage Optional storage for error messsage, meaningful
|
||||||
* only on failure.
|
* only on failure.
|
||||||
* @return False on error, true otherwise.
|
* @return False on error, true otherwise.
|
||||||
*/
|
*/
|
||||||
virtual bool sendEvent(
|
virtual bool sendEvent(
|
||||||
const RsEvent& event,
|
std::shared_ptr<const RsEvent> event,
|
||||||
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
|
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
|
||||||
) = 0;
|
) = 0;
|
||||||
|
|
||||||
|
@ -155,7 +154,7 @@ public:
|
||||||
* @return False on error, true otherwise.
|
* @return False on error, true otherwise.
|
||||||
*/
|
*/
|
||||||
virtual bool registerEventsHandler(
|
virtual bool registerEventsHandler(
|
||||||
std::function<void(const RsEvent&)> multiCallback,
|
std::function<void(std::shared_ptr<const RsEvent>)> multiCallback,
|
||||||
RsEventsHandlerId_t& hId = RS_DEFAULT_STORAGE_PARAM(RsEventsHandlerId_t, 0)
|
RsEventsHandlerId_t& hId = RS_DEFAULT_STORAGE_PARAM(RsEventsHandlerId_t, 0)
|
||||||
) = 0;
|
) = 0;
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
* *
|
* *
|
||||||
* libretroshare: retroshare core library *
|
* libretroshare: retroshare core library *
|
||||||
* *
|
* *
|
||||||
* Copyright 2008-2008 by Robert Fernie <retroshare@lunamutt.com> *
|
* Copyright (C) 2008 Robert Fernie <retroshare@lunamutt.com> *
|
||||||
|
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||||
* *
|
* *
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
|
@ -208,7 +209,7 @@ public:
|
||||||
virtual ~RsFiles() {}
|
virtual ~RsFiles() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides file data for the gui, media streaming or rpc clients.
|
* @brief Provides file data for the gui, media streaming or rpc clients.
|
||||||
* It may return unverified chunks. This allows streaming without having to
|
* It may return unverified chunks. This allows streaming without having to
|
||||||
* wait for hashes or completion of the file.
|
* wait for hashes or completion of the file.
|
||||||
* This function returns an unspecified amount of bytes. Either as much data
|
* This function returns an unspecified amount of bytes. Either as much data
|
||||||
|
@ -224,7 +225,7 @@ public:
|
||||||
* @param[in] offset where the desired block starts
|
* @param[in] offset where the desired block starts
|
||||||
* @param[inout] requested_size size of pre-allocated data. Will be updated
|
* @param[inout] requested_size size of pre-allocated data. Will be updated
|
||||||
* by the function.
|
* by the function.
|
||||||
* @param data pre-allocated memory chunk of size 'requested_size' by the
|
* @param[out] data pre-allocated memory chunk of size 'requested_size' by the
|
||||||
* client
|
* client
|
||||||
* @return Returns false in case
|
* @return Returns false in case
|
||||||
* - the files is not available on the local node
|
* - the files is not available on the local node
|
||||||
|
@ -422,22 +423,47 @@ public:
|
||||||
* @brief Get details about the upload with given hash
|
* @brief Get details about the upload with given hash
|
||||||
* @jsonapi{development}
|
* @jsonapi{development}
|
||||||
* @param[in] hash file identifier
|
* @param[in] hash file identifier
|
||||||
* @param[in] peer_id peer identifier
|
* @param[in] peerId peer identifier
|
||||||
* @param[out] map storage for chunk info
|
* @param[out] map storage for chunk info
|
||||||
* @return true if file found, false otherwise
|
* @return true if file found, false otherwise
|
||||||
*/
|
*/
|
||||||
virtual bool FileUploadChunksDetails(
|
virtual bool FileUploadChunksDetails(
|
||||||
const RsFileHash& hash, const RsPeerId& peer_id,
|
const RsFileHash& hash, const RsPeerId& peerId,
|
||||||
CompressedChunkMap& map ) = 0;
|
CompressedChunkMap& map ) = 0;
|
||||||
|
|
||||||
/***
|
/**
|
||||||
* Extra List Access
|
* @brief Remove file from extra fila shared list
|
||||||
***/
|
* @jsonapi{development}
|
||||||
//virtual bool ExtraFileAdd(std::string fname, std::string hash, uint64_t size, uint32_t period, TransferRequestFlags flags) = 0;
|
* @param[in] hash hash of the file to remove
|
||||||
|
* @return return false on error, true otherwise
|
||||||
|
*/
|
||||||
virtual bool ExtraFileRemove(const RsFileHash& hash) = 0;
|
virtual bool ExtraFileRemove(const RsFileHash& hash) = 0;
|
||||||
virtual bool ExtraFileHash(std::string localpath, uint32_t period, TransferRequestFlags flags) = 0;
|
|
||||||
|
/**
|
||||||
|
* @brief Add file to extra shared file list
|
||||||
|
* @jsonapi{development}
|
||||||
|
* @param[in] localpath path of the file
|
||||||
|
* @param[in] period how much time the file will be kept in extra list in
|
||||||
|
* seconds
|
||||||
|
* @param[in] flags sharing policy flags ex: RS_FILE_REQ_ANONYMOUS_ROUTING
|
||||||
|
* @return false on error, true otherwise
|
||||||
|
*/
|
||||||
|
virtual bool ExtraFileHash(
|
||||||
|
std::string localpath, rstime_t period, TransferRequestFlags flags
|
||||||
|
) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get extra file information
|
||||||
|
* @jsonapi{development}
|
||||||
|
* @param[in] localpath path of the file
|
||||||
|
* @param[out] info storage for the file information
|
||||||
|
* @return false on error, true otherwise
|
||||||
|
*/
|
||||||
virtual bool ExtraFileStatus(std::string localpath, FileInfo &info) = 0;
|
virtual bool ExtraFileStatus(std::string localpath, FileInfo &info) = 0;
|
||||||
virtual bool ExtraFileMove(std::string fname, const RsFileHash& hash, uint64_t size, std::string destpath) = 0;
|
|
||||||
|
virtual bool ExtraFileMove(
|
||||||
|
std::string fname, const RsFileHash& hash, uint64_t size,
|
||||||
|
std::string destpath ) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Request directory details, subsequent multiple call may be used to
|
* @brief Request directory details, subsequent multiple call may be used to
|
||||||
|
|
|
@ -1,6 +1,37 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* libretroshare/src/retroshare: rsflags.h *
|
||||||
|
* *
|
||||||
|
* libretroshare: retroshare core library *
|
||||||
|
* *
|
||||||
|
* Copyright 2012-2019 by Retroshare Team <contact@retroshare.cc> *
|
||||||
|
* *
|
||||||
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
|
* published by the Free Software Foundation, either version 3 of the *
|
||||||
|
* License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU Lesser General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License *
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
*******************************************************************************/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <cstdint>
|
||||||
|
|
||||||
|
/* G10h4ck: TODO we should redefine flags in a way that the flag declaration and
|
||||||
|
* the flags values (bit fields) would be strongly logically linked.
|
||||||
|
* A possible way is to take an enum class containing the names of each
|
||||||
|
* bitfield and corresponding value as template parameter, this way would also
|
||||||
|
* avoid the need of dumb template parameter that is used only to make the
|
||||||
|
* types incompatible but that doesn't help finding what are the possible values
|
||||||
|
* for a kind of flag. Another appealing approach seems the first one described
|
||||||
|
* here https://softwareengineering.stackexchange.com/questions/194412/using-scoped-enums-for-bit-flags-in-c
|
||||||
|
* a few simple macros could be used instead of the template class */
|
||||||
|
|
||||||
// This class provides a representation for flags that can be combined with bitwise
|
// This class provides a representation for flags that can be combined with bitwise
|
||||||
// operations. However, because the class is templated with an id, it's not possible to
|
// operations. However, because the class is templated with an id, it's not possible to
|
||||||
|
|
|
@ -142,10 +142,13 @@ public:
|
||||||
* posted
|
* posted
|
||||||
* @param[in] threadId Id of the post (that is a thread) in the channel
|
* @param[in] threadId Id of the post (that is a thread) in the channel
|
||||||
* where the comment is placed
|
* where the comment is placed
|
||||||
|
* @param[in] comment UTF-8 string containing the comment itself
|
||||||
|
* @param[in] authorId Id of the author of the comment
|
||||||
* @param[in] parentId Id of the parent of the comment that is either a
|
* @param[in] parentId Id of the parent of the comment that is either a
|
||||||
* channel post Id or the Id of another comment.
|
* channel post Id or the Id of another comment.
|
||||||
* @param[in] authorId Id of the author of the comment
|
* @param[in] origCommentId If this is supposed to replace an already
|
||||||
* @param[in] comment UTF-8 string containing the comment itself
|
* existent comment, the id of the old post.
|
||||||
|
* If left blank a new post will be created.
|
||||||
* @param[out] commentMessageId Optional storage for the id of the comment
|
* @param[out] commentMessageId Optional storage for the id of the comment
|
||||||
* that was created, meaningful only on success.
|
* that was created, meaningful only on success.
|
||||||
* @param[out] errorMessage Optional storage for error message, meaningful
|
* @param[out] errorMessage Optional storage for error message, meaningful
|
||||||
|
@ -155,9 +158,10 @@ public:
|
||||||
virtual bool createCommentV2(
|
virtual bool createCommentV2(
|
||||||
const RsGxsGroupId& channelId,
|
const RsGxsGroupId& channelId,
|
||||||
const RsGxsMessageId& threadId,
|
const RsGxsMessageId& threadId,
|
||||||
const RsGxsMessageId& parentId,
|
|
||||||
const RsGxsId& authorId,
|
|
||||||
const std::string& comment,
|
const std::string& comment,
|
||||||
|
const RsGxsId& authorId,
|
||||||
|
const RsGxsMessageId& parentId = RsGxsMessageId(),
|
||||||
|
const RsGxsMessageId& origCommentId = RsGxsMessageId(),
|
||||||
RsGxsMessageId& commentMessageId = RS_DEFAULT_STORAGE_PARAM(RsGxsMessageId),
|
RsGxsMessageId& commentMessageId = RS_DEFAULT_STORAGE_PARAM(RsGxsMessageId),
|
||||||
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
|
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
|
||||||
) = 0;
|
) = 0;
|
||||||
|
|
|
@ -142,19 +142,6 @@ struct RsGxsComment : RsSerializable
|
||||||
RS_SERIAL_PROCESS(mOwnVote);
|
RS_SERIAL_PROCESS(mOwnVote);
|
||||||
RS_SERIAL_PROCESS(mVotes);
|
RS_SERIAL_PROCESS(mVotes);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::ostream &print(std::ostream &out, std::string indent = "", std::string varName = "") const {
|
|
||||||
out << indent << varName << " of RsGxsComment Values ###################" << std::endl;
|
|
||||||
mMeta.print(out, indent + " ", "mMeta");
|
|
||||||
out << indent << " mComment: " << mComment << std::endl;
|
|
||||||
out << indent << " mUpVotes: " << mUpVotes << std::endl;
|
|
||||||
out << indent << " mDownVotes: " << mDownVotes << std::endl;
|
|
||||||
out << indent << " mScore: " << mScore << std::endl;
|
|
||||||
out << indent << " mOwnVote: " << mOwnVote << std::endl;
|
|
||||||
out << indent << " mVotes.size(): " << mVotes.size() << std::endl;
|
|
||||||
out << indent << "######################################################" << std::endl;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -52,12 +52,11 @@ namespace GXS_SERV {
|
||||||
static const uint32_t FLAG_AUTHOR_AUTHENTICATION_MASK = 0x0000ff00;
|
static const uint32_t FLAG_AUTHOR_AUTHENTICATION_MASK = 0x0000ff00;
|
||||||
static const uint32_t FLAG_AUTHOR_AUTHENTICATION_NONE = 0x00000000;
|
static const uint32_t FLAG_AUTHOR_AUTHENTICATION_NONE = 0x00000000;
|
||||||
static const uint32_t FLAG_AUTHOR_AUTHENTICATION_GPG = 0x00000100; // Anti-spam feature. Allows to ask higher reputation to anonymous IDs
|
static const uint32_t FLAG_AUTHOR_AUTHENTICATION_GPG = 0x00000100; // Anti-spam feature. Allows to ask higher reputation to anonymous IDs
|
||||||
static const uint32_t FLAG_AUTHOR_AUTHENTICATION_REQUIRED = 0x00000200; // unused
|
static const uint32_t FLAG_AUTHOR_AUTHENTICATION_REQUIRED = 0x00000200;
|
||||||
static const uint32_t FLAG_AUTHOR_AUTHENTICATION_IFNOPUBSIGN = 0x00000400; // ???
|
static const uint32_t FLAG_AUTHOR_AUTHENTICATION_IFNOPUBSIGN = 0x00000400; // ???
|
||||||
static const uint32_t FLAG_AUTHOR_AUTHENTICATION_TRACK_MESSAGES = 0x00000800; // not used anymore
|
static const uint32_t FLAG_AUTHOR_AUTHENTICATION_TRACK_MESSAGES = 0x00000800; // not used anymore
|
||||||
static const uint32_t FLAG_AUTHOR_AUTHENTICATION_GPG_KNOWN = 0x00001000; // Anti-spam feature. Allows to ask higher reputation to unknown IDs and anonymous IDs
|
static const uint32_t FLAG_AUTHOR_AUTHENTICATION_GPG_KNOWN = 0x00001000; // Anti-spam feature. Allows to ask higher reputation to unknown IDs and anonymous IDs
|
||||||
|
|
||||||
// These are *not used*
|
|
||||||
static const uint32_t FLAG_GROUP_SIGN_PUBLISH_MASK = 0x000000ff;
|
static const uint32_t FLAG_GROUP_SIGN_PUBLISH_MASK = 0x000000ff;
|
||||||
static const uint32_t FLAG_GROUP_SIGN_PUBLISH_ENCRYPTED = 0x00000001;
|
static const uint32_t FLAG_GROUP_SIGN_PUBLISH_ENCRYPTED = 0x00000001;
|
||||||
static const uint32_t FLAG_GROUP_SIGN_PUBLISH_ALLSIGNED = 0x00000002; // unused
|
static const uint32_t FLAG_GROUP_SIGN_PUBLISH_ALLSIGNED = 0x00000002; // unused
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
* *
|
* *
|
||||||
* libretroshare: retroshare core library *
|
* libretroshare: retroshare core library *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 2012 by Robert Fernie <retroshare@lunamutt.com> *
|
* Copyright (C) 2012-2014 Robert Fernie <retroshare@lunamutt.com> *
|
||||||
* Copyright (C) 2018 Gioacchino Mazzurco <gio@eigenlab.org> *
|
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||||
* *
|
* *
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
|
@ -30,9 +30,9 @@
|
||||||
#include "retroshare/rsgxsifacehelper.h"
|
#include "retroshare/rsgxsifacehelper.h"
|
||||||
#include "serialiser/rstlvidset.h"
|
#include "serialiser/rstlvidset.h"
|
||||||
#include "serialiser/rsserializable.h"
|
#include "serialiser/rsserializable.h"
|
||||||
|
#include "retroshare/rsgxscircles.h"
|
||||||
|
|
||||||
|
|
||||||
/* The Main Interface Class - for information about your Peers */
|
|
||||||
class RsGxsForums;
|
class RsGxsForums;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,6 +45,8 @@ extern RsGxsForums* rsGxsForums;
|
||||||
/** Forum Service message flags, to be used in RsMsgMetaData::mMsgFlags
|
/** Forum Service message flags, to be used in RsMsgMetaData::mMsgFlags
|
||||||
* Gxs imposes to use the first two bytes (lower bytes) of mMsgFlags for
|
* Gxs imposes to use the first two bytes (lower bytes) of mMsgFlags for
|
||||||
* private forum flags, the upper bytes being used for internal GXS stuff.
|
* private forum flags, the upper bytes being used for internal GXS stuff.
|
||||||
|
* @todo mixing service level flags and GXS level flag into the same member is
|
||||||
|
* prone to confusion, use separated members for those things
|
||||||
*/
|
*/
|
||||||
static const uint32_t RS_GXS_FORUM_MSG_FLAGS_MASK = 0x0000000f;
|
static const uint32_t RS_GXS_FORUM_MSG_FLAGS_MASK = 0x0000000f;
|
||||||
static const uint32_t RS_GXS_FORUM_MSG_FLAGS_MODERATED = 0x00000001;
|
static const uint32_t RS_GXS_FORUM_MSG_FLAGS_MODERATED = 0x00000001;
|
||||||
|
@ -54,46 +56,52 @@ static const uint32_t RS_GXS_FORUM_MSG_FLAGS_MODERATED = 0x00000001;
|
||||||
|
|
||||||
struct RsGxsForumGroup : RsSerializable
|
struct RsGxsForumGroup : RsSerializable
|
||||||
{
|
{
|
||||||
virtual ~RsGxsForumGroup() {}
|
/** Forum GXS metadata */
|
||||||
|
|
||||||
RsGroupMetaData mMeta;
|
RsGroupMetaData mMeta;
|
||||||
|
|
||||||
|
/** @brief Forum desciption */
|
||||||
std::string mDescription;
|
std::string mDescription;
|
||||||
|
|
||||||
/* What's below is optional, and handled by the serialiser
|
/** @brief List of forum moderators ids
|
||||||
* TODO: run away from TLV old serializables as those types are opaque to
|
* @todo run away from TLV old serializables as those types are opaque to
|
||||||
* JSON API! */
|
* JSON API! */
|
||||||
RsTlvGxsIdSet mAdminList;
|
RsTlvGxsIdSet mAdminList;
|
||||||
|
|
||||||
|
/** @brief List of forum pinned posts, those are usually displayed on top
|
||||||
|
* @todo run away from TLV old serializables as those types are opaque to
|
||||||
|
* JSON API! */
|
||||||
RsTlvGxsMsgIdSet mPinnedPosts;
|
RsTlvGxsMsgIdSet mPinnedPosts;
|
||||||
|
|
||||||
/// @see RsSerializable
|
/// @see RsSerializable
|
||||||
virtual void serial_process( RsGenericSerializer::SerializeJob j,
|
virtual void serial_process(
|
||||||
RsGenericSerializer::SerializeContext& ctx )
|
RsGenericSerializer::SerializeJob j,
|
||||||
{
|
RsGenericSerializer::SerializeContext& ctx ) override;
|
||||||
RS_SERIAL_PROCESS(mMeta);
|
|
||||||
RS_SERIAL_PROCESS(mDescription);
|
|
||||||
RS_SERIAL_PROCESS(mAdminList);
|
|
||||||
RS_SERIAL_PROCESS(mPinnedPosts);
|
|
||||||
}
|
|
||||||
|
|
||||||
// utility functions
|
~RsGxsForumGroup() override;
|
||||||
|
|
||||||
bool canEditPosts(const RsGxsId& id) const { return mAdminList.ids.find(id) != mAdminList.ids.end() || id == mMeta.mAuthorId; }
|
/* G10h4ck: We should avoid actual methods in this contexts as they are
|
||||||
|
* invisible to JSON API */
|
||||||
|
bool canEditPosts(const RsGxsId& id) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RsGxsForumMsg : RsSerializable
|
struct RsGxsForumMsg : RsSerializable
|
||||||
{
|
{
|
||||||
virtual ~RsGxsForumMsg() {}
|
/** @brief Forum post GXS metadata */
|
||||||
|
|
||||||
RsMsgMetaData mMeta;
|
RsMsgMetaData mMeta;
|
||||||
|
|
||||||
|
/** @brief Forum post content */
|
||||||
std::string mMsg;
|
std::string mMsg;
|
||||||
|
|
||||||
/// @see RsSerializable
|
/// @see RsSerializable
|
||||||
virtual void serial_process( RsGenericSerializer::SerializeJob j,
|
virtual void serial_process(
|
||||||
RsGenericSerializer::SerializeContext& ctx )
|
RsGenericSerializer::SerializeJob j,
|
||||||
|
RsGenericSerializer::SerializeContext& ctx ) override
|
||||||
{
|
{
|
||||||
RS_SERIAL_PROCESS(mMeta);
|
RS_SERIAL_PROCESS(mMeta);
|
||||||
RS_SERIAL_PROCESS(mMsg);
|
RS_SERIAL_PROCESS(mMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~RsGxsForumMsg() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -101,23 +109,67 @@ class RsGxsForums: public RsGxsIfaceHelper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit RsGxsForums(RsGxsIface& gxs) : RsGxsIfaceHelper(gxs) {}
|
explicit RsGxsForums(RsGxsIface& gxs) : RsGxsIfaceHelper(gxs) {}
|
||||||
virtual ~RsGxsForums() {}
|
virtual ~RsGxsForums();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create forum. Blocking API.
|
* @brief Create forum.
|
||||||
* @jsonapi{development}
|
* @jsonapi{development}
|
||||||
* @param[inout] forum Forum data (name, description...)
|
* @param[in] name Name of the forum
|
||||||
* @return false on error, true otherwise
|
* @param[in] description Optional description of the forum
|
||||||
|
* @param[in] authorId Optional id of the froum owner author
|
||||||
|
* @param[in] moderatorsIds Optional list of forum moderators
|
||||||
|
* @param[in] circleType Optional visibility rule, default public.
|
||||||
|
* @param[in] circleId If the forum is not public specify the id of
|
||||||
|
* the circle who can see the forum. Depending on
|
||||||
|
* the value you pass for circleType this should
|
||||||
|
* be a circle if EXTERNAL is passed, a local
|
||||||
|
* friends group id if NODES_GROUP is passed,
|
||||||
|
* empty otherwise.
|
||||||
|
* @param[out] forumId Optional storage for the id of the created
|
||||||
|
* forum, meaningful only if creations succeeds.
|
||||||
|
* @param[out] errorMessage Optional storage for error messsage, meaningful
|
||||||
|
* only if creation fail.
|
||||||
|
* @return False on error, true otherwise.
|
||||||
*/
|
*/
|
||||||
virtual bool createForum(RsGxsForumGroup& forum) = 0;
|
virtual bool createForumV2(
|
||||||
|
const std::string& name, const std::string& description,
|
||||||
|
const RsGxsId& authorId = RsGxsId(),
|
||||||
|
const std::set<RsGxsId>& moderatorsIds = std::set<RsGxsId>(),
|
||||||
|
RsGxsCircleType circleType = RsGxsCircleType::PUBLIC,
|
||||||
|
const RsGxsCircleId& circleId = RsGxsCircleId(),
|
||||||
|
RsGxsGroupId& forumId = RS_DEFAULT_STORAGE_PARAM(RsGxsGroupId),
|
||||||
|
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
|
||||||
|
) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create forum message. Blocking API.
|
* @brief Create a post on the given forum.
|
||||||
* @jsonapi{development}
|
* @jsonapi{development}
|
||||||
* @param[inout] message
|
* @param[in] forumId Id of the forum in which the post is to be
|
||||||
|
* submitted
|
||||||
|
* @param[in] title UTF-8 string containing the title of the post
|
||||||
|
* @param[in] mBody UTF-8 string containing the text of the post
|
||||||
|
* @param[in] authorId Id of the author of the comment
|
||||||
|
* @param[in] parentId Optional Id of the parent post if this post is a
|
||||||
|
* reply to another post, empty otherwise.
|
||||||
|
* @param[in] origPostId If this is supposed to replace an already
|
||||||
|
* existent post, the id of the old post.
|
||||||
|
* If left blank a new post will be created.
|
||||||
|
* @param[out] postMsgId Optional storage for the id of the created,
|
||||||
|
* meaningful only on success.
|
||||||
|
* @param[out] errorMessage Optional storage for error message, meaningful
|
||||||
|
* only on failure.
|
||||||
* @return false on error, true otherwise
|
* @return false on error, true otherwise
|
||||||
*/
|
*/
|
||||||
virtual bool createMessage(RsGxsForumMsg& message) = 0;
|
virtual bool createPost(
|
||||||
|
const RsGxsGroupId& forumId,
|
||||||
|
const std::string& title,
|
||||||
|
const std::string& mBody,
|
||||||
|
const RsGxsId& authorId,
|
||||||
|
const RsGxsMessageId& parentId = RsGxsMessageId(),
|
||||||
|
const RsGxsMessageId& origPostId = RsGxsMessageId(),
|
||||||
|
RsGxsMessageId& postMsgId = RS_DEFAULT_STORAGE_PARAM(RsGxsMessageId),
|
||||||
|
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
|
||||||
|
) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Edit forum details.
|
* @brief Edit forum details.
|
||||||
|
@ -167,7 +219,7 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual bool getForumContent(
|
virtual bool getForumContent(
|
||||||
const RsGxsGroupId& forumId,
|
const RsGxsGroupId& forumId,
|
||||||
std::set<RsGxsMessageId>& msgsIds,
|
const std::set<RsGxsMessageId>& msgsIds,
|
||||||
std::vector<RsGxsForumMsg>& msgs) = 0;
|
std::vector<RsGxsForumMsg>& msgs) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -189,6 +241,26 @@ public:
|
||||||
virtual bool subscribeToForum( const RsGxsGroupId& forumId,
|
virtual bool subscribeToForum( const RsGxsGroupId& forumId,
|
||||||
bool subscribe ) = 0;
|
bool subscribe ) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create forum. Blocking API.
|
||||||
|
* @jsonapi{development}
|
||||||
|
* @param[inout] forum Forum data (name, description...)
|
||||||
|
* @return false on error, true otherwise
|
||||||
|
* @deprecated @see createForumV2
|
||||||
|
*/
|
||||||
|
RS_DEPRECATED_FOR(createForumV2)
|
||||||
|
virtual bool createForum(RsGxsForumGroup& forum) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create forum message. Blocking API.
|
||||||
|
* @jsonapi{development}
|
||||||
|
* @param[inout] message
|
||||||
|
* @return false on error, true otherwise
|
||||||
|
* @deprecated @see createPost
|
||||||
|
*/
|
||||||
|
RS_DEPRECATED_FOR(createPost)
|
||||||
|
virtual bool createMessage(RsGxsForumMsg& message) = 0;
|
||||||
|
|
||||||
/* Specific Service Data */
|
/* Specific Service Data */
|
||||||
RS_DEPRECATED_FOR("getForumsSummaries, getForumsInfo")
|
RS_DEPRECATED_FOR("getForumsSummaries, getForumsInfo")
|
||||||
virtual bool getGroupData(const uint32_t &token, std::vector<RsGxsForumGroup> &groups) = 0;
|
virtual bool getGroupData(const uint32_t &token, std::vector<RsGxsForumGroup> &groups) = 0;
|
||||||
|
@ -203,4 +275,3 @@ public:
|
||||||
RS_DEPRECATED_FOR(editForum)
|
RS_DEPRECATED_FOR(editForum)
|
||||||
virtual bool updateGroup(uint32_t &token, RsGxsForumGroup &group) = 0;
|
virtual bool updateGroup(uint32_t &token, RsGxsForumGroup &group) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -91,6 +91,7 @@ struct RsGxsChanges : RsEvent
|
||||||
void serial_process( RsGenericSerializer::SerializeJob j,
|
void serial_process( RsGenericSerializer::SerializeJob j,
|
||||||
RsGenericSerializer::SerializeContext& ctx) override
|
RsGenericSerializer::SerializeContext& ctx) override
|
||||||
{
|
{
|
||||||
|
RsEvent::serial_process(j,ctx);
|
||||||
RS_SERIAL_PROCESS(mServiceType);
|
RS_SERIAL_PROCESS(mServiceType);
|
||||||
RS_SERIAL_PROCESS(mMsgs);
|
RS_SERIAL_PROCESS(mMsgs);
|
||||||
RS_SERIAL_PROCESS(mMsgsMeta);
|
RS_SERIAL_PROCESS(mMsgsMeta);
|
||||||
|
@ -99,7 +100,7 @@ struct RsGxsChanges : RsEvent
|
||||||
RS_SERIAL_PROCESS(mDistantSearchReqs);
|
RS_SERIAL_PROCESS(mDistantSearchReqs);
|
||||||
}
|
}
|
||||||
|
|
||||||
RsTokenService* mService; // Weak pointer, not serialized
|
RsTokenService* mService; /// Weak pointer, not serialized
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
|
@ -140,13 +140,19 @@ struct RsMsgMetaData : RsSerializable
|
||||||
std::string mMsgName;
|
std::string mMsgName;
|
||||||
rstime_t mPublishTs;
|
rstime_t mPublishTs;
|
||||||
|
|
||||||
/// the lower 16 bits for service, upper 16 bits for GXS
|
/** the lower 16 bits for service, upper 16 bits for GXS
|
||||||
|
* @todo mixing service level flags and GXS level flag into the same member
|
||||||
|
* is prone to confusion, use separated members for those things, this could
|
||||||
|
* be done without breaking network retro-compatibility */
|
||||||
uint32_t mMsgFlags;
|
uint32_t mMsgFlags;
|
||||||
|
|
||||||
// BELOW HERE IS LOCAL DATA, THAT IS NOT FROM MSG.
|
// BELOW HERE IS LOCAL DATA, THAT IS NOT FROM MSG.
|
||||||
// normally READ / UNREAD flags. LOCAL Data.
|
// normally READ / UNREAD flags. LOCAL Data.
|
||||||
|
|
||||||
/// the first 16 bits for service, last 16 for GXS
|
/** the first 16 bits for service, last 16 for GXS
|
||||||
|
* @todo mixing service level flags and GXS level flag into the same member
|
||||||
|
* is prone to confusion, use separated members for those things, this could
|
||||||
|
* be done without breaking network retro-compatibility */
|
||||||
uint32_t mMsgStatus;
|
uint32_t mMsgStatus;
|
||||||
|
|
||||||
rstime_t mChildTs;
|
rstime_t mChildTs;
|
||||||
|
@ -169,25 +175,6 @@ struct RsMsgMetaData : RsSerializable
|
||||||
RS_SERIAL_PROCESS(mChildTs);
|
RS_SERIAL_PROCESS(mChildTs);
|
||||||
RS_SERIAL_PROCESS(mServiceString);
|
RS_SERIAL_PROCESS(mServiceString);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::ostream &print(std::ostream &out, std::string indent = "", std::string varName = "") const {
|
|
||||||
out
|
|
||||||
<< indent << varName << " of RsMsgMetaData Values ###################" << std::endl
|
|
||||||
<< indent << " mGroupId: " << mGroupId.toStdString() << std::endl
|
|
||||||
<< indent << " mMsgId: " << mMsgId.toStdString() << std::endl
|
|
||||||
<< indent << " mThreadId: " << mThreadId.toStdString() << std::endl
|
|
||||||
<< indent << " mParentId: " << mParentId.toStdString() << std::endl
|
|
||||||
<< indent << " mOrigMsgId: " << mOrigMsgId.toStdString() << std::endl
|
|
||||||
<< indent << " mAuthorId: " << mAuthorId.toStdString() << std::endl
|
|
||||||
<< indent << " mMsgName: " << mMsgName << std::endl
|
|
||||||
<< indent << " mPublishTs: " << mPublishTs << std::endl
|
|
||||||
<< indent << " mMsgFlags: " << std::hex << mMsgFlags << std::dec << std::endl
|
|
||||||
<< indent << " mMsgStatus: " << std::hex << mMsgStatus << std::dec << std::endl
|
|
||||||
<< indent << " mChildTs: " << mChildTs << std::endl
|
|
||||||
<< indent << " mServiceString: " << mServiceString << std::endl
|
|
||||||
<< indent << "######################################################" << std::endl;
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class GxsGroupStatistic
|
class GxsGroupStatistic
|
||||||
|
|
|
@ -1,3 +1,23 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* libretroshare/src/retroshare: rsgxstrans.h *
|
||||||
|
* *
|
||||||
|
* libretroshare: retroshare core library *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2016-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||||
|
* *
|
||||||
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU Lesser General Public License version 3 as *
|
||||||
|
* published by the Free Software Foundation. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU Lesser General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License *
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
*******************************************************************************/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "retroshare/rstokenservice.h"
|
#include "retroshare/rstokenservice.h"
|
||||||
|
@ -41,7 +61,8 @@ enum class GxsTransSendStatus : uint8_t
|
||||||
/// Records with status >= RECEIPT_RECEIVED get deleted
|
/// Records with status >= RECEIPT_RECEIVED get deleted
|
||||||
RECEIPT_RECEIVED = 0x0a,
|
RECEIPT_RECEIVED = 0x0a,
|
||||||
FAILED_RECEIPT_SIGNATURE = 0xf0,
|
FAILED_RECEIPT_SIGNATURE = 0xf0,
|
||||||
FAILED_ENCRYPTION = 0xf1
|
FAILED_ENCRYPTION = 0xf1,
|
||||||
|
FAILED_TIMED_OUT = 0xf2
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef uint64_t RsGxsTransId;
|
typedef uint64_t RsGxsTransId;
|
||||||
|
@ -79,6 +100,7 @@ struct RsGxsTransOutgoingRecord
|
||||||
RsGxsGroupId group_id ;
|
RsGxsGroupId group_id ;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// RetroShare GxsTrans asyncronous redundant small mail trasport on top of GXS
|
||||||
class RsGxsTrans: public RsGxsIfaceHelper
|
class RsGxsTrans: public RsGxsIfaceHelper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -244,14 +244,22 @@ struct RsIdentityUsage : RsSerializable
|
||||||
CIRCLE_MEMBERSHIP_CHECK = 0x13
|
CIRCLE_MEMBERSHIP_CHECK = 0x13
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
RS_DEPRECATED
|
||||||
RsIdentityUsage( uint16_t service, const RsIdentityUsage::UsageCode& code,
|
RsIdentityUsage( uint16_t service, const RsIdentityUsage::UsageCode& code,
|
||||||
const RsGxsGroupId& gid = RsGxsGroupId(),
|
const RsGxsGroupId& gid = RsGxsGroupId(),
|
||||||
const RsGxsMessageId& mid = RsGxsMessageId(),
|
const RsGxsMessageId& mid = RsGxsMessageId(),
|
||||||
uint64_t additional_id=0,
|
uint64_t additional_id=0,
|
||||||
const std::string& comment = std::string() );
|
const std::string& comment = std::string() );
|
||||||
|
|
||||||
|
RsIdentityUsage( RsServiceType service,
|
||||||
|
RsIdentityUsage::UsageCode code,
|
||||||
|
const RsGxsGroupId& gid = RsGxsGroupId(),
|
||||||
|
const RsGxsMessageId& mid = RsGxsMessageId(),
|
||||||
|
uint64_t additional_id=0,
|
||||||
|
const std::string& comment = std::string() );
|
||||||
|
|
||||||
/// Id of the service using that identity, as understood by rsServiceControl
|
/// Id of the service using that identity, as understood by rsServiceControl
|
||||||
uint16_t mServiceId;
|
RsServiceType mServiceId;
|
||||||
|
|
||||||
/** Specific code to use. Will allow forming the correct translated message
|
/** Specific code to use. Will allow forming the correct translated message
|
||||||
* in the GUI if necessary. */
|
* in the GUI if necessary. */
|
||||||
|
@ -380,6 +388,7 @@ struct RsIdentity : RsGxsIfaceHelper
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get identity details, from the cache
|
* @brief Get identity details, from the cache
|
||||||
|
* @jsonapi{development}
|
||||||
* @param[in] id Id of the identity
|
* @param[in] id Id of the identity
|
||||||
* @param[out] details Storage for the identity details
|
* @param[out] details Storage for the identity details
|
||||||
* @return false on error, true otherwise
|
* @return false on error, true otherwise
|
||||||
|
@ -400,7 +409,7 @@ struct RsIdentity : RsGxsIfaceHelper
|
||||||
* @param[out] ids storage for the ids
|
* @param[out] ids storage for the ids
|
||||||
* @return false on error, true otherwise
|
* @return false on error, true otherwise
|
||||||
*/
|
*/
|
||||||
virtual bool getOwnSignedIds(std::vector<RsGxsId> ids) = 0;
|
virtual bool getOwnSignedIds(std::vector<RsGxsId>& ids) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get own pseudonimous (unsigned) ids
|
* @brief Get own pseudonimous (unsigned) ids
|
||||||
|
@ -408,7 +417,7 @@ struct RsIdentity : RsGxsIfaceHelper
|
||||||
* @param[out] ids storage for the ids
|
* @param[out] ids storage for the ids
|
||||||
* @return false on error, true otherwise
|
* @return false on error, true otherwise
|
||||||
*/
|
*/
|
||||||
virtual bool getOwnPseudonimousIds(std::vector<RsGxsId> ids) = 0;
|
virtual bool getOwnPseudonimousIds(std::vector<RsGxsId>& ids) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Check if an id is own
|
* @brief Check if an id is own
|
||||||
|
@ -468,6 +477,7 @@ struct RsIdentity : RsGxsIfaceHelper
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set/unset identity as contact
|
* @brief Set/unset identity as contact
|
||||||
|
* @jsonapi{development}
|
||||||
* @param[in] id Id of the identity
|
* @param[in] id Id of the identity
|
||||||
* @param[in] isContact true to set, false to unset
|
* @param[in] isContact true to set, false to unset
|
||||||
* @return false on error, true otherwise
|
* @return false on error, true otherwise
|
||||||
|
@ -503,6 +513,14 @@ struct RsIdentity : RsGxsIfaceHelper
|
||||||
*/
|
*/
|
||||||
virtual void setDeleteBannedNodesThreshold(uint32_t days) = 0;
|
virtual void setDeleteBannedNodesThreshold(uint32_t days) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief request details of a not yet known identity to the network
|
||||||
|
* @jsonapi{development}
|
||||||
|
* @param[in] id id of the identity to request
|
||||||
|
* @return false on error, true otherwise
|
||||||
|
*/
|
||||||
|
virtual bool requestIdentity(const RsGxsId& id) = 0;
|
||||||
|
|
||||||
|
|
||||||
RS_DEPRECATED
|
RS_DEPRECATED
|
||||||
virtual bool getGroupSerializedData(
|
virtual bool getGroupSerializedData(
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* libretroshare/src/retroshare: rsinit.h *
|
* libretroshare/src/retroshare: rsinit.h *
|
||||||
* *
|
* *
|
||||||
* libretroshare: retroshare core library *
|
* Copyright (C) 2004-2014 Robert Fernie <retroshare@lunamutt.com> *
|
||||||
* *
|
* Copyright (C) 2016-2019 Gioacchino Mazzurco <gio@altermundi.net> *
|
||||||
* Copyright 2004-2006 by Robert Fernie <retroshare@lunamutt.com> *
|
|
||||||
* *
|
* *
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
|
@ -19,8 +18,10 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||||
* *
|
* *
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
#ifndef RETROSHARE_INIT_INTERFACE_H
|
#pragma once
|
||||||
#define RETROSHARE_INIT_INTERFACE_H
|
|
||||||
|
/// RetroShare initialization and login API
|
||||||
|
|
||||||
|
|
||||||
// Initialize ok, result >= 0
|
// Initialize ok, result >= 0
|
||||||
#define RS_INIT_OK 0 // Initialize ok
|
#define RS_INIT_OK 0 // Initialize ok
|
||||||
|
@ -30,13 +31,6 @@
|
||||||
#define RS_INIT_BASE_DIR_ERROR -2 // AuthGPG::InitAuth failed
|
#define RS_INIT_BASE_DIR_ERROR -2 // AuthGPG::InitAuth failed
|
||||||
#define RS_INIT_NO_KEYRING -3 // Keyring is empty. Need to import it.
|
#define RS_INIT_NO_KEYRING -3 // Keyring is empty. Need to import it.
|
||||||
|
|
||||||
|
|
||||||
/****
|
|
||||||
* #define RS_USE_PGPSSL 1
|
|
||||||
***/
|
|
||||||
|
|
||||||
#define RS_USE_PGPSSL 1
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
@ -340,5 +334,3 @@ struct RsLoginHelper
|
||||||
*/
|
*/
|
||||||
bool isLoggedIn();
|
bool isLoggedIn();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -470,6 +470,8 @@ public:
|
||||||
std::map<RsGxsId, rstime_t> gxs_ids ; // list of non direct friend who participate. Used to display only.
|
std::map<RsGxsId, rstime_t> gxs_ids ; // list of non direct friend who participate. Used to display only.
|
||||||
rstime_t last_activity ; // last recorded activity. Useful for removing dead lobbies.
|
rstime_t last_activity ; // last recorded activity. Useful for removing dead lobbies.
|
||||||
|
|
||||||
|
virtual void clear() { gxs_ids.clear(); lobby_id = 0; lobby_name.clear(); lobby_topic.clear(); participating_friends.clear(); }
|
||||||
|
|
||||||
// RsSerializable interface
|
// RsSerializable interface
|
||||||
public:
|
public:
|
||||||
void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext &ctx) {
|
void serial_process(RsGenericSerializer::SerializeJob j, RsGenericSerializer::SerializeContext &ctx) {
|
||||||
|
@ -831,6 +833,13 @@ virtual void getOwnAvatarData(unsigned char *& data,int& size) = 0 ;
|
||||||
*/
|
*/
|
||||||
virtual void unsubscribeChatLobby(const ChatLobbyId &lobby_id) = 0;
|
virtual void unsubscribeChatLobby(const ChatLobbyId &lobby_id) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief sendLobbyStatusPeerLeaving notify friend nodes that we're leaving a subscribed lobby
|
||||||
|
* @jsonapi{development}
|
||||||
|
* @param[in] lobby_id lobby to leave
|
||||||
|
*/
|
||||||
|
virtual void sendLobbyStatusPeerLeaving(const ChatLobbyId& lobby_id) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief setIdentityForChatLobby set the chat identit
|
* @brief setIdentityForChatLobby set the chat identit
|
||||||
* @jsonapi{development}
|
* @jsonapi{development}
|
||||||
|
|
|
@ -212,6 +212,8 @@ public:
|
||||||
NotifyClient() {}
|
NotifyClient() {}
|
||||||
virtual ~NotifyClient() {}
|
virtual ~NotifyClient() {}
|
||||||
|
|
||||||
|
virtual void notifyPeerConnected (const std::string& /* peer_id */) {}
|
||||||
|
virtual void notifyPeerDisconnected (const std::string& /* peer_id */) {}
|
||||||
virtual void notifyListPreChange (int /* list */, int /* type */) {}
|
virtual void notifyListPreChange (int /* list */, int /* type */) {}
|
||||||
virtual void notifyListChange (int /* list */, int /* type */) {}
|
virtual void notifyListChange (int /* list */, int /* type */) {}
|
||||||
virtual void notifyErrorMsg (int /* list */, int /* sev */, std::string /* msg */) {}
|
virtual void notifyErrorMsg (int /* list */, int /* sev */, std::string /* msg */) {}
|
||||||
|
|
|
@ -231,7 +231,7 @@ struct RsPeerDetails : RsSerializable
|
||||||
|
|
||||||
RsPgpId issuer;
|
RsPgpId issuer;
|
||||||
|
|
||||||
PGPFingerprintType fpr; /* pgp fingerprint */
|
RsPgpFingerprint fpr; /* pgp fingerprint */
|
||||||
std::string authcode; // TODO: 2015/12/31 (cyril) what is this used for ?????
|
std::string authcode; // TODO: 2015/12/31 (cyril) what is this used for ?????
|
||||||
std::list<RsPgpId> gpgSigners;
|
std::list<RsPgpId> gpgSigners;
|
||||||
|
|
||||||
|
@ -499,9 +499,9 @@ public:
|
||||||
virtual RsPgpId getGPGId(const RsPeerId& sslId) = 0;
|
virtual RsPgpId getGPGId(const RsPeerId& sslId) = 0;
|
||||||
virtual bool isKeySupported(const RsPgpId& gpg_ids) = 0;
|
virtual bool isKeySupported(const RsPgpId& gpg_ids) = 0;
|
||||||
virtual bool getGPGAcceptedList(std::list<RsPgpId> &gpg_ids) = 0;
|
virtual bool getGPGAcceptedList(std::list<RsPgpId> &gpg_ids) = 0;
|
||||||
virtual bool getGPGSignedList(std::list<RsPgpId> &gpg_ids) = 0;//friends that we accpet to connect with but we don't want to sign their gpg key
|
virtual bool getGPGSignedList(std::list<RsPgpId> &gpg_ids) = 0;// keys signed by our own PGP key.
|
||||||
virtual bool getGPGValidList(std::list<RsPgpId> &gpg_ids) = 0;
|
virtual bool getGPGValidList(std::list<RsPgpId> &gpg_ids) = 0;// all PGP keys without filtering
|
||||||
virtual bool getGPGAllList(std::list<RsPgpId> &gpg_ids) = 0;
|
virtual bool getGPGAllList(std::list<RsPgpId> &gpg_ids) = 0;// all PGP keys as well
|
||||||
virtual bool getAssociatedSSLIds(const RsPgpId& gpg_id, std::list<RsPeerId>& ids) = 0;
|
virtual bool getAssociatedSSLIds(const RsPgpId& gpg_id, std::list<RsPeerId>& ids) = 0;
|
||||||
virtual bool gpgSignData(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen, std::string reason = "") = 0;
|
virtual bool gpgSignData(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen, std::string reason = "") = 0;
|
||||||
|
|
||||||
|
|
|
@ -348,11 +348,11 @@ const std::string CUPnPLib::Element_GetAttributeByTag(
|
||||||
|
|
||||||
CUPnPError::CUPnPError(
|
CUPnPError::CUPnPError(
|
||||||
const CUPnPLib &upnpLib,
|
const CUPnPLib &upnpLib,
|
||||||
IXML_Document *errorDoc)
|
const IXML_Document *errorDoc)
|
||||||
:
|
:
|
||||||
m_root (upnpLib.Element_GetRootElement(errorDoc)),
|
m_root (upnpLib.Element_GetRootElement(errorDoc)),
|
||||||
m_ErrorCode (upnpLib.Element_GetChildValueByTag(m_root, "errorCode")),
|
m_ErrorCode (upnpLib.Element_GetChildValueByTag(m_root, "errorCode")),
|
||||||
m_ErrorDescription(upnpLib.Element_GetChildValueByTag(m_root, "errorDescription"))
|
m_ErrorDescription(upnpLib.Element_GetChildValueByTag(m_root, "errorDescription"))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -488,6 +488,7 @@ m_timeout(1801),
|
||||||
m_SCPD(NULL)
|
m_SCPD(NULL)
|
||||||
{
|
{
|
||||||
int errcode;
|
int errcode;
|
||||||
|
m_SID[0]=0;
|
||||||
|
|
||||||
std::vector<char> vscpdURL(URLBase.length() + m_SCPDURL.length() + 1);
|
std::vector<char> vscpdURL(URLBase.length() + m_SCPDURL.length() + 1);
|
||||||
char *scpdURL = &vscpdURL[0];
|
char *scpdURL = &vscpdURL[0];
|
||||||
|
@ -1333,6 +1334,12 @@ int CUPnPControlPoint::Callback(
|
||||||
std::string devType(upnpCP->m_upnpLib.
|
std::string devType(upnpCP->m_upnpLib.
|
||||||
Element_GetChildValueByTag(rootDevice, "deviceType"));
|
Element_GetChildValueByTag(rootDevice, "deviceType"));
|
||||||
|
|
||||||
|
#ifdef UPNP_DEBUG
|
||||||
|
std::cerr << "CUPnPControlPoint::Callback() EventType==UPNP_DISCOVERY_SEARCH_RESULT" << std::endl
|
||||||
|
<< "urlBase:" << urlBase << std::endl
|
||||||
|
<< "devType:" << devType << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Only add device if it is an InternetGatewayDevice
|
// Only add device if it is an InternetGatewayDevice
|
||||||
if (stdStringIsEqualCI(devType, upnpCP->m_upnpLib.UPNP_DEVICE_IGW))
|
if (stdStringIsEqualCI(devType, upnpCP->m_upnpLib.UPNP_DEVICE_IGW))
|
||||||
{
|
{
|
||||||
|
@ -1351,6 +1358,10 @@ int CUPnPControlPoint::Callback(
|
||||||
rootDevice, urlBase,
|
rootDevice, urlBase,
|
||||||
UpnpDiscovery_get_Location_cstr(d_event),
|
UpnpDiscovery_get_Location_cstr(d_event),
|
||||||
UpnpDiscovery_get_Expires(d_event) );
|
UpnpDiscovery_get_Expires(d_event) );
|
||||||
|
|
||||||
|
#if (UPNP_VERSION > 10624) && (UPNP_VERSION < 10800)
|
||||||
|
upnpCP->m_WaitForSearchTimeoutMutex.unlock();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free the XML doc tree
|
// Free the XML doc tree
|
||||||
|
@ -1359,6 +1370,13 @@ int CUPnPControlPoint::Callback(
|
||||||
}
|
}
|
||||||
case UPNP_DISCOVERY_SEARCH_TIMEOUT:
|
case UPNP_DISCOVERY_SEARCH_TIMEOUT:
|
||||||
{
|
{
|
||||||
|
#if (UPNP_VERSION > 10624) && (UPNP_VERSION < 10800)
|
||||||
|
std::cerr << "********************************************************************************" << std::endl
|
||||||
|
<< "*** THIS SHOULD NOT HAPPEN !!! TELL IT TO DEVS ***" << std::endl
|
||||||
|
<< "*** UPnPBase.cpp CUPnPControlPoint::Callback() UPNP_DISCOVERY_SEARCH_TIMEOUT ***" << std::endl
|
||||||
|
<< "********************************************************************************" << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Unlock the search timeout mutex
|
// Unlock the search timeout mutex
|
||||||
upnpCP->m_WaitForSearchTimeoutMutex.unlock();
|
upnpCP->m_WaitForSearchTimeoutMutex.unlock();
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
extern std::string stdEmptyString;
|
extern std::string stdEmptyString;
|
||||||
#endif // UPNP_C
|
#endif // UPNP_C
|
||||||
|
|
||||||
|
//#define UPNP_DEBUG 1
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Case insensitive std::string comparison
|
* Case insensitive std::string comparison
|
||||||
|
@ -255,7 +256,7 @@ private:
|
||||||
public:
|
public:
|
||||||
CUPnPError(
|
CUPnPError(
|
||||||
const CUPnPLib &upnpLib,
|
const CUPnPLib &upnpLib,
|
||||||
IXML_Document *errorDoc);
|
const IXML_Document *errorDoc);
|
||||||
~CUPnPError() {}
|
~CUPnPError() {}
|
||||||
const std::string &getErrorCode() const
|
const std::string &getErrorCode() const
|
||||||
{ return m_ErrorCode; }
|
{ return m_ErrorCode; }
|
||||||
|
|
|
@ -35,8 +35,6 @@
|
||||||
#include "pqi/p3linkmgr.h"
|
#include "pqi/p3linkmgr.h"
|
||||||
#include "pqi/p3netmgr.h"
|
#include "pqi/p3netmgr.h"
|
||||||
|
|
||||||
int rsserverzone = 101;
|
|
||||||
|
|
||||||
#include "util/rsdebug.h"
|
#include "util/rsdebug.h"
|
||||||
|
|
||||||
#include "retroshare/rsevents.h"
|
#include "retroshare/rsevents.h"
|
||||||
|
@ -86,7 +84,7 @@ RsServer::RsServer() :
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
RsEventsService* tmpRsEvtPtr = new RsEventsService();
|
RsEventsService* tmpRsEvtPtr = new RsEventsService();
|
||||||
rsEvents.reset(tmpRsEvtPtr);
|
rsEvents = tmpRsEvtPtr;
|
||||||
startServiceThread(tmpRsEvtPtr, "RsEventsService");
|
startServiceThread(tmpRsEvtPtr, "RsEventsService");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,8 +269,6 @@ void RsServer::data_tick()
|
||||||
std::string out;
|
std::string out;
|
||||||
rs_sprintf(out, "RsServer::run() WARNING Excessively Long Cycle Time: %g secs => Please DEBUG", cycleTime);
|
rs_sprintf(out, "RsServer::run() WARNING Excessively Long Cycle Time: %g secs => Please DEBUG", cycleTime);
|
||||||
std::cerr << out << std::endl;
|
std::cerr << out << std::endl;
|
||||||
|
|
||||||
rslog(RSL_ALERT, rsserverzone, out);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -453,6 +453,10 @@ void p3Msgs::invitePeerToLobby(const ChatLobbyId& lobby_id, const RsPeerId& peer
|
||||||
{
|
{
|
||||||
mChatSrv->invitePeerToLobby(lobby_id,peer_id) ;
|
mChatSrv->invitePeerToLobby(lobby_id,peer_id) ;
|
||||||
}
|
}
|
||||||
|
void p3Msgs::sendLobbyStatusPeerLeaving(const ChatLobbyId& lobby_id)
|
||||||
|
{
|
||||||
|
mChatSrv->sendLobbyStatusPeerLeaving(lobby_id) ;
|
||||||
|
}
|
||||||
void p3Msgs::unsubscribeChatLobby(const ChatLobbyId& lobby_id)
|
void p3Msgs::unsubscribeChatLobby(const ChatLobbyId& lobby_id)
|
||||||
{
|
{
|
||||||
mChatSrv->unsubscribeChatLobby(lobby_id) ;
|
mChatSrv->unsubscribeChatLobby(lobby_id) ;
|
||||||
|
|
|
@ -147,6 +147,7 @@ class p3Msgs: public RsMsgs
|
||||||
virtual void denyLobbyInvite(const ChatLobbyId& id) ;
|
virtual void denyLobbyInvite(const ChatLobbyId& id) ;
|
||||||
virtual void getPendingChatLobbyInvites(std::list<ChatLobbyInvite>& invites) ;
|
virtual void getPendingChatLobbyInvites(std::list<ChatLobbyInvite>& invites) ;
|
||||||
virtual void unsubscribeChatLobby(const ChatLobbyId& lobby_id) ;
|
virtual void unsubscribeChatLobby(const ChatLobbyId& lobby_id) ;
|
||||||
|
virtual void sendLobbyStatusPeerLeaving(const ChatLobbyId& lobby_id);
|
||||||
virtual bool setIdentityForChatLobby(const ChatLobbyId& lobby_id,const RsGxsId&) ;
|
virtual bool setIdentityForChatLobby(const ChatLobbyId& lobby_id,const RsGxsId&) ;
|
||||||
virtual bool getIdentityForChatLobby(const ChatLobbyId&,RsGxsId& nick) ;
|
virtual bool getIdentityForChatLobby(const ChatLobbyId&,RsGxsId& nick) ;
|
||||||
virtual bool setDefaultIdentityForChatLobby(const RsGxsId&) ;
|
virtual bool setDefaultIdentityForChatLobby(const RsGxsId&) ;
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* libretroshare/src/retroshare: rsinit.cc *
|
* libretroshare/src/retroshare: rsinit.cc *
|
||||||
* *
|
* *
|
||||||
* libretroshare: retroshare core library *
|
* Copyright (C) 2004-2014 Robert Fernie <retroshare@lunamutt.com> *
|
||||||
* *
|
* Copyright (C) 2016-2019 Gioacchino Mazzurco <gio@altermundi.net> *
|
||||||
* Copyright 2004-2006 by Robert Fernie <retroshare@lunamutt.com> *
|
|
||||||
* *
|
* *
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
|
@ -20,8 +19,7 @@
|
||||||
* *
|
* *
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
/* This is an updated startup class. Class variables are hidden from
|
/// RetroShare initialization and login API implementation
|
||||||
* the GUI / External via a hidden class */
|
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* libretroshare: retroshare core library *
|
* libretroshare: retroshare core library *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 2017 Cyril Soler <csoler@users.sourceforge.net> *
|
* Copyright (C) 2017 Cyril Soler <csoler@users.sourceforge.net> *
|
||||||
* Copyright (C) 2018 Gioacchino Mazzurco <gio@eigenlab.org> *
|
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||||
* *
|
* *
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
|
@ -39,8 +39,7 @@
|
||||||
#include <rapid_json/prettywriter.h>
|
#include <rapid_json/prettywriter.h>
|
||||||
#endif // HAS_RAPIDJSON
|
#endif // HAS_RAPIDJSON
|
||||||
|
|
||||||
//static const uint32_t MAX_SERIALIZED_ARRAY_SIZE = 500 ;
|
static constexpr uint32_t MAX_SERIALIZED_CHUNK_SIZE = 10*1024*1024 ; // 10 MB.
|
||||||
static const uint32_t MAX_SERIALIZED_CHUNK_SIZE = 10*1024*1024 ; // 10 MB.
|
|
||||||
|
|
||||||
#ifdef RSSERIAL_DEBUG
|
#ifdef RSSERIAL_DEBUG
|
||||||
# define SAFE_GET_JSON_V() \
|
# define SAFE_GET_JSON_V() \
|
||||||
|
@ -63,6 +62,61 @@ static const uint32_t MAX_SERIALIZED_CHUNK_SIZE = 10*1024*1024 ; // 10 MB.
|
||||||
#endif // ifdef RSSERIAL_DEBUG
|
#endif // ifdef RSSERIAL_DEBUG
|
||||||
|
|
||||||
|
|
||||||
|
//============================================================================//
|
||||||
|
// std::string //
|
||||||
|
//============================================================================//
|
||||||
|
|
||||||
|
template<> uint32_t RsTypeSerializer::serial_size(const std::string& str)
|
||||||
|
{
|
||||||
|
return getRawStringSize(str);
|
||||||
|
}
|
||||||
|
template<> bool RsTypeSerializer::serialize( uint8_t data[], uint32_t size,
|
||||||
|
uint32_t& offset,
|
||||||
|
const std::string& str )
|
||||||
|
{
|
||||||
|
return setRawString(data, size, &offset, str);
|
||||||
|
}
|
||||||
|
template<> bool RsTypeSerializer::deserialize( const uint8_t data[],
|
||||||
|
uint32_t size, uint32_t &offset,
|
||||||
|
std::string& str )
|
||||||
|
{
|
||||||
|
return getRawString(data, size, &offset, str);
|
||||||
|
}
|
||||||
|
template<> void RsTypeSerializer::print_data( const std::string& n,
|
||||||
|
const std::string& str )
|
||||||
|
{
|
||||||
|
std::cerr << " [std::string] " << n << ": " << str << std::endl;
|
||||||
|
}
|
||||||
|
template<> /*static*/
|
||||||
|
bool RsTypeSerializer::to_JSON( const std::string& membername,
|
||||||
|
const std::string& member, RsJson& jDoc )
|
||||||
|
{
|
||||||
|
rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator();
|
||||||
|
|
||||||
|
rapidjson::Value key;
|
||||||
|
key.SetString( membername.c_str(),
|
||||||
|
static_cast<rapidjson::SizeType>(membername.length()),
|
||||||
|
allocator );
|
||||||
|
|
||||||
|
rapidjson::Value value;
|
||||||
|
value.SetString( member.c_str(),
|
||||||
|
static_cast<rapidjson::SizeType>(member.length()),
|
||||||
|
allocator );
|
||||||
|
|
||||||
|
jDoc.AddMember(key, value, allocator);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
template<> /*static*/
|
||||||
|
bool RsTypeSerializer::from_JSON( const std::string& memberName,
|
||||||
|
std::string& member, RsJson& jDoc )
|
||||||
|
{
|
||||||
|
SAFE_GET_JSON_V();
|
||||||
|
ret = ret && v.IsString();
|
||||||
|
if(ret) member = v.GetString();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
//============================================================================//
|
//============================================================================//
|
||||||
// Integer types //
|
// Integer types //
|
||||||
//============================================================================//
|
//============================================================================//
|
||||||
|
@ -199,7 +253,9 @@ template<> bool RsTypeSerializer::to_JSON( const std::string& memberName, \
|
||||||
rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator(); \
|
rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator(); \
|
||||||
\
|
\
|
||||||
rapidjson::Value key; \
|
rapidjson::Value key; \
|
||||||
key.SetString(memberName.c_str(), memberName.length(), allocator); \
|
key.SetString( memberName.c_str(), \
|
||||||
|
static_cast<rapidjson::SizeType>(memberName.length()), \
|
||||||
|
allocator ); \
|
||||||
\
|
\
|
||||||
rapidjson::Value value(member); \
|
rapidjson::Value value(member); \
|
||||||
\
|
\
|
||||||
|
@ -210,12 +266,39 @@ template<> bool RsTypeSerializer::to_JSON( const std::string& memberName, \
|
||||||
|
|
||||||
SIMPLE_TO_JSON_DEF(bool)
|
SIMPLE_TO_JSON_DEF(bool)
|
||||||
SIMPLE_TO_JSON_DEF(int32_t)
|
SIMPLE_TO_JSON_DEF(int32_t)
|
||||||
SIMPLE_TO_JSON_DEF(rstime_t)
|
|
||||||
|
|
||||||
SIMPLE_TO_JSON_DEF(uint8_t)
|
SIMPLE_TO_JSON_DEF(uint8_t)
|
||||||
SIMPLE_TO_JSON_DEF(uint16_t)
|
SIMPLE_TO_JSON_DEF(uint16_t)
|
||||||
SIMPLE_TO_JSON_DEF(uint32_t)
|
SIMPLE_TO_JSON_DEF(uint32_t)
|
||||||
SIMPLE_TO_JSON_DEF(uint64_t)
|
|
||||||
|
/** Be very careful in changing this constant as it would break 64 bit integers
|
||||||
|
* members JSON string representation retrocompatibility */
|
||||||
|
static constexpr char strReprSuffix[] = "_sixtyfour_str";
|
||||||
|
|
||||||
|
/** While JSON doesn't have problems representing 64 bit integers JavaScript
|
||||||
|
* standard represents numbers in a double-like format thus it is not capable to
|
||||||
|
* handle safely integers outside the range [-(2^53 - 1), 2^53 - 1], so we add
|
||||||
|
* to JSON also the string representation for this types as a workaround for the
|
||||||
|
* sake of JavaScript clients @see https://stackoverflow.com/a/34989371
|
||||||
|
*/
|
||||||
|
#define SIXTYFOUR_INTEGERS_TO_JSON_DEF(T) \
|
||||||
|
template<> bool RsTypeSerializer::to_JSON( const std::string& memberName, \
|
||||||
|
const T& member, RsJson& jDoc ) \
|
||||||
|
{ \
|
||||||
|
rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator(); \
|
||||||
|
\
|
||||||
|
rapidjson::Value key; \
|
||||||
|
key.SetString( memberName.c_str(), \
|
||||||
|
static_cast<rapidjson::SizeType>(memberName.length()), \
|
||||||
|
allocator ); \
|
||||||
|
rapidjson::Value value(member); \
|
||||||
|
jDoc.AddMember(key, value, allocator); \
|
||||||
|
\
|
||||||
|
return to_JSON(memberName + strReprSuffix, std::to_string(member), jDoc); \
|
||||||
|
}
|
||||||
|
|
||||||
|
SIXTYFOUR_INTEGERS_TO_JSON_DEF(int64_t);
|
||||||
|
SIXTYFOUR_INTEGERS_TO_JSON_DEF(uint64_t);
|
||||||
|
|
||||||
template<> /*static*/
|
template<> /*static*/
|
||||||
bool RsTypeSerializer::from_JSON( const std::string& memberName, bool& member,
|
bool RsTypeSerializer::from_JSON( const std::string& memberName, bool& member,
|
||||||
|
@ -237,23 +320,13 @@ bool RsTypeSerializer::from_JSON( const std::string& memberName,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> /*static*/
|
|
||||||
bool RsTypeSerializer::from_JSON( const std::string& memberName, rstime_t& member,
|
|
||||||
RsJson& jDoc )
|
|
||||||
{
|
|
||||||
SAFE_GET_JSON_V();
|
|
||||||
ret = ret && v.IsInt64();
|
|
||||||
if(ret) member = v.GetInt64();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<> /*static*/
|
template<> /*static*/
|
||||||
bool RsTypeSerializer::from_JSON( const std::string& memberName,
|
bool RsTypeSerializer::from_JSON( const std::string& memberName,
|
||||||
uint8_t& member, RsJson& jDoc )
|
uint8_t& member, RsJson& jDoc )
|
||||||
{
|
{
|
||||||
SAFE_GET_JSON_V();
|
SAFE_GET_JSON_V();
|
||||||
ret = ret && v.IsUint();
|
ret = ret && v.IsUint();
|
||||||
if(ret) member = v.GetUint();
|
if(ret) member = static_cast<uint8_t>(v.GetUint());
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,7 +336,7 @@ bool RsTypeSerializer::from_JSON( const std::string& memberName,
|
||||||
{
|
{
|
||||||
SAFE_GET_JSON_V();
|
SAFE_GET_JSON_V();
|
||||||
ret = ret && v.IsUint();
|
ret = ret && v.IsUint();
|
||||||
if(ret) member = v.GetUint();
|
if(ret) member = static_cast<uint16_t>(v.GetUint());
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,14 +350,98 @@ bool RsTypeSerializer::from_JSON( const std::string& memberName,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** While JSON doesn't have problems representing 64 bit integers JavaScript
|
||||||
|
* standard represents numbers in a double-like format thus it is not capable to
|
||||||
|
* handle safely integers outside the range [-(2^53 - 1), 2^53 - 1], so we look
|
||||||
|
* for the string representation in the JSON for this types as a workaround for
|
||||||
|
* the sake of JavaScript clients @see https://stackoverflow.com/a/34989371
|
||||||
|
*/
|
||||||
template<> /*static*/
|
template<> /*static*/
|
||||||
bool RsTypeSerializer::from_JSON( const std::string& memberName,
|
bool RsTypeSerializer::from_JSON(
|
||||||
uint64_t& member, RsJson& jDoc )
|
const std::string& memberName, int64_t& member, RsJson& jDoc )
|
||||||
{
|
{
|
||||||
SAFE_GET_JSON_V();
|
const char* mName = memberName.c_str();
|
||||||
ret = ret && v.IsUint64();
|
if(jDoc.HasMember(mName))
|
||||||
if(ret) member = v.GetUint64();
|
{
|
||||||
return ret;
|
rapidjson::Value& v = jDoc[mName];
|
||||||
|
if(v.IsInt64())
|
||||||
|
{
|
||||||
|
member = v.GetInt64();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Dbg4() << __PRETTY_FUNCTION__ << " int64_t " << memberName << " not found "
|
||||||
|
<< "in JSON then attempt to look for string representation"
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
const std::string str_key = memberName + strReprSuffix;
|
||||||
|
std::string str_value;
|
||||||
|
if(from_JSON(str_key, str_value, jDoc))
|
||||||
|
{
|
||||||
|
try { member = std::stoll(str_value); }
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
RsErr() << __PRETTY_FUNCTION__ << " cannot convert "
|
||||||
|
<< str_value << " to int64_t" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dbg3() << __PRETTY_FUNCTION__ << " neither " << memberName << " nor its "
|
||||||
|
<< "string representation " << str_key << " has been found "
|
||||||
|
<< "in JSON" << std::endl;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** While JSON doesn't have problems representing 64 bit integers JavaScript
|
||||||
|
* standard represents numbers in a double-like format thus it is not capable to
|
||||||
|
* handle safely integers outside the range [-(2^53 - 1), 2^53 - 1], so we look
|
||||||
|
* for the string representation in the JSON for this types as a workaround for
|
||||||
|
* the sake of JavaScript clients @see https://stackoverflow.com/a/34989371
|
||||||
|
*/
|
||||||
|
template<> /*static*/
|
||||||
|
bool RsTypeSerializer::from_JSON(
|
||||||
|
const std::string& memberName, uint64_t& member, RsJson& jDoc )
|
||||||
|
{
|
||||||
|
const char* mName = memberName.c_str();
|
||||||
|
if(jDoc.HasMember(mName))
|
||||||
|
{
|
||||||
|
rapidjson::Value& v = jDoc[mName];
|
||||||
|
if(v.IsUint64())
|
||||||
|
{
|
||||||
|
member = v.GetUint64();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Dbg4() << __PRETTY_FUNCTION__ << " uint64_t " << memberName << " not found "
|
||||||
|
<< "in JSON then attempt to look for string representation"
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
const std::string str_key = memberName + strReprSuffix;
|
||||||
|
std::string str_value;
|
||||||
|
if(from_JSON(str_key, str_value, jDoc))
|
||||||
|
{
|
||||||
|
try { member = std::stoull(str_value); }
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
RsErr() << __PRETTY_FUNCTION__ << " cannot convert "
|
||||||
|
<< str_value << " to uint64_t" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dbg3() << __PRETTY_FUNCTION__ << " neither " << memberName << " nor its "
|
||||||
|
<< "string representation " << str_key << " has been found "
|
||||||
|
<< "in JSON" << std::endl;
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -363,59 +520,6 @@ bool RsTypeSerializer::from_JSON( const std::string& memberName,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================================//
|
|
||||||
// std::string //
|
|
||||||
//============================================================================//
|
|
||||||
|
|
||||||
template<> uint32_t RsTypeSerializer::serial_size(const std::string& str)
|
|
||||||
{
|
|
||||||
return getRawStringSize(str);
|
|
||||||
}
|
|
||||||
template<> bool RsTypeSerializer::serialize( uint8_t data[], uint32_t size,
|
|
||||||
uint32_t& offset,
|
|
||||||
const std::string& str )
|
|
||||||
{
|
|
||||||
return setRawString(data, size, &offset, str);
|
|
||||||
}
|
|
||||||
template<> bool RsTypeSerializer::deserialize( const uint8_t data[],
|
|
||||||
uint32_t size, uint32_t &offset,
|
|
||||||
std::string& str )
|
|
||||||
{
|
|
||||||
return getRawString(data, size, &offset, str);
|
|
||||||
}
|
|
||||||
template<> void RsTypeSerializer::print_data( const std::string& n,
|
|
||||||
const std::string& str )
|
|
||||||
{
|
|
||||||
std::cerr << " [std::string] " << n << ": " << str << std::endl;
|
|
||||||
}
|
|
||||||
template<> /*static*/
|
|
||||||
bool RsTypeSerializer::to_JSON( const std::string& membername,
|
|
||||||
const std::string& member, RsJson& jDoc )
|
|
||||||
{
|
|
||||||
rapidjson::Document::AllocatorType& allocator = jDoc.GetAllocator();
|
|
||||||
|
|
||||||
rapidjson::Value key;
|
|
||||||
key.SetString(membername.c_str(), membername.length(), allocator);
|
|
||||||
|
|
||||||
rapidjson::Value value;;
|
|
||||||
value.SetString(member.c_str(), member.length(), allocator);
|
|
||||||
|
|
||||||
jDoc.AddMember(key, value, allocator);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
template<> /*static*/
|
|
||||||
bool RsTypeSerializer::from_JSON( const std::string& memberName,
|
|
||||||
std::string& member, RsJson& jDoc )
|
|
||||||
{
|
|
||||||
SAFE_GET_JSON_V();
|
|
||||||
ret = ret && v.IsString();
|
|
||||||
if(ret) member = v.GetString();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================//
|
//============================================================================//
|
||||||
// TlvString with subtype //
|
// TlvString with subtype //
|
||||||
//============================================================================//
|
//============================================================================//
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* libretroshare: retroshare core library *
|
* libretroshare: retroshare core library *
|
||||||
* *
|
* *
|
||||||
* Copyright (C) 2017 Cyril Soler <csoler@users.sourceforge.net> *
|
* Copyright (C) 2017 Cyril Soler <csoler@users.sourceforge.net> *
|
||||||
* Copyright (C) 2018 Gioacchino Mazzurco <gio@eigenlab.org> *
|
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||||
* *
|
* *
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
|
@ -32,6 +32,7 @@
|
||||||
#include "serialiser/rsserializer.h"
|
#include "serialiser/rsserializer.h"
|
||||||
#include "serialiser/rsserializable.h"
|
#include "serialiser/rsserializable.h"
|
||||||
#include "util/rsjson.h"
|
#include "util/rsjson.h"
|
||||||
|
#include "util/rsdebug.h"
|
||||||
|
|
||||||
#include <typeinfo> // for typeid
|
#include <typeinfo> // for typeid
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
@ -907,6 +908,8 @@ protected:
|
||||||
static bool from_JSON( const std::string& memberName,
|
static bool from_JSON( const std::string& memberName,
|
||||||
t_RsTlvList<TLV_CLASS,TLV_TYPE>& member,
|
t_RsTlvList<TLV_CLASS,TLV_TYPE>& member,
|
||||||
RsJson& jDoc );
|
RsJson& jDoc );
|
||||||
|
|
||||||
|
RS_SET_CONTEXT_DEBUG_LEVEL(1)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,6 @@ struct BroadcastDiscoveryPack : RsSerializable
|
||||||
{
|
{
|
||||||
BroadcastDiscoveryPack() : mLocalPort(0) {}
|
BroadcastDiscoveryPack() : mLocalPort(0) {}
|
||||||
|
|
||||||
RsPgpFingerprint mPgpFingerprint;
|
|
||||||
RsPeerId mSslId;
|
RsPeerId mSslId;
|
||||||
uint16_t mLocalPort;
|
uint16_t mLocalPort;
|
||||||
std::string mProfileName;
|
std::string mProfileName;
|
||||||
|
@ -48,7 +47,6 @@ struct BroadcastDiscoveryPack : RsSerializable
|
||||||
void serial_process( RsGenericSerializer::SerializeJob j,
|
void serial_process( RsGenericSerializer::SerializeJob j,
|
||||||
RsGenericSerializer::SerializeContext& ctx ) override
|
RsGenericSerializer::SerializeContext& ctx ) override
|
||||||
{
|
{
|
||||||
RS_SERIAL_PROCESS(mPgpFingerprint);
|
|
||||||
RS_SERIAL_PROCESS(mSslId);
|
RS_SERIAL_PROCESS(mSslId);
|
||||||
RS_SERIAL_PROCESS(mLocalPort);
|
RS_SERIAL_PROCESS(mLocalPort);
|
||||||
RS_SERIAL_PROCESS(mProfileName);
|
RS_SERIAL_PROCESS(mProfileName);
|
||||||
|
@ -57,7 +55,6 @@ struct BroadcastDiscoveryPack : RsSerializable
|
||||||
static BroadcastDiscoveryPack fromPeerDetails(const RsPeerDetails& pd)
|
static BroadcastDiscoveryPack fromPeerDetails(const RsPeerDetails& pd)
|
||||||
{
|
{
|
||||||
BroadcastDiscoveryPack bdp;
|
BroadcastDiscoveryPack bdp;
|
||||||
bdp.mPgpFingerprint = pd.fpr;
|
|
||||||
bdp.mSslId = pd.id;
|
bdp.mSslId = pd.id;
|
||||||
bdp.mLocalPort = pd.localPort;
|
bdp.mLocalPort = pd.localPort;
|
||||||
bdp.mProfileName = pd.name;
|
bdp.mProfileName = pd.name;
|
||||||
|
@ -103,12 +100,12 @@ BroadcastDiscoveryService::BroadcastDiscoveryService(
|
||||||
mUdcParameters.set_port(port);
|
mUdcParameters.set_port(port);
|
||||||
mUdcParameters.set_application_id(appId);
|
mUdcParameters.set_application_id(appId);
|
||||||
|
|
||||||
mUdcEndpoint.Start(mUdcParameters, "");
|
mUdcPeer.Start(mUdcParameters, "");
|
||||||
updatePublishedData();
|
updatePublishedData();
|
||||||
}
|
}
|
||||||
|
|
||||||
BroadcastDiscoveryService::~BroadcastDiscoveryService()
|
BroadcastDiscoveryService::~BroadcastDiscoveryService()
|
||||||
{ mUdcEndpoint.Stop(true); }
|
{ mUdcPeer.Stop(true); }
|
||||||
|
|
||||||
std::vector<RsBroadcastDiscoveryResult>
|
std::vector<RsBroadcastDiscoveryResult>
|
||||||
BroadcastDiscoveryService::getDiscoveredPeers()
|
BroadcastDiscoveryService::getDiscoveredPeers()
|
||||||
|
@ -126,7 +123,7 @@ void BroadcastDiscoveryService::updatePublishedData()
|
||||||
{
|
{
|
||||||
RsPeerDetails od;
|
RsPeerDetails od;
|
||||||
mRsPeers.getPeerDetails(mRsPeers.getOwnId(), od);
|
mRsPeers.getPeerDetails(mRsPeers.getOwnId(), od);
|
||||||
mUdcEndpoint.SetUserData(
|
mUdcPeer.SetUserData(
|
||||||
BroadcastDiscoveryPack::fromPeerDetails(od).serializeToString());
|
BroadcastDiscoveryPack::fromPeerDetails(od).serializeToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,7 +134,7 @@ void BroadcastDiscoveryService::data_tick()
|
||||||
if( mUdcParameters.can_discover() &&
|
if( mUdcParameters.can_discover() &&
|
||||||
!mRsPeers.isHiddenNode(mRsPeers.getOwnId()) )
|
!mRsPeers.isHiddenNode(mRsPeers.getOwnId()) )
|
||||||
{
|
{
|
||||||
auto currentEndpoints = mUdcEndpoint.ListDiscovered();
|
auto currentEndpoints = mUdcPeer.ListDiscovered();
|
||||||
std::map<UDC::IpPort, std::string> currentMap;
|
std::map<UDC::IpPort, std::string> currentMap;
|
||||||
std::map<UDC::IpPort, std::string> updateMap;
|
std::map<UDC::IpPort, std::string> updateMap;
|
||||||
|
|
||||||
|
@ -163,23 +160,20 @@ void BroadcastDiscoveryService::data_tick()
|
||||||
createResult(pp.first, pp.second);
|
createResult(pp.first, pp.second);
|
||||||
|
|
||||||
const bool isFriend = mRsPeers.isFriend(rbdr.mSslId);
|
const bool isFriend = mRsPeers.isFriend(rbdr.mSslId);
|
||||||
if( isFriend && rbdr.locator.hasPort() &&
|
if( isFriend && rbdr.mLocator.hasPort() &&
|
||||||
!mRsPeers.isOnline(rbdr.mSslId) )
|
!mRsPeers.isOnline(rbdr.mSslId) )
|
||||||
{
|
{
|
||||||
mRsPeers.setLocalAddress(
|
mRsPeers.setLocalAddress(
|
||||||
rbdr.mSslId, rbdr.locator.host(),
|
rbdr.mSslId, rbdr.mLocator.host(),
|
||||||
rbdr.locator.port() );
|
rbdr.mLocator.port() );
|
||||||
mRsPeers.connectAttempt(rbdr.mSslId);
|
mRsPeers.connectAttempt(rbdr.mSslId);
|
||||||
}
|
}
|
||||||
else if(!isFriend)
|
else if(!isFriend)
|
||||||
{
|
{
|
||||||
typedef RsBroadcastDiscoveryPeerFoundEvent Evt_t;
|
typedef RsBroadcastDiscoveryPeerFoundEvent Evt_t;
|
||||||
|
if(rsEvents)
|
||||||
// Ensure rsEvents is not deleted while we use it
|
rsEvents->postEvent(
|
||||||
std::shared_ptr<RsEvents> lockedRsEvents = rsEvents;
|
std::shared_ptr<Evt_t>(new Evt_t(rbdr)) );
|
||||||
if(lockedRsEvents)
|
|
||||||
lockedRsEvents->postEvent(
|
|
||||||
std::unique_ptr<Evt_t>(new Evt_t(rbdr)) );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -199,10 +193,9 @@ RsBroadcastDiscoveryResult BroadcastDiscoveryService::createResult(
|
||||||
BroadcastDiscoveryPack::fromSerializedString(uData);
|
BroadcastDiscoveryPack::fromSerializedString(uData);
|
||||||
|
|
||||||
RsBroadcastDiscoveryResult rbdr;
|
RsBroadcastDiscoveryResult rbdr;
|
||||||
rbdr.mPgpFingerprint = bdp.mPgpFingerprint;
|
|
||||||
rbdr.mSslId = bdp.mSslId;
|
rbdr.mSslId = bdp.mSslId;
|
||||||
rbdr.mProfileName = bdp.mProfileName;
|
rbdr.mProfileName = bdp.mProfileName;
|
||||||
rbdr.locator.
|
rbdr.mLocator.
|
||||||
setScheme("ipv4").
|
setScheme("ipv4").
|
||||||
setHost(UDC::IpToString(ipp.ip())).
|
setHost(UDC::IpToString(ipp.ip())).
|
||||||
setPort(bdp.mLocalPort);
|
setPort(bdp.mLocalPort);
|
||||||
|
|
|
@ -22,10 +22,11 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <endpoint.hpp>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <forward_list>
|
#include <forward_list>
|
||||||
|
|
||||||
|
#include <udp_discovery_peer.hpp>
|
||||||
|
|
||||||
#include "retroshare/rsbroadcastdiscovery.h"
|
#include "retroshare/rsbroadcastdiscovery.h"
|
||||||
#include "util/rsthreads.h"
|
#include "util/rsthreads.h"
|
||||||
|
|
||||||
|
@ -52,8 +53,8 @@ protected:
|
||||||
|
|
||||||
void updatePublishedData();
|
void updatePublishedData();
|
||||||
|
|
||||||
UDC::EndpointParameters mUdcParameters;
|
UDC::PeerParameters mUdcParameters;
|
||||||
UDC::Endpoint mUdcEndpoint;
|
UDC::Peer mUdcPeer;
|
||||||
|
|
||||||
std::map<UDC::IpPort, std::string> mDiscoveredData;
|
std::map<UDC::IpPort, std::string> mDiscoveredData;
|
||||||
RsMutex mDiscoveredDataMutex;
|
RsMutex mDiscoveredDataMutex;
|
||||||
|
|
|
@ -306,18 +306,23 @@ bool p3BanList::acceptedBanRanges_locked(const BanListPeer& blp)
|
||||||
}
|
}
|
||||||
return false ;
|
return false ;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool p3BanList::isAddressAccepted(
|
bool p3BanList::isAddressAccepted(
|
||||||
const sockaddr_storage& dAddr, uint32_t checking_flags,
|
const sockaddr_storage& dAddr, uint32_t checking_flags,
|
||||||
uint32_t& check_result )
|
uint32_t& check_result )
|
||||||
{
|
{
|
||||||
check_result = RSBANLIST_CHECK_RESULT_NOCHECK;
|
check_result = RSBANLIST_CHECK_RESULT_NOCHECK;
|
||||||
if(!mIPFilteringEnabled) return true;
|
|
||||||
|
|
||||||
sockaddr_storage addr; sockaddr_storage_copy(dAddr, addr);
|
sockaddr_storage addr; sockaddr_storage_copy(dAddr, addr);
|
||||||
|
|
||||||
if(!sockaddr_storage_ipv6_to_ipv4(addr)) return true;
|
if(!sockaddr_storage_ipv6_to_ipv4(addr)) return true;
|
||||||
if(sockaddr_storage_isLoopbackNet(addr)) return true;
|
if(sockaddr_storage_isLoopbackNet(addr)) return true;
|
||||||
|
|
||||||
|
|
||||||
|
RS_STACK_MUTEX(mBanMtx);
|
||||||
|
|
||||||
|
if(!mIPFilteringEnabled) return true;
|
||||||
|
|
||||||
#ifdef DEBUG_BANLIST
|
#ifdef DEBUG_BANLIST
|
||||||
std::cerr << "isAddressAccepted(): tested addr=" << sockaddr_storage_iptostring(addr) << ", checking flags=" << checking_flags ;
|
std::cerr << "isAddressAccepted(): tested addr=" << sockaddr_storage_iptostring(addr) << ", checking flags=" << checking_flags ;
|
||||||
#endif
|
#endif
|
||||||
|
@ -409,6 +414,7 @@ bool p3BanList::isAddressAccepted(
|
||||||
check_result = RSBANLIST_CHECK_RESULT_ACCEPTED;
|
check_result = RSBANLIST_CHECK_RESULT_ACCEPTED;
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void p3BanList::getWhiteListedIps(std::list<BanListPeer> &lst)
|
void p3BanList::getWhiteListedIps(std::list<BanListPeer> &lst)
|
||||||
{
|
{
|
||||||
RS_STACK_MUTEX(mBanMtx) ;
|
RS_STACK_MUTEX(mBanMtx) ;
|
||||||
|
@ -582,11 +588,6 @@ int p3BanList::tick()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int p3BanList::status()
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void p3BanList::getDhtInfo()
|
void p3BanList::getDhtInfo()
|
||||||
{
|
{
|
||||||
// Get the list of masquerading peers from the DHT. Add them as potential IPs to be banned.
|
// Get the list of masquerading peers from the DHT. Add them as potential IPs to be banned.
|
||||||
|
|
|
@ -105,7 +105,6 @@ public:
|
||||||
|
|
||||||
*/
|
*/
|
||||||
virtual int tick();
|
virtual int tick();
|
||||||
virtual int status();
|
|
||||||
|
|
||||||
int sendPackets();
|
int sendPackets();
|
||||||
bool processIncoming();
|
bool processIncoming();
|
||||||
|
|
|
@ -1433,13 +1433,15 @@ bool p3GxsChannels::createPostV2(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool p3GxsChannels::createCommentV2(const RsGxsGroupId& channelId,
|
bool p3GxsChannels::createCommentV2(
|
||||||
|
const RsGxsGroupId& channelId,
|
||||||
const RsGxsMessageId& threadId,
|
const RsGxsMessageId& threadId,
|
||||||
const RsGxsMessageId& parentId,
|
|
||||||
const RsGxsId& authorId,
|
|
||||||
const std::string& comment,
|
const std::string& comment,
|
||||||
|
const RsGxsId& authorId,
|
||||||
|
const RsGxsMessageId& parentId,
|
||||||
|
const RsGxsMessageId& origCommentId,
|
||||||
RsGxsMessageId& commentMessageId,
|
RsGxsMessageId& commentMessageId,
|
||||||
std::string& errorMessage)
|
std::string& errorMessage )
|
||||||
{
|
{
|
||||||
std::vector<RsGxsChannelGroup> channelsInfo;
|
std::vector<RsGxsChannelGroup> channelsInfo;
|
||||||
if(!getChannelsInfo(std::list<RsGxsGroupId>({channelId}),channelsInfo))
|
if(!getChannelsInfo(std::list<RsGxsGroupId>({channelId}),channelsInfo))
|
||||||
|
@ -1476,6 +1478,7 @@ bool p3GxsChannels::createCommentV2(const RsGxsGroupId& channelId,
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!parentId.isNull())
|
if(!parentId.isNull())
|
||||||
|
{
|
||||||
if(!getChannelContent( // does the post thread exist?
|
if(!getChannelContent( // does the post thread exist?
|
||||||
channelId,std::set<RsGxsMessageId>({parentId}),posts,comments ))
|
channelId,std::set<RsGxsMessageId>({parentId}),posts,comments ))
|
||||||
{
|
{
|
||||||
|
@ -1485,17 +1488,50 @@ bool p3GxsChannels::createCommentV2(const RsGxsGroupId& channelId,
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if(comments.size() != 1 || comments[0].mMeta.mParentId.isNull())
|
else
|
||||||
|
{
|
||||||
|
if(comments.size() != 1 || comments[0].mMeta.mParentId.isNull())
|
||||||
{ // is the comment parent actually a comment?
|
{ // is the comment parent actually a comment?
|
||||||
errorMessage = "You cannot comment post " + parentId.toStdString()
|
errorMessage = "You cannot comment post "
|
||||||
|
+ parentId.toStdString()
|
||||||
+ " of channel with Id " + channelId.toStdString() +
|
+ " of channel with Id " + channelId.toStdString() +
|
||||||
": supplied mParentMsgId is not a comment Id!";
|
": supplied mParentMsgId is not a comment Id!";
|
||||||
std::cerr << __PRETTY_FUNCTION__ << " Error: " << errorMessage
|
std::cerr << __PRETTY_FUNCTION__ << " Error: " << errorMessage
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(!rsIdentity->isOwnId(authorId)) // is the voter ID actually ours?
|
if(!origCommentId.isNull())
|
||||||
|
{
|
||||||
|
std::set<RsGxsMessageId> s({origCommentId});
|
||||||
|
std::vector<RsGxsChannelPost> posts;
|
||||||
|
std::vector<RsGxsComment> comments;
|
||||||
|
|
||||||
|
if( !getChannelContent(channelId, s, posts, comments) ||
|
||||||
|
comments.size() != 1 )
|
||||||
|
{
|
||||||
|
errorMessage = "You cannot edit comment "
|
||||||
|
+ origCommentId.toStdString()
|
||||||
|
+ " of channel with Id " + channelId.toStdString()
|
||||||
|
+ ": this post does not exist locally!";
|
||||||
|
RsErr() << __PRETTY_FUNCTION__ << " " << errorMessage << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const RsGxsId& commentAuthor = comments[0].mMeta.mAuthorId;
|
||||||
|
if(commentAuthor != authorId)
|
||||||
|
{
|
||||||
|
errorMessage = "Editor identity and creator doesn't match "
|
||||||
|
+ authorId.toStdString() + " != "
|
||||||
|
+ commentAuthor.toStdString();
|
||||||
|
RsErr() << __PRETTY_FUNCTION__ << " " << errorMessage << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!rsIdentity->isOwnId(authorId)) // is the author ID actually ours?
|
||||||
{
|
{
|
||||||
errorMessage = "You cannot comment to channel with Id " +
|
errorMessage = "You cannot comment to channel with Id " +
|
||||||
channelId.toStdString() + " with identity " +
|
channelId.toStdString() + " with identity " +
|
||||||
|
@ -1511,6 +1547,7 @@ bool p3GxsChannels::createCommentV2(const RsGxsGroupId& channelId,
|
||||||
cmt.mMeta.mThreadId = threadId;
|
cmt.mMeta.mThreadId = threadId;
|
||||||
cmt.mMeta.mParentId = parentId;
|
cmt.mMeta.mParentId = parentId;
|
||||||
cmt.mMeta.mAuthorId = authorId;
|
cmt.mMeta.mAuthorId = authorId;
|
||||||
|
cmt.mMeta.mOrigMsgId = origCommentId;
|
||||||
cmt.mComment = comment;
|
cmt.mComment = comment;
|
||||||
|
|
||||||
uint32_t token;
|
uint32_t token;
|
||||||
|
@ -1852,12 +1889,8 @@ bool p3GxsChannels::ExtraFileHash(const std::string& path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool p3GxsChannels::ExtraFileRemove(const RsFileHash &hash)
|
bool p3GxsChannels::ExtraFileRemove(const RsFileHash& hash)
|
||||||
{
|
{ return rsFiles->ExtraFileRemove(hash); }
|
||||||
//TransferRequestFlags tflags = RS_FILE_REQ_ANONYMOUS_ROUTING | RS_FILE_REQ_EXTRA;
|
|
||||||
RsFileHash fh = RsFileHash(hash);
|
|
||||||
return rsFiles->ExtraFileRemove(fh);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
/********************************************************************************************/
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
#include "gxs/rsgenexchange.h"
|
#include "gxs/rsgenexchange.h"
|
||||||
#include "gxs/gxstokenqueue.h"
|
#include "gxs/gxstokenqueue.h"
|
||||||
#include "util/rsmemory.h"
|
#include "util/rsmemory.h"
|
||||||
|
#include "util/rsdebug.h"
|
||||||
#include "util/rstickevent.h"
|
#include "util/rstickevent.h"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
@ -213,9 +213,12 @@ virtual bool ExtraFileRemove(const RsFileHash &hash);
|
||||||
|
|
||||||
/// Implementation of @see RsGxsChannels::createComment
|
/// Implementation of @see RsGxsChannels::createComment
|
||||||
virtual bool createCommentV2(
|
virtual bool createCommentV2(
|
||||||
const RsGxsGroupId& channelId, const RsGxsMessageId& threadId,
|
const RsGxsGroupId& channelId,
|
||||||
const RsGxsMessageId& parentId, const RsGxsId& authorId,
|
const RsGxsMessageId& threadId,
|
||||||
const std::string& comment,
|
const std::string& comment,
|
||||||
|
const RsGxsId& authorId,
|
||||||
|
const RsGxsMessageId& parentId = RsGxsMessageId(),
|
||||||
|
const RsGxsMessageId& origCommentId = RsGxsMessageId(),
|
||||||
RsGxsMessageId& commentMessageId = RS_DEFAULT_STORAGE_PARAM(RsGxsMessageId),
|
RsGxsMessageId& commentMessageId = RS_DEFAULT_STORAGE_PARAM(RsGxsMessageId),
|
||||||
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
|
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
|
||||||
) override;
|
) override;
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
* *
|
* *
|
||||||
* libretroshare: retroshare core library *
|
* libretroshare: retroshare core library *
|
||||||
* *
|
* *
|
||||||
* Copyright 2012-2012 Robert Fernie <retroshare@lunamutt.com> *
|
* Copyright (C) 2012-2014 Robert Fernie <retroshare@lunamutt.com> *
|
||||||
|
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||||
* *
|
* *
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
|
@ -21,8 +22,8 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
#include "services/p3gxsforums.h"
|
#include "services/p3gxsforums.h"
|
||||||
#include "rsitems/rsgxsforumitems.h"
|
#include "rsitems/rsgxsforumitems.h"
|
||||||
|
#include "retroshare/rspeers.h"
|
||||||
#include <retroshare/rsidentity.h>
|
#include "retroshare/rsidentity.h"
|
||||||
|
|
||||||
#include "rsserver/p3face.h"
|
#include "rsserver/p3face.h"
|
||||||
#include "retroshare/rsnotify.h"
|
#include "retroshare/rsnotify.h"
|
||||||
|
@ -384,6 +385,165 @@ bool p3GxsForums::getMsgData(const uint32_t &token, std::vector<RsGxsForumMsg> &
|
||||||
|
|
||||||
/********************************************************************************************/
|
/********************************************************************************************/
|
||||||
|
|
||||||
|
bool p3GxsForums::createForumV2(
|
||||||
|
const std::string& name, const std::string& description,
|
||||||
|
const RsGxsId& authorId, const std::set<RsGxsId>& moderatorsIds,
|
||||||
|
RsGxsCircleType circleType, const RsGxsCircleId& circleId,
|
||||||
|
RsGxsGroupId& forumId, std::string& errorMessage )
|
||||||
|
{
|
||||||
|
auto createFail = [&](std::string mErr)
|
||||||
|
{
|
||||||
|
errorMessage = mErr;
|
||||||
|
RsErr() << __PRETTY_FUNCTION__ << " " << errorMessage << std::endl;
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
if(name.empty()) return createFail("Forum name is required");
|
||||||
|
|
||||||
|
if(!authorId.isNull() && !rsIdentity->isOwnId(authorId))
|
||||||
|
return createFail("Author must be iether null or and identity owned by "
|
||||||
|
"this node");
|
||||||
|
|
||||||
|
switch(circleType)
|
||||||
|
{
|
||||||
|
case RsGxsCircleType::PUBLIC: // fallthrough
|
||||||
|
case RsGxsCircleType::LOCAL: // fallthrough
|
||||||
|
case RsGxsCircleType::YOUR_EYES_ONLY:
|
||||||
|
break;
|
||||||
|
case RsGxsCircleType::EXTERNAL:
|
||||||
|
if(circleId.isNull())
|
||||||
|
return createFail("circleType is EXTERNAL but circleId is null");
|
||||||
|
break;
|
||||||
|
case RsGxsCircleType::NODES_GROUP:
|
||||||
|
{
|
||||||
|
RsGroupInfo ginfo;
|
||||||
|
if(!rsPeers->getGroupInfo(RsNodeGroupId(circleId), ginfo))
|
||||||
|
return createFail("circleType is NODES_GROUP but circleId does not "
|
||||||
|
"correspond to an actual group of friends");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: return createFail("circleType has invalid value");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a consistent channel group meta from the information supplied
|
||||||
|
RsGxsForumGroup forum;
|
||||||
|
|
||||||
|
forum.mMeta.mGroupName = name;
|
||||||
|
forum.mMeta.mAuthorId = authorId;
|
||||||
|
forum.mMeta.mCircleType = static_cast<uint32_t>(circleType);
|
||||||
|
|
||||||
|
forum.mMeta.mSignFlags = GXS_SERV::FLAG_GROUP_SIGN_PUBLISH_NONEREQ
|
||||||
|
| GXS_SERV::FLAG_AUTHOR_AUTHENTICATION_REQUIRED;
|
||||||
|
|
||||||
|
forum.mMeta.mGroupFlags = GXS_SERV::FLAG_PRIVACY_PUBLIC;
|
||||||
|
|
||||||
|
forum.mMeta.mCircleId.clear();
|
||||||
|
forum.mMeta.mInternalCircle.clear();
|
||||||
|
|
||||||
|
switch(circleType)
|
||||||
|
{
|
||||||
|
case RsGxsCircleType::NODES_GROUP:
|
||||||
|
forum.mMeta.mInternalCircle = circleId; break;
|
||||||
|
case RsGxsCircleType::EXTERNAL:
|
||||||
|
forum.mMeta.mCircleId = circleId; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
forum.mDescription = description;
|
||||||
|
forum.mAdminList.ids = moderatorsIds;
|
||||||
|
|
||||||
|
uint32_t token;
|
||||||
|
if(!createGroup(token, forum))
|
||||||
|
return createFail("Failed creating GXS group.");
|
||||||
|
|
||||||
|
// wait for the group creation to complete.
|
||||||
|
RsTokenService::GxsRequestStatus wSt =
|
||||||
|
waitToken( token, std::chrono::milliseconds(5000),
|
||||||
|
std::chrono::milliseconds(20) );
|
||||||
|
if(wSt != RsTokenService::COMPLETE)
|
||||||
|
return createFail( "GXS operation waitToken failed with: "
|
||||||
|
+ std::to_string(wSt) );
|
||||||
|
|
||||||
|
if(!RsGenExchange::getPublishedGroupMeta(token, forum.mMeta))
|
||||||
|
return createFail("Failure getting updated group data.");
|
||||||
|
|
||||||
|
forumId = forum.mMeta.mGroupId;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool p3GxsForums::createPost(
|
||||||
|
const RsGxsGroupId& forumId, const std::string& title,
|
||||||
|
const std::string& mBody,
|
||||||
|
const RsGxsId& authorId, const RsGxsMessageId& parentId,
|
||||||
|
const RsGxsMessageId& origPostId, RsGxsMessageId& postMsgId,
|
||||||
|
std::string& errorMessage )
|
||||||
|
{
|
||||||
|
RsGxsForumMsg post;
|
||||||
|
|
||||||
|
auto failure = [&](std::string errMsg)
|
||||||
|
{
|
||||||
|
errorMessage = errMsg;
|
||||||
|
RsErr() << __PRETTY_FUNCTION__ << " " << errorMessage << std::endl;
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
if(title.empty()) return failure("Title is required");
|
||||||
|
|
||||||
|
if(authorId.isNull()) return failure("Author id is needed");
|
||||||
|
|
||||||
|
if(!rsIdentity->isOwnId(authorId))
|
||||||
|
return failure( "Author id: " + authorId.toStdString() + " is not of"
|
||||||
|
"own identity" );
|
||||||
|
|
||||||
|
if(!parentId.isNull())
|
||||||
|
{
|
||||||
|
std::vector<RsGxsForumMsg> msgs;
|
||||||
|
if( getForumContent(forumId, std::set<RsGxsMessageId>({parentId}), msgs)
|
||||||
|
&& msgs.size() == 1 )
|
||||||
|
{
|
||||||
|
post.mMeta.mParentId = parentId;
|
||||||
|
post.mMeta.mThreadId = msgs[0].mMeta.mThreadId;
|
||||||
|
}
|
||||||
|
else return failure("Parent post " + parentId.toStdString()
|
||||||
|
+ " doesn't exists locally");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<RsGxsForumGroup> forumInfo;
|
||||||
|
if(!getForumsInfo(std::list<RsGxsGroupId>({forumId}), forumInfo))
|
||||||
|
return failure( "Forum with Id " + forumId.toStdString()
|
||||||
|
+ " does not exist locally." );
|
||||||
|
|
||||||
|
if(!origPostId.isNull())
|
||||||
|
{
|
||||||
|
std::vector<RsGxsForumMsg> msgs;
|
||||||
|
if( getForumContent( forumId,
|
||||||
|
std::set<RsGxsMessageId>({origPostId}), msgs)
|
||||||
|
&& msgs.size() == 1 )
|
||||||
|
post.mMeta.mOrigMsgId = origPostId;
|
||||||
|
else return failure("Original post " + origPostId.toStdString()
|
||||||
|
+ " doesn't exists locally");
|
||||||
|
}
|
||||||
|
|
||||||
|
post.mMeta.mGroupId = forumId;
|
||||||
|
post.mMeta.mMsgName = title;
|
||||||
|
post.mMeta.mAuthorId = authorId;
|
||||||
|
post.mMsg = mBody;
|
||||||
|
|
||||||
|
uint32_t token;
|
||||||
|
if( !createMsg(token, post)
|
||||||
|
|| waitToken(
|
||||||
|
token,
|
||||||
|
std::chrono::milliseconds(5000) ) != RsTokenService::COMPLETE )
|
||||||
|
return failure("Failure creating GXS message");
|
||||||
|
|
||||||
|
if(!RsGenExchange::getPublishedMsgMeta(token, post.mMeta))
|
||||||
|
return failure("Failure getting created GXS message metadata");
|
||||||
|
|
||||||
|
postMsgId = post.mMeta.mMsgId;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool p3GxsForums::createForum(RsGxsForumGroup& forum)
|
bool p3GxsForums::createForum(RsGxsForumGroup& forum)
|
||||||
{
|
{
|
||||||
uint32_t token;
|
uint32_t token;
|
||||||
|
@ -461,7 +621,8 @@ bool p3GxsForums::getForumsInfo(
|
||||||
}
|
}
|
||||||
|
|
||||||
bool p3GxsForums::getForumContent(
|
bool p3GxsForums::getForumContent(
|
||||||
const RsGxsGroupId& forumId, std::set<RsGxsMessageId>& msgs_to_request,
|
const RsGxsGroupId& forumId,
|
||||||
|
const std::set<RsGxsMessageId>& msgs_to_request,
|
||||||
std::vector<RsGxsForumMsg>& msgs )
|
std::vector<RsGxsForumMsg>& msgs )
|
||||||
{
|
{
|
||||||
uint32_t token;
|
uint32_t token;
|
||||||
|
@ -813,3 +974,37 @@ void p3GxsForums::handle_event(uint32_t event_type, const std::string &/*elabel*
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RsGxsForumGroup::serial_process(
|
||||||
|
RsGenericSerializer::SerializeJob j,
|
||||||
|
RsGenericSerializer::SerializeContext& ctx )
|
||||||
|
{
|
||||||
|
RS_SERIAL_PROCESS(mMeta);
|
||||||
|
RS_SERIAL_PROCESS(mDescription);
|
||||||
|
|
||||||
|
/* Work around to have usable JSON API, without breaking binary
|
||||||
|
* serialization retrocompatibility */
|
||||||
|
switch (j)
|
||||||
|
{
|
||||||
|
case RsGenericSerializer::TO_JSON: // fallthrough
|
||||||
|
case RsGenericSerializer::FROM_JSON:
|
||||||
|
RsTypeSerializer::serial_process( j, ctx,
|
||||||
|
mAdminList.ids, "mAdminList" );
|
||||||
|
RsTypeSerializer::serial_process( j, ctx,
|
||||||
|
mPinnedPosts.ids, "mPinnedPosts" );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
RS_SERIAL_PROCESS(mAdminList);
|
||||||
|
RS_SERIAL_PROCESS(mPinnedPosts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RsGxsForumGroup::canEditPosts(const RsGxsId& id) const
|
||||||
|
{
|
||||||
|
return mAdminList.ids.find(id) != mAdminList.ids.end() ||
|
||||||
|
id == mMeta.mAuthorId;
|
||||||
|
}
|
||||||
|
|
||||||
|
RsGxsForumGroup::~RsGxsForumGroup() = default;
|
||||||
|
RsGxsForumMsg::~RsGxsForumMsg() = default;
|
||||||
|
RsGxsForums::~RsGxsForums() = default;
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
* *
|
* *
|
||||||
* libretroshare: retroshare core library *
|
* libretroshare: retroshare core library *
|
||||||
* *
|
* *
|
||||||
* Copyright 2012-2012 Robert Fernie <retroshare@lunamutt.com> *
|
* Copyright (C) 2012-2014 Robert Fernie <retroshare@lunamutt.com> *
|
||||||
|
* Copyright (C) 2018-2019 Gioacchino Mazzurco <gio@eigenlab.org> *
|
||||||
* *
|
* *
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
|
@ -19,21 +20,17 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||||
* *
|
* *
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
#ifndef P3_GXSFORUMS_SERVICE_HEADER
|
#pragma once
|
||||||
#define P3_GXSFORUMS_SERVICE_HEADER
|
|
||||||
|
|
||||||
|
|
||||||
#include "retroshare/rsgxsforums.h"
|
|
||||||
#include "gxs/rsgenexchange.h"
|
|
||||||
|
|
||||||
#include "util/rstickevent.h"
|
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
/*
|
#include "retroshare/rsgxsforums.h"
|
||||||
*
|
#include "gxs/rsgenexchange.h"
|
||||||
*/
|
#include "retroshare/rsgxscircles.h"
|
||||||
|
#include "util/rstickevent.h"
|
||||||
|
#include "util/rsdebug.h"
|
||||||
|
|
||||||
|
|
||||||
class p3GxsForums: public RsGenExchange, public RsGxsForums, public p3Config,
|
class p3GxsForums: public RsGenExchange, public RsGxsForums, public p3Config,
|
||||||
public RsTickEvent /* only needed for testing - remove after */
|
public RsTickEvent /* only needed for testing - remove after */
|
||||||
|
@ -55,14 +52,39 @@ protected:
|
||||||
virtual bool loadList(std::list<RsItem *>& loadList); // @see p3Config::loadList(std::list<RsItem *>&)
|
virtual bool loadList(std::list<RsItem *>& loadList); // @see p3Config::loadList(std::list<RsItem *>&)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// @see RsGxsForums::createForum
|
/// @see RsGxsForums::createForumV2
|
||||||
|
bool createForumV2(
|
||||||
|
const std::string& name, const std::string& description,
|
||||||
|
const RsGxsId& authorId = RsGxsId(),
|
||||||
|
const std::set<RsGxsId>& moderatorsIds = std::set<RsGxsId>(),
|
||||||
|
RsGxsCircleType circleType = RsGxsCircleType::PUBLIC,
|
||||||
|
const RsGxsCircleId& circleId = RsGxsCircleId(),
|
||||||
|
RsGxsGroupId& forumId = RS_DEFAULT_STORAGE_PARAM(RsGxsGroupId),
|
||||||
|
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
|
||||||
|
) override;
|
||||||
|
|
||||||
|
/// @see RsGxsForums::createPost
|
||||||
|
bool createPost(
|
||||||
|
const RsGxsGroupId& forumId,
|
||||||
|
const std::string& title,
|
||||||
|
const std::string& mBody,
|
||||||
|
const RsGxsId& authorId,
|
||||||
|
const RsGxsMessageId& parentId = RsGxsMessageId(),
|
||||||
|
const RsGxsMessageId& origPostId = RsGxsMessageId(),
|
||||||
|
RsGxsMessageId& postMsgId = RS_DEFAULT_STORAGE_PARAM(RsGxsMessageId),
|
||||||
|
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
|
||||||
|
) override;
|
||||||
|
|
||||||
|
/// @see RsGxsForums::createForum @deprecated
|
||||||
|
RS_DEPRECATED_FOR(createForumV2)
|
||||||
virtual bool createForum(RsGxsForumGroup& forum);
|
virtual bool createForum(RsGxsForumGroup& forum);
|
||||||
|
|
||||||
/// @see RsGxsForums::createMessage
|
/// @see RsGxsForums::createMessage @deprecated
|
||||||
|
RS_DEPRECATED_FOR(createPost)
|
||||||
virtual bool createMessage(RsGxsForumMsg& message);
|
virtual bool createMessage(RsGxsForumMsg& message);
|
||||||
|
|
||||||
/// @see RsGxsForums::editForum
|
/// @see RsGxsForums::editForum
|
||||||
virtual bool editForum(RsGxsForumGroup& forum);
|
virtual bool editForum(RsGxsForumGroup& forum) override;
|
||||||
|
|
||||||
/// @see RsGxsForums::getForumsSummaries
|
/// @see RsGxsForums::getForumsSummaries
|
||||||
virtual bool getForumsSummaries(std::list<RsGroupMetaData>& forums);
|
virtual bool getForumsSummaries(std::list<RsGroupMetaData>& forums);
|
||||||
|
@ -78,7 +100,7 @@ public:
|
||||||
/// @see RsGxsForums::getForumContent
|
/// @see RsGxsForums::getForumContent
|
||||||
virtual bool getForumContent(
|
virtual bool getForumContent(
|
||||||
const RsGxsGroupId& forumId,
|
const RsGxsGroupId& forumId,
|
||||||
std::set<RsGxsMessageId>& msgs_to_request,
|
const std::set<RsGxsMessageId>& msgs_to_request,
|
||||||
std::vector<RsGxsForumMsg>& msgs );
|
std::vector<RsGxsForumMsg>& msgs );
|
||||||
|
|
||||||
/// @see RsGxsForums::markRead
|
/// @see RsGxsForums::markRead
|
||||||
|
@ -130,5 +152,3 @@ bool generateGroup(uint32_t &token, std::string groupName);
|
||||||
std::map<RsGxsGroupId,rstime_t> mKnownForums ;
|
std::map<RsGxsGroupId,rstime_t> mKnownForums ;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* libretroshare/src/services: p3idservice.cc *
|
* libretroshare/src/services: p3idservice.cc *
|
||||||
* *
|
* *
|
||||||
* libretroshare: retroshare core library *
|
* Copyright (C) 2012-2014 Robert Fernie <retroshare@lunamutt.com> *
|
||||||
* *
|
* Copyright (C) 2017-2019 Gioacchino Mazzurco <gio@altermundi.net> *
|
||||||
* Copyright 2012-2012 Robert Fernie <retroshare@lunamutt.com> *
|
|
||||||
* Copyright (C) 2018 Gioacchino Mazzurco <gio@eigenlab.org> *
|
|
||||||
* *
|
* *
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
|
@ -20,8 +18,14 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||||
* *
|
* *
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
|
/// RetroShare GXS identities service
|
||||||
|
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <sstream>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
#include "services/p3idservice.h"
|
#include "services/p3idservice.h"
|
||||||
#include "pgp/pgpauxutils.h"
|
#include "pgp/pgpauxutils.h"
|
||||||
|
@ -36,15 +40,9 @@
|
||||||
#include "crypto/hashstream.h"
|
#include "crypto/hashstream.h"
|
||||||
#include "gxs/gxssecurity.h"
|
#include "gxs/gxssecurity.h"
|
||||||
#include "retroshare/rspeers.h"
|
#include "retroshare/rspeers.h"
|
||||||
|
#include "retroshare/rsnotify.h"
|
||||||
|
|
||||||
|
|
||||||
//#include "pqi/authgpg.h"
|
|
||||||
|
|
||||||
//#include <retroshare/rspeers.h>
|
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
/****
|
/****
|
||||||
* #define DEBUG_IDS 1
|
* #define DEBUG_IDS 1
|
||||||
* #define DEBUG_RECOGN 1
|
* #define DEBUG_RECOGN 1
|
||||||
|
@ -71,7 +69,7 @@ static const uint32_t MAX_DELAY_BEFORE_CLEANING= 1800 ; // clean old keys eve
|
||||||
|
|
||||||
static const uint32_t MAX_SERIALISED_IDENTITY_AGE = 600 ; // after 10 mins, a serialised identity record must be renewed.
|
static const uint32_t MAX_SERIALISED_IDENTITY_AGE = 600 ; // after 10 mins, a serialised identity record must be renewed.
|
||||||
|
|
||||||
RsIdentity *rsIdentity = NULL;
|
RsIdentity* rsIdentity = nullptr;
|
||||||
|
|
||||||
/******
|
/******
|
||||||
* Some notes:
|
* Some notes:
|
||||||
|
@ -757,7 +755,7 @@ bool p3IdService::isOwnId(const RsGxsId& id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool p3IdService::getOwnSignedIds(std::vector<RsGxsId> ids)
|
bool p3IdService::getOwnSignedIds(std::vector<RsGxsId>& ids)
|
||||||
{
|
{
|
||||||
ids.clear();
|
ids.clear();
|
||||||
|
|
||||||
|
@ -769,27 +767,29 @@ bool p3IdService::getOwnSignedIds(std::vector<RsGxsId> ids)
|
||||||
if(ownIdsAreLoaded())
|
if(ownIdsAreLoaded())
|
||||||
{
|
{
|
||||||
RS_STACK_MUTEX(mIdMtx);
|
RS_STACK_MUTEX(mIdMtx);
|
||||||
ids.reserve(mOwnSignedIds.size());
|
ids.resize(mOwnSignedIds.size());
|
||||||
ids.insert(ids.end(), mOwnSignedIds.begin(), mOwnSignedIds.end());
|
std::copy(mOwnSignedIds.begin(), mOwnSignedIds.end(), ids.begin());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool p3IdService::getOwnPseudonimousIds(std::vector<RsGxsId> ids)
|
bool p3IdService::getOwnPseudonimousIds(std::vector<RsGxsId>& ids)
|
||||||
{
|
{
|
||||||
ids.clear();
|
ids.clear();
|
||||||
std::vector<RsGxsId> signedV;
|
std::vector<RsGxsId> signedV;
|
||||||
|
|
||||||
// this implicitely ensure ids are already loaded ;)
|
// this implicitely ensure ids are already loaded ;)
|
||||||
if(!getOwnSignedIds(signedV)) return false;
|
if(!getOwnSignedIds(signedV)) return false;
|
||||||
|
|
||||||
std::set<RsGxsId> signedS(signedV.begin(), signedV.end());
|
std::set<RsGxsId> signedS(signedV.begin(), signedV.end());
|
||||||
|
|
||||||
{
|
{
|
||||||
RS_STACK_MUTEX(mIdMtx);
|
RS_STACK_MUTEX(mIdMtx);
|
||||||
std::copy_if(mOwnIds.begin(), mOwnIds.end(), ids.end(),
|
ids.resize(mOwnIds.size() - signedV.size());
|
||||||
[&](const RsGxsId& id) {return !signedS.count(id);});
|
std::copy_if( mOwnIds.begin(), mOwnIds.end(), ids.begin(),
|
||||||
|
[&](const RsGxsId& id) {return !signedS.count(id);} );
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -908,40 +908,75 @@ bool p3IdService::createIdentity(
|
||||||
const std::string& name, const RsGxsImage& avatar,
|
const std::string& name, const RsGxsImage& avatar,
|
||||||
bool pseudonimous, const std::string& pgpPassword)
|
bool pseudonimous, const std::string& pgpPassword)
|
||||||
{
|
{
|
||||||
if(!pgpPassword.empty())
|
bool ret = true;
|
||||||
std::cerr<< __PRETTY_FUNCTION__ << " Warning! PGP Password handling "
|
|
||||||
<< "not implemented yet!" << std::endl;
|
|
||||||
|
|
||||||
RsIdentityParameters params;
|
RsIdentityParameters params;
|
||||||
|
uint32_t token = 0;
|
||||||
|
RsGroupMetaData meta;
|
||||||
|
RsTokenService::GxsRequestStatus wtStatus = RsTokenService::CANCELLED;
|
||||||
|
|
||||||
|
if(!pseudonimous && !pgpPassword.empty())
|
||||||
|
{
|
||||||
|
if(!rsNotify->cachePgpPassphrase(pgpPassword))
|
||||||
|
{
|
||||||
|
RsErr() << __PRETTY_FUNCTION__ << " Failure caching password"
|
||||||
|
<< std::endl;
|
||||||
|
ret = false;
|
||||||
|
goto LabelCreateIdentityCleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!rsNotify->setDisableAskPassword(true))
|
||||||
|
{
|
||||||
|
RsErr() << __PRETTY_FUNCTION__ << " Failure disabling password user"
|
||||||
|
<< " request" << std::endl;
|
||||||
|
ret = false;
|
||||||
|
goto LabelCreateIdentityCleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
params.isPgpLinked = !pseudonimous;
|
params.isPgpLinked = !pseudonimous;
|
||||||
params.nickname = name;
|
params.nickname = name;
|
||||||
params.mImage = avatar;
|
params.mImage = avatar;
|
||||||
|
|
||||||
uint32_t token;
|
|
||||||
if(!createIdentity(token, params))
|
if(!createIdentity(token, params))
|
||||||
{
|
{
|
||||||
std::cerr << __PRETTY_FUNCTION__ << " Error! Failed creating group."
|
RsErr() << __PRETTY_FUNCTION__ << " Failed creating GXS group."
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
return false;
|
ret = false;
|
||||||
|
goto LabelCreateIdentityCleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(waitToken(token) != RsTokenService::COMPLETE)
|
/* Use custom timeout for waitToken because creating identities involves
|
||||||
|
* creating multiple signatures, which can take a lot of time expecially on
|
||||||
|
* slow hardware like phones or embedded devices */
|
||||||
|
if( (wtStatus = waitToken(
|
||||||
|
token, std::chrono::seconds(10), std::chrono::milliseconds(20) ))
|
||||||
|
!= RsTokenService::COMPLETE )
|
||||||
{
|
{
|
||||||
std::cerr << __PRETTY_FUNCTION__ << " Error! GXS operation failed."
|
RsErr() << __PRETTY_FUNCTION__ << " waitToken("<< token
|
||||||
<< std::endl;
|
<< ") failed with: " << wtStatus << std::endl;
|
||||||
return false;
|
ret = false;
|
||||||
|
goto LabelCreateIdentityCleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
RsGroupMetaData meta;
|
|
||||||
if(!RsGenExchange::getPublishedGroupMeta(token, meta))
|
if(!RsGenExchange::getPublishedGroupMeta(token, meta))
|
||||||
{
|
{
|
||||||
std::cerr << __PRETTY_FUNCTION__ << "Error! Failure getting updated "
|
RsErr() << __PRETTY_FUNCTION__ << " Failure getting updated group data."
|
||||||
<< " group data." << std::endl;
|
<< std::endl;
|
||||||
return false;
|
ret = false;
|
||||||
|
goto LabelCreateIdentityCleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
id = RsGxsId(meta.mGroupId);
|
id = RsGxsId(meta.mGroupId);
|
||||||
return true;
|
|
||||||
|
|
||||||
|
LabelCreateIdentityCleanup:
|
||||||
|
if(!pseudonimous && !pgpPassword.empty())
|
||||||
|
{
|
||||||
|
rsNotify->setDisableAskPassword(false);
|
||||||
|
rsNotify->clearPgpPassphrase();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool p3IdService::createIdentity(uint32_t& token, RsIdentityParameters ¶ms)
|
bool p3IdService::createIdentity(uint32_t& token, RsIdentityParameters ¶ms)
|
||||||
|
@ -1151,6 +1186,16 @@ static void mergeIds(std::map<RsGxsId,std::list<RsPeerId> >& idmap,const RsGxsId
|
||||||
old_peers.push_back(*it) ;
|
old_peers.push_back(*it) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool p3IdService::requestIdentity(const RsGxsId& id)
|
||||||
|
{
|
||||||
|
RsIdentityUsage usageInfo( RsServiceType::GXSID,
|
||||||
|
RsIdentityUsage::IDENTITY_DATA_UPDATE );
|
||||||
|
std::list<RsPeerId> onlinePeers;
|
||||||
|
|
||||||
|
return rsPeers && rsPeers->getOnlineList(onlinePeers)
|
||||||
|
&& requestKey(id, onlinePeers, usageInfo);
|
||||||
|
}
|
||||||
|
|
||||||
bool p3IdService::requestKey(const RsGxsId &id, const std::list<RsPeerId>& peers,const RsIdentityUsage& use_info)
|
bool p3IdService::requestKey(const RsGxsId &id, const std::list<RsPeerId>& peers,const RsIdentityUsage& use_info)
|
||||||
{
|
{
|
||||||
if(id.isNull())
|
if(id.isNull())
|
||||||
|
@ -3297,13 +3342,10 @@ static void calcPGPHash(const RsGxsId &id, const PGPFingerprintType &pgp, Sha1Ch
|
||||||
|
|
||||||
|
|
||||||
// Must Use meta.
|
// Must Use meta.
|
||||||
RsGenExchange::ServiceCreate_Return p3IdService::service_CreateGroup(RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& keySet)
|
RsGenExchange::ServiceCreate_Return p3IdService::service_CreateGroup(
|
||||||
|
RsGxsGrpItem* grpItem, RsTlvSecurityKeySet& keySet )
|
||||||
{
|
{
|
||||||
|
Dbg2() << __PRETTY_FUNCTION__ << std::endl;
|
||||||
#ifdef DEBUG_IDS
|
|
||||||
std::cerr << "p3IdService::service_CreateGroup()";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif // DEBUG_IDS
|
|
||||||
|
|
||||||
RsGxsIdGroupItem *item = dynamic_cast<RsGxsIdGroupItem *>(grpItem);
|
RsGxsIdGroupItem *item = dynamic_cast<RsGxsIdGroupItem *>(grpItem);
|
||||||
if (!item)
|
if (!item)
|
||||||
|
@ -3313,18 +3355,12 @@ RsGenExchange::ServiceCreate_Return p3IdService::service_CreateGroup(RsGxsGrpIte
|
||||||
return SERVICE_CREATE_FAIL;
|
return SERVICE_CREATE_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_IDS
|
|
||||||
std::cerr << "p3IdService::service_CreateGroup() Item is:";
|
|
||||||
std::cerr << std::endl;
|
|
||||||
item->print(std::cerr);
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif // DEBUG_IDS
|
|
||||||
|
|
||||||
item->meta.mGroupId.clear();
|
item->meta.mGroupId.clear();
|
||||||
|
|
||||||
/********************* TEMP HACK UNTIL GXS FILLS IN GROUP_ID *****************/
|
/********************* TEMP HACK UNTIL GXS FILLS IN GROUP_ID *****************/
|
||||||
// find private admin key
|
// find private admin key
|
||||||
for(std::map<RsGxsId, RsTlvPrivateRSAKey>::iterator mit = keySet.private_keys.begin();mit != keySet.private_keys.end(); ++mit)
|
for( std::map<RsGxsId, RsTlvPrivateRSAKey>::iterator mit =
|
||||||
|
keySet.private_keys.begin(); mit != keySet.private_keys.end(); ++mit )
|
||||||
if(mit->second.keyFlags == (RSTLV_KEY_DISTRIB_ADMIN | RSTLV_KEY_TYPE_FULL))
|
if(mit->second.keyFlags == (RSTLV_KEY_DISTRIB_ADMIN | RSTLV_KEY_TYPE_FULL))
|
||||||
{
|
{
|
||||||
item->meta.mGroupId = RsGxsGroupId(mit->second.keyId);
|
item->meta.mGroupId = RsGxsGroupId(mit->second.keyId);
|
||||||
|
@ -3333,8 +3369,7 @@ RsGenExchange::ServiceCreate_Return p3IdService::service_CreateGroup(RsGxsGrpIte
|
||||||
|
|
||||||
if(item->meta.mGroupId.isNull())
|
if(item->meta.mGroupId.isNull())
|
||||||
{
|
{
|
||||||
std::cerr << "p3IdService::service_CreateGroup() ERROR no admin key";
|
RsErr() << __PRETTY_FUNCTION__ << " missing admin key!" << std::endl;
|
||||||
std::cerr << std::endl;
|
|
||||||
return SERVICE_CREATE_FAIL;
|
return SERVICE_CREATE_FAIL;
|
||||||
}
|
}
|
||||||
mKeysTS[RsGxsId(item->meta.mGroupId)].TS = time(NULL) ;
|
mKeysTS[RsGxsId(item->meta.mGroupId)].TS = time(NULL) ;
|
||||||
|
@ -3384,8 +3419,7 @@ RsGenExchange::ServiceCreate_Return p3IdService::service_CreateGroup(RsGxsGrpIte
|
||||||
/* create the hash */
|
/* create the hash */
|
||||||
Sha1CheckSum hash;
|
Sha1CheckSum hash;
|
||||||
|
|
||||||
/* */
|
RsPgpFingerprint ownFinger;
|
||||||
PGPFingerprintType ownFinger;
|
|
||||||
RsPgpId ownId(mPgpUtils->getPGPOwnId());
|
RsPgpId ownId(mPgpUtils->getPGPOwnId());
|
||||||
|
|
||||||
#ifdef DEBUG_IDS
|
#ifdef DEBUG_IDS
|
||||||
|
@ -3400,10 +3434,10 @@ RsGenExchange::ServiceCreate_Return p3IdService::service_CreateGroup(RsGxsGrpIte
|
||||||
// }
|
// }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!mPgpUtils->getKeyFingerprint(ownId,ownFinger))
|
if(!mPgpUtils->getKeyFingerprint(ownId,ownFinger))
|
||||||
{
|
{
|
||||||
std::cerr << "p3IdService::service_CreateGroup() ERROR Own Finger is stuck";
|
RsErr() << __PRETTY_FUNCTION__
|
||||||
std::cerr << std::endl;
|
<< " failure retriving own PGP fingerprint" << std::endl;
|
||||||
return SERVICE_CREATE_FAIL; // abandon attempt!
|
return SERVICE_CREATE_FAIL; // abandon attempt!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3428,59 +3462,68 @@ RsGenExchange::ServiceCreate_Return p3IdService::service_CreateGroup(RsGxsGrpIte
|
||||||
#define MAX_SIGN_SIZE 2048
|
#define MAX_SIGN_SIZE 2048
|
||||||
uint8_t signarray[MAX_SIGN_SIZE];
|
uint8_t signarray[MAX_SIGN_SIZE];
|
||||||
unsigned int sign_size = MAX_SIGN_SIZE;
|
unsigned int sign_size = MAX_SIGN_SIZE;
|
||||||
int result ;
|
|
||||||
|
|
||||||
memset(signarray,0,MAX_SIGN_SIZE) ; // just in case.
|
memset(signarray,0,MAX_SIGN_SIZE) ; // just in case.
|
||||||
|
|
||||||
mPgpUtils->askForDeferredSelfSignature((void *) hash.toByteArray(), hash.SIZE_IN_BYTES, signarray, &sign_size,result, "p3IdService::service_CreateGroup()") ;
|
/* -10 is never returned by askForDeferredSelfSignature therefore we can
|
||||||
|
* use it to properly detect and handle the case libretroshare is being
|
||||||
|
* used outside retroshare-gui */
|
||||||
|
int result = -10;
|
||||||
|
|
||||||
|
/* This method is DEPRECATED we call it only for retrocompatibility with
|
||||||
|
* retroshare-gui, when called from something different then
|
||||||
|
* retroshare-gui for example retroshare-service it miserably fail! */
|
||||||
|
mPgpUtils->askForDeferredSelfSignature(
|
||||||
|
static_cast<const void*>(hash.toByteArray()),
|
||||||
|
hash.SIZE_IN_BYTES, signarray, &sign_size, result,
|
||||||
|
__PRETTY_FUNCTION__ );
|
||||||
|
|
||||||
|
/* If askForDeferredSelfSignature left result untouched it means
|
||||||
|
* libretroshare is being used by something different then
|
||||||
|
* retroshare-gui so try calling AuthGPG::getAuthGPG()->SignDataBin
|
||||||
|
* directly */
|
||||||
|
if( result == -10 )
|
||||||
|
result = AuthGPG::getAuthGPG()->SignDataBin(
|
||||||
|
static_cast<const void*>(hash.toByteArray()),
|
||||||
|
hash.SIZE_IN_BYTES, signarray, &sign_size,
|
||||||
|
__PRETTY_FUNCTION__ )
|
||||||
|
?
|
||||||
|
SELF_SIGNATURE_RESULT_SUCCESS :
|
||||||
|
SELF_SIGNATURE_RESULT_FAILED;
|
||||||
|
|
||||||
/* error */
|
|
||||||
switch(result)
|
switch(result)
|
||||||
{
|
{
|
||||||
case SELF_SIGNATURE_RESULT_PENDING : createStatus = SERVICE_CREATE_FAIL_TRY_LATER;
|
case SELF_SIGNATURE_RESULT_PENDING:
|
||||||
std::cerr << "p3IdService::service_CreateGroup() signature still pending" << std::endl;
|
createStatus = SERVICE_CREATE_FAIL_TRY_LATER;
|
||||||
break ;
|
Dbg1() << __PRETTY_FUNCTION__ << " signature still pending"
|
||||||
default:
|
<< std::endl;
|
||||||
case SELF_SIGNATURE_RESULT_FAILED: return SERVICE_CREATE_FAIL ;
|
break;
|
||||||
std::cerr << "p3IdService::service_CreateGroup() signature failed" << std::endl;
|
|
||||||
break ;
|
|
||||||
|
|
||||||
case SELF_SIGNATURE_RESULT_SUCCESS:
|
case SELF_SIGNATURE_RESULT_SUCCESS:
|
||||||
{
|
{
|
||||||
// Additional consistency checks.
|
// Additional consistency checks.
|
||||||
|
|
||||||
if(sign_size == MAX_SIGN_SIZE)
|
if(sign_size == MAX_SIGN_SIZE)
|
||||||
{
|
{
|
||||||
std::cerr << "Inconsistent result. Signature uses full buffer. This is probably an error." << std::endl;
|
RsErr() << __PRETTY_FUNCTION__ << "Inconsistent result. "
|
||||||
return SERVICE_CREATE_FAIL; // abandon attempt!
|
<< "Signature uses full buffer. This is probably an "
|
||||||
|
<< "error." << std::endl;
|
||||||
|
return SERVICE_CREATE_FAIL;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_IDS
|
|
||||||
std::cerr << "p3IdService::service_CreateGroup() Signature: ";
|
|
||||||
std::string strout;
|
|
||||||
#endif
|
|
||||||
/* push binary into string -> really bad! */
|
/* push binary into string -> really bad! */
|
||||||
item->mPgpIdSign = "";
|
item->mPgpIdSign = "";
|
||||||
for(unsigned int i = 0; i < sign_size; i++)
|
for(unsigned int i = 0; i < sign_size; i++)
|
||||||
{
|
item->mPgpIdSign += static_cast<char>(signarray[i]);
|
||||||
#ifdef DEBUG_IDS
|
|
||||||
rs_sprintf_append(strout, "%02x", (uint32_t) signarray[i]);
|
|
||||||
#endif
|
|
||||||
item->mPgpIdSign += signarray[i];
|
|
||||||
}
|
|
||||||
createStatus = SERVICE_CREATE_SUCCESS;
|
|
||||||
|
|
||||||
#ifdef DEBUG_IDS
|
|
||||||
std::cerr << strout;
|
|
||||||
std::cerr << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* done! */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
createStatus = SERVICE_CREATE_SUCCESS;
|
createStatus = SERVICE_CREATE_SUCCESS;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
case SELF_SIGNATURE_RESULT_FAILED: /* fall-through */
|
||||||
|
default:
|
||||||
|
RsErr() << __PRETTY_FUNCTION__ << " signature failed with: "
|
||||||
|
<< result << std::endl;
|
||||||
|
return SERVICE_CREATE_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else createStatus = SERVICE_CREATE_SUCCESS;
|
||||||
|
|
||||||
// Enforce no AuthorId.
|
// Enforce no AuthorId.
|
||||||
item->meta.mAuthorId.clear() ;
|
item->meta.mAuthorId.clear() ;
|
||||||
|
@ -3492,15 +3535,16 @@ RsGenExchange::ServiceCreate_Return p3IdService::service_CreateGroup(RsGxsGrpIte
|
||||||
// this allows the user interface
|
// this allows the user interface
|
||||||
// to see the grp id on the list of ownIds immediately after the group was created
|
// to see the grp id on the list of ownIds immediately after the group was created
|
||||||
{
|
{
|
||||||
RsStackMutex stack(mIdMtx);
|
RS_STACK_MUTEX(mIdMtx);
|
||||||
RsGxsId gxsId(item->meta.mGroupId);
|
RsGxsId gxsId(item->meta.mGroupId);
|
||||||
if (std::find(mOwnIds.begin(), mOwnIds.end(), gxsId) == mOwnIds.end())
|
if (std::find(mOwnIds.begin(), mOwnIds.end(), gxsId) == mOwnIds.end())
|
||||||
{
|
{
|
||||||
mOwnIds.push_back(gxsId);
|
mOwnIds.push_back(gxsId);
|
||||||
mKeysTS[gxsId].TS = time(NULL) ;
|
mKeysTS[gxsId].TS = time(nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Dbg2() << __PRETTY_FUNCTION__ << " returns: " << createStatus << std::endl;
|
||||||
return createStatus;
|
return createStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4678,12 +4722,34 @@ void RsGxsIdGroup::serial_process(
|
||||||
RS_SERIAL_PROCESS(mReputation);
|
RS_SERIAL_PROCESS(mReputation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RsIdentityUsage::RsIdentityUsage(
|
||||||
|
RsServiceType service, RsIdentityUsage::UsageCode code,
|
||||||
|
const RsGxsGroupId& gid, const RsGxsMessageId& mid,
|
||||||
|
uint64_t additional_id, const std::string& comment ) :
|
||||||
|
mServiceId(service), mUsageCode(code), mGrpId(gid), mMsgId(mid),
|
||||||
|
mAdditionalId(additional_id), mComment(comment)
|
||||||
|
{
|
||||||
|
/* This is a hack, since it will hash also mHash, but because it is
|
||||||
|
* initialized to 0, and only computed in the constructor here, it should
|
||||||
|
* be ok. */
|
||||||
|
librs::crypto::HashStream hs(librs::crypto::HashStream::SHA1);
|
||||||
|
|
||||||
|
hs << static_cast<uint32_t>(service); // G10h4ck: Why uint32 if it's 16 bits?
|
||||||
|
hs << static_cast<uint8_t>(code);
|
||||||
|
hs << gid;
|
||||||
|
hs << mid;
|
||||||
|
hs << static_cast<uint64_t>(additional_id);
|
||||||
|
hs << comment;
|
||||||
|
|
||||||
|
mHash = hs.hash();
|
||||||
|
}
|
||||||
|
|
||||||
RsIdentityUsage::RsIdentityUsage(
|
RsIdentityUsage::RsIdentityUsage(
|
||||||
uint16_t service, const RsIdentityUsage::UsageCode& code,
|
uint16_t service, const RsIdentityUsage::UsageCode& code,
|
||||||
const RsGxsGroupId& gid, const RsGxsMessageId& mid,
|
const RsGxsGroupId& gid, const RsGxsMessageId& mid,
|
||||||
uint64_t additional_id,const std::string& comment ) :
|
uint64_t additional_id,const std::string& comment ) :
|
||||||
mServiceId(service), mUsageCode(code), mGrpId(gid), mMsgId(mid),
|
mServiceId(static_cast<RsServiceType>(service)), mUsageCode(code),
|
||||||
mAdditionalId(additional_id), mComment(comment)
|
mGrpId(gid), mMsgId(mid), mAdditionalId(additional_id), mComment(comment)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_IDS
|
#ifdef DEBUG_IDS
|
||||||
std::cerr << "New identity usage: " << std::endl;
|
std::cerr << "New identity usage: " << std::endl;
|
||||||
|
@ -4700,7 +4766,7 @@ RsIdentityUsage::RsIdentityUsage(
|
||||||
* be ok. */
|
* be ok. */
|
||||||
librs::crypto::HashStream hs(librs::crypto::HashStream::SHA1) ;
|
librs::crypto::HashStream hs(librs::crypto::HashStream::SHA1) ;
|
||||||
|
|
||||||
hs << (uint32_t)service ;
|
hs << (uint32_t)service ; // G10h4ck: Why uint32 if it's 16 bits?
|
||||||
hs << (uint8_t)code ;
|
hs << (uint8_t)code ;
|
||||||
hs << gid ;
|
hs << gid ;
|
||||||
hs << mid ;
|
hs << mid ;
|
||||||
|
@ -4715,4 +4781,5 @@ RsIdentityUsage::RsIdentityUsage(
|
||||||
}
|
}
|
||||||
|
|
||||||
RsIdentityUsage::RsIdentityUsage() :
|
RsIdentityUsage::RsIdentityUsage() :
|
||||||
mServiceId(0), mUsageCode(UNKNOWN_USAGE), mAdditionalId(0) {}
|
mServiceId(RsServiceType::NONE), mUsageCode(UNKNOWN_USAGE), mAdditionalId(0)
|
||||||
|
{}
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* libretroshare/src/services: p3idservice.h *
|
* libretroshare/src/services: p3idservice.h *
|
||||||
* *
|
* *
|
||||||
* libretroshare: retroshare core library *
|
* Copyright (C) 2012-2014 Robert Fernie <retroshare@lunamutt.com> *
|
||||||
* *
|
* Copyright (C) 2017-2019 Gioacchino Mazzurco <gio@altermundi.net> *
|
||||||
* Copyright 2012-2012 Robert Fernie <retroshare@lunamutt.com> *
|
|
||||||
* *
|
* *
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
|
@ -19,51 +18,28 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||||
* *
|
* *
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
#ifndef P3_IDENTITY_SERVICE_HEADER
|
#pragma once
|
||||||
#define P3_IDENTITY_SERVICE_HEADER
|
|
||||||
|
|
||||||
|
/// RetroShare GXS identities service
|
||||||
|
|
||||||
#include "retroshare/rsidentity.h" // External Interfaces.
|
|
||||||
#include "gxs/rsgenexchange.h" // GXS service.
|
|
||||||
#include "gxs/rsgixs.h" // Internal Interfaces.
|
|
||||||
|
|
||||||
#include "gxs/gxstokenqueue.h"
|
|
||||||
#include "rsitems/rsgxsiditems.h"
|
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "retroshare/rsidentity.h" // External Interfaces.
|
||||||
|
#include "gxs/rsgenexchange.h" // GXS service.
|
||||||
|
#include "gxs/rsgixs.h" // Internal Interfaces.
|
||||||
|
#include "util/rsdebug.h"
|
||||||
|
#include "gxs/gxstokenqueue.h"
|
||||||
|
#include "rsitems/rsgxsiditems.h"
|
||||||
#include "util/rsmemcache.h"
|
#include "util/rsmemcache.h"
|
||||||
#include "util/rstickevent.h"
|
#include "util/rstickevent.h"
|
||||||
#include "util/rsrecogn.h"
|
#include "util/rsrecogn.h"
|
||||||
|
|
||||||
#include "pqi/authgpg.h"
|
#include "pqi/authgpg.h"
|
||||||
|
|
||||||
#include "rsitems/rsgxsrecognitems.h"
|
#include "rsitems/rsgxsrecognitems.h"
|
||||||
|
|
||||||
class PgpAuxUtils;
|
class PgpAuxUtils;
|
||||||
|
|
||||||
/*
|
|
||||||
* Identity Service
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
class GxsReputation
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
GxsReputation();
|
|
||||||
|
|
||||||
bool updateIdScore(bool pgpLinked, bool pgpKnown);
|
|
||||||
bool update(); // checks ranges and calculates overall score.
|
|
||||||
int mOverallScore;
|
|
||||||
int mIdScore; // PGP, Known, etc.
|
|
||||||
int mOwnOpinion;
|
|
||||||
int mPeerOpinion;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class OpinionRequest
|
class OpinionRequest
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -312,10 +288,10 @@ public:
|
||||||
/**************** RsGixs Implementation ***************/
|
/**************** RsGixs Implementation ***************/
|
||||||
|
|
||||||
/// @see RsIdentity
|
/// @see RsIdentity
|
||||||
bool getOwnSignedIds(std::vector<RsGxsId> ids) override;
|
bool getOwnSignedIds(std::vector<RsGxsId>& ids) override;
|
||||||
|
|
||||||
/// @see RsIdentity
|
/// @see RsIdentity
|
||||||
bool getOwnPseudonimousIds(std::vector<RsGxsId> ids) override;
|
bool getOwnPseudonimousIds(std::vector<RsGxsId>& ids) override;
|
||||||
|
|
||||||
virtual bool getOwnIds(std::list<RsGxsId> &ownIds, bool signed_only = false);
|
virtual bool getOwnIds(std::list<RsGxsId> &ownIds, bool signed_only = false);
|
||||||
|
|
||||||
|
@ -392,6 +368,9 @@ public:
|
||||||
virtual bool deserialiseIdentityFromMemory(const std::string& radix_string,
|
virtual bool deserialiseIdentityFromMemory(const std::string& radix_string,
|
||||||
RsGxsId* id = nullptr);
|
RsGxsId* id = nullptr);
|
||||||
|
|
||||||
|
/// @see RsIdentity
|
||||||
|
bool requestIdentity(const RsGxsId& id) override;
|
||||||
|
|
||||||
/**************** RsGixsReputation Implementation ****************/
|
/**************** RsGixsReputation Implementation ****************/
|
||||||
|
|
||||||
// get Reputation.
|
// get Reputation.
|
||||||
|
@ -641,9 +620,6 @@ private:
|
||||||
|
|
||||||
bool mAutoAddFriendsIdentitiesAsContacts;
|
bool mAutoAddFriendsIdentitiesAsContacts;
|
||||||
uint32_t mMaxKeepKeysBanned ;
|
uint32_t mMaxKeepKeysBanned ;
|
||||||
|
|
||||||
|
RS_SET_CONTEXT_DEBUG_LEVEL(1)
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // P3_IDENTITY_SERVICE_HEADER
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -25,36 +25,43 @@
|
||||||
#include "services/rseventsservice.h"
|
#include "services/rseventsservice.h"
|
||||||
|
|
||||||
|
|
||||||
/*extern*/ std::shared_ptr<RsEvents> rsEvents(nullptr);
|
/*extern*/ RsEvents* rsEvents = nullptr;
|
||||||
RsEvent::~RsEvent() {};
|
RsEvent::~RsEvent() {};
|
||||||
RsEvents::~RsEvents() {};
|
RsEvents::~RsEvents() {};
|
||||||
|
|
||||||
bool isEventValid(const RsEvent& event, std::string& errorMessage)
|
bool isEventValid(
|
||||||
|
std::shared_ptr<const RsEvent> event, std::string& errorMessage )
|
||||||
{
|
{
|
||||||
if(event.mType <= RsEventType::NONE)
|
if(!event)
|
||||||
|
{
|
||||||
|
errorMessage = "Event is null!";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(event->mType <= RsEventType::NONE)
|
||||||
{
|
{
|
||||||
errorMessage = "Event has type NONE: " +
|
errorMessage = "Event has type NONE: " +
|
||||||
std::to_string(
|
std::to_string(
|
||||||
static_cast<std::underlying_type<RsEventType>::type >(
|
static_cast<std::underlying_type<RsEventType>::type >(
|
||||||
event.mType ) );
|
event->mType ) );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(event.mType >= RsEventType::MAX)
|
if(event->mType >= RsEventType::MAX)
|
||||||
{
|
{
|
||||||
errorMessage = "Event has type >= RsEventType::MAX: " +
|
errorMessage = "Event has type >= RsEventType::MAX: " +
|
||||||
std::to_string(
|
std::to_string(
|
||||||
static_cast<std::underlying_type<RsEventType>::type >(
|
static_cast<std::underlying_type<RsEventType>::type >(
|
||||||
event.mType ) );
|
event->mType ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RsEventsService::postEvent( std::unique_ptr<RsEvent> event,
|
bool RsEventsService::postEvent( std::shared_ptr<const RsEvent> event,
|
||||||
std::string& errorMessage )
|
std::string& errorMessage )
|
||||||
{
|
{
|
||||||
if(!isEventValid(*event, errorMessage))
|
if(!isEventValid(event, errorMessage))
|
||||||
{
|
{
|
||||||
std::cerr << __PRETTY_FUNCTION__ << " Error: "<< errorMessage
|
std::cerr << __PRETTY_FUNCTION__ << " Error: "<< errorMessage
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
@ -62,17 +69,16 @@ bool RsEventsService::postEvent( std::unique_ptr<RsEvent> event,
|
||||||
}
|
}
|
||||||
|
|
||||||
RS_STACK_MUTEX(mEventQueueMtx);
|
RS_STACK_MUTEX(mEventQueueMtx);
|
||||||
mEventQueue.push_back(std::move(event));
|
mEventQueue.push_back(event);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RsEventsService::sendEvent( const RsEvent& event,
|
bool RsEventsService::sendEvent( std::shared_ptr<const RsEvent> event,
|
||||||
std::string& errorMessage )
|
std::string& errorMessage )
|
||||||
{
|
{
|
||||||
if(!isEventValid(event, errorMessage))
|
if(!isEventValid(event, errorMessage))
|
||||||
{
|
{
|
||||||
std::cerr << __PRETTY_FUNCTION__ << " Error: "<< errorMessage
|
RsErr() << __PRETTY_FUNCTION__ << " "<< errorMessage << std::endl;
|
||||||
<< std::endl;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,12 +99,12 @@ RsEventsHandlerId_t RsEventsService::generateUniqueHandlerId_unlocked()
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RsEventsService::registerEventsHandler(
|
bool RsEventsService::registerEventsHandler(
|
||||||
std::function<void(const RsEvent&)> multiCallback,
|
std::function<void(std::shared_ptr<const RsEvent>)> multiCallback,
|
||||||
RsEventsHandlerId_t& hId )
|
RsEventsHandlerId_t& hId )
|
||||||
{
|
{
|
||||||
RS_STACK_MUTEX(mHandlerMapMtx);
|
RS_STACK_MUTEX(mHandlerMapMtx);
|
||||||
if(!hId) hId = generateUniqueHandlerId_unlocked();
|
if(!hId) hId = generateUniqueHandlerId_unlocked();
|
||||||
mHandlerMap[hId] = std::move(multiCallback);
|
mHandlerMap[hId] = multiCallback;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,19 +122,19 @@ void RsEventsService::data_tick()
|
||||||
auto nextRunAt = std::chrono::system_clock::now() +
|
auto nextRunAt = std::chrono::system_clock::now() +
|
||||||
std::chrono::milliseconds(1);
|
std::chrono::milliseconds(1);
|
||||||
|
|
||||||
std::unique_ptr<RsEvent> eventPtr(nullptr);
|
std::shared_ptr<const RsEvent> eventPtr(nullptr);
|
||||||
size_t futureEventsCounter = 0;
|
size_t futureEventsCounter = 0;
|
||||||
|
|
||||||
dispatchEventFromQueueLock:
|
dispatchEventFromQueueLock:
|
||||||
mEventQueueMtx.lock();
|
mEventQueueMtx.lock();
|
||||||
if(mEventQueue.size() > futureEventsCounter)
|
if(mEventQueue.size() > futureEventsCounter)
|
||||||
{
|
{
|
||||||
eventPtr = std::move(mEventQueue.front());
|
eventPtr = mEventQueue.front();
|
||||||
mEventQueue.pop_front();
|
mEventQueue.pop_front();
|
||||||
|
|
||||||
if(eventPtr->mTimePoint >= nextRunAt)
|
if(eventPtr->mTimePoint >= nextRunAt)
|
||||||
{
|
{
|
||||||
mEventQueue.push_back(std::move(eventPtr));
|
mEventQueue.push_back(eventPtr);
|
||||||
++futureEventsCounter;
|
++futureEventsCounter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,17 +143,17 @@ dispatchEventFromQueueLock:
|
||||||
if(eventPtr)
|
if(eventPtr)
|
||||||
{
|
{
|
||||||
/* It is relevant that this stays out of mEventQueueMtx */
|
/* It is relevant that this stays out of mEventQueueMtx */
|
||||||
handleEvent(*eventPtr);
|
handleEvent(eventPtr);
|
||||||
eventPtr.reset(nullptr); // ensure memory is freed before sleep
|
eventPtr = nullptr; // ensure refcounter is decremented before sleep
|
||||||
goto dispatchEventFromQueueLock;
|
goto dispatchEventFromQueueLock;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::this_thread::sleep_until(nextRunAt);
|
std::this_thread::sleep_until(nextRunAt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RsEventsService::handleEvent(const RsEvent& event)
|
void RsEventsService::handleEvent(std::shared_ptr<const RsEvent> event)
|
||||||
{
|
{
|
||||||
std::function<void(const RsEvent&)> mCallback;
|
std::function<void(std::shared_ptr<const RsEvent>)> mCallback;
|
||||||
|
|
||||||
mHandlerMapMtx.lock();
|
mHandlerMapMtx.lock();
|
||||||
auto cbpt = mHandlerMap.begin();
|
auto cbpt = mHandlerMap.begin();
|
||||||
|
@ -165,7 +171,7 @@ getHandlerFromMapLock:
|
||||||
if(mCallback)
|
if(mCallback)
|
||||||
{
|
{
|
||||||
mCallback(event); // It is relevant that this happens outside mutex
|
mCallback(event); // It is relevant that this happens outside mutex
|
||||||
mCallback = std::function<void(const RsEvent&)>(nullptr);
|
mCallback = std::function<void(std::shared_ptr<const RsEvent>)>(nullptr);
|
||||||
goto getHandlerFromMapLock;
|
goto getHandlerFromMapLock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#include "retroshare/rsevents.h"
|
#include "retroshare/rsevents.h"
|
||||||
#include "util/rsthreads.h"
|
#include "util/rsthreads.h"
|
||||||
|
#include "util/rsdebug.h"
|
||||||
|
|
||||||
class RsEventsService :
|
class RsEventsService :
|
||||||
public RsEvents, public RsTickingThread
|
public RsEvents, public RsTickingThread
|
||||||
|
@ -38,13 +39,13 @@ public:
|
||||||
|
|
||||||
/// @see RsEvents
|
/// @see RsEvents
|
||||||
bool postEvent(
|
bool postEvent(
|
||||||
std::unique_ptr<RsEvent> event,
|
std::shared_ptr<const RsEvent> event,
|
||||||
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
|
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
|
||||||
) override;
|
) override;
|
||||||
|
|
||||||
/// @see RsEvents
|
/// @see RsEvents
|
||||||
bool sendEvent(
|
bool sendEvent(
|
||||||
const RsEvent& event,
|
std::shared_ptr<const RsEvent> event,
|
||||||
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
|
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
|
||||||
) override;
|
) override;
|
||||||
|
|
||||||
|
@ -53,7 +54,7 @@ public:
|
||||||
|
|
||||||
/// @see RsEvents
|
/// @see RsEvents
|
||||||
bool registerEventsHandler(
|
bool registerEventsHandler(
|
||||||
std::function<void(const RsEvent&)> multiCallback,
|
std::function<void(std::shared_ptr<const RsEvent>)> multiCallback,
|
||||||
RsEventsHandlerId_t& hId = RS_DEFAULT_STORAGE_PARAM(RsEventsHandlerId_t, 0)
|
RsEventsHandlerId_t& hId = RS_DEFAULT_STORAGE_PARAM(RsEventsHandlerId_t, 0)
|
||||||
) override;
|
) override;
|
||||||
|
|
||||||
|
@ -63,15 +64,18 @@ public:
|
||||||
protected:
|
protected:
|
||||||
RsMutex mHandlerMapMtx;
|
RsMutex mHandlerMapMtx;
|
||||||
RsEventsHandlerId_t mLastHandlerId;
|
RsEventsHandlerId_t mLastHandlerId;
|
||||||
std::map< RsEventsHandlerId_t, std::function<void(const RsEvent&)> >
|
std::map<
|
||||||
mHandlerMap;
|
RsEventsHandlerId_t,
|
||||||
|
std::function<void(std::shared_ptr<const RsEvent>)> > mHandlerMap;
|
||||||
|
|
||||||
RsMutex mEventQueueMtx;
|
RsMutex mEventQueueMtx;
|
||||||
std::deque< std::unique_ptr<RsEvent> > mEventQueue;
|
std::deque< std::shared_ptr<const RsEvent> > mEventQueue;
|
||||||
|
|
||||||
/// @see RsTickingThread
|
/// @see RsTickingThread
|
||||||
void data_tick() override;
|
void data_tick() override;
|
||||||
|
|
||||||
void handleEvent(const RsEvent& event);
|
void handleEvent(std::shared_ptr<const RsEvent> event);
|
||||||
RsEventsHandlerId_t generateUniqueHandlerId_unlocked();
|
RsEventsHandlerId_t generateUniqueHandlerId_unlocked();
|
||||||
|
|
||||||
|
RS_SET_CONTEXT_DEBUG_LEVEL(3)
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
* *
|
* *
|
||||||
* libretroshare: retroshare core library *
|
* libretroshare: retroshare core library *
|
||||||
* *
|
* *
|
||||||
* Copyright 2012 Christopher Evi-Parker <retroshare@lunamutt.com> *
|
* Copyright (C) 2012 Christopher Evi-Parker <retroshare@lunamutt.com> *
|
||||||
|
* Copyright (C) 2019 Gioacchino Mazzurco <gio@altermundi.net> *
|
||||||
* *
|
* *
|
||||||
* This program is free software: you can redistribute it and/or modify *
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
* it under the terms of the GNU Lesser General Public License as *
|
* it under the terms of the GNU Lesser General Public License as *
|
||||||
|
@ -22,106 +23,143 @@
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <memory.h>
|
#include <memory>
|
||||||
#include "util/rstime.h"
|
#include <cstdint>
|
||||||
#include <inttypes.h>
|
#include <cerrno>
|
||||||
|
|
||||||
#include "retrodb.h"
|
#include "util/rstime.h"
|
||||||
#include "rsdbbind.h"
|
#include "util/retrodb.h"
|
||||||
|
#include "util/rsdbbind.h"
|
||||||
|
#include "util/stacktrace.h"
|
||||||
|
#include "util/rsdir.h"
|
||||||
|
|
||||||
//#define RETRODB_DEBUG
|
//#define RETRODB_DEBUG
|
||||||
|
|
||||||
#ifndef NO_SQLCIPHER
|
|
||||||
#define ENABLE_ENCRYPTED_DB
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const int RetroDb::OPEN_READONLY = SQLITE_OPEN_READONLY;
|
const int RetroDb::OPEN_READONLY = SQLITE_OPEN_READONLY;
|
||||||
const int RetroDb::OPEN_READWRITE = SQLITE_OPEN_READWRITE;
|
const int RetroDb::OPEN_READWRITE = SQLITE_OPEN_READWRITE;
|
||||||
const int RetroDb::OPEN_READWRITE_CREATE = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
|
const int RetroDb::OPEN_READWRITE_CREATE = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
|
||||||
|
|
||||||
RetroDb::RetroDb(const std::string &dbPath, int flags, const std::string& key) : mDb(NULL), mKey(key) {
|
RetroDb::RetroDb(const std::string& dbPath, int flags, const std::string& key):
|
||||||
|
mDb(nullptr), mKey(key)
|
||||||
|
{
|
||||||
|
bool alreadyExists = RsDirUtil::fileExists(dbPath);
|
||||||
|
|
||||||
int rc = sqlite3_open_v2(dbPath.c_str(), &mDb, flags, NULL);
|
int rc = sqlite3_open_v2(dbPath.c_str(), &mDb, flags, nullptr);
|
||||||
|
if(rc)
|
||||||
if(rc){
|
{
|
||||||
std::cerr << "Can't open database, Error code: " << sqlite3_errmsg(mDb)
|
RsErr() << __PRETTY_FUNCTION__ << " Can't open database, Error: "
|
||||||
<< std::endl;
|
<< rc << " " << sqlite3_errmsg(mDb) << std::endl;
|
||||||
sqlite3_close(mDb);
|
closeDb();
|
||||||
mDb = NULL;
|
print_stacktrace();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_ENCRYPTED_DB
|
if(alreadyExists)
|
||||||
|
{
|
||||||
|
/* If the database has been created by a RetroShare compiled without
|
||||||
|
* SQLCipher, open it as a plain SQLite database instead of failing
|
||||||
|
* miserably. If RetroShare has been compiled without SQLCipher but the
|
||||||
|
* database seems encrypted print a meaningful error message instead of
|
||||||
|
* crashing miserably.
|
||||||
|
* At some point we could implement a migration SQLite <-> SQLCipher
|
||||||
|
* mecanism and suggest it to the user, or give the option to the user
|
||||||
|
* to choice between plain SQLite or SQLCipher database, is some cases
|
||||||
|
* such as encrypted FS it might make sense to keep SQLite even if
|
||||||
|
* SQLCipher is availble for performance, as encryption is already
|
||||||
|
* provided at FS level. */
|
||||||
|
|
||||||
|
rc = sqlite3_exec( mDb, "PRAGMA schema_version;",
|
||||||
|
nullptr, nullptr, nullptr );
|
||||||
|
if( rc == SQLITE_OK )
|
||||||
|
{
|
||||||
|
#ifndef NO_SQLCIPHER
|
||||||
|
RsWarn() << __PRETTY_FUNCTION__ << " The database is not encrypted: "
|
||||||
|
<< dbPath << std::endl;
|
||||||
|
#endif // ndef NO_SQLCIPHER
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef NO_SQLCIPHER
|
||||||
|
RsErr() << __PRETTY_FUNCTION__ << " Error quering schema version."
|
||||||
|
<< " Are you trying to open an encrypted database without "
|
||||||
|
<< "compiling SQLCipher support?" << std::endl << std::endl;
|
||||||
|
print_stacktrace();
|
||||||
|
closeDb();
|
||||||
|
#else // def NO_SQLCIPHER
|
||||||
|
RsInfo() << __PRETTY_FUNCTION__ << " The database seems encrypted: "
|
||||||
|
<< dbPath << std::endl;
|
||||||
|
#endif // def NO_SQLCIPHER
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef NO_SQLCIPHER
|
||||||
if(!mKey.empty())
|
if(!mKey.empty())
|
||||||
{
|
{
|
||||||
rc = sqlite3_key(mDb, mKey.c_str(), mKey.size());
|
rc = sqlite3_key(mDb, mKey.c_str(), static_cast<int>(mKey.size()));
|
||||||
|
|
||||||
if(rc){
|
if(rc)
|
||||||
std::cerr << "Can't key database: " << sqlite3_errmsg(mDb)
|
{
|
||||||
<< std::endl;
|
RsErr() << __PRETTY_FUNCTION__ << " Can't key database: " << rc
|
||||||
|
<< " " << sqlite3_errmsg(mDb) << std::endl;
|
||||||
sqlite3_close(mDb);
|
closeDb();
|
||||||
mDb = NULL;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char *err = NULL;
|
char* err = nullptr;
|
||||||
rc = sqlite3_exec(mDb, "PRAGMA cipher_migrate;", NULL, NULL, &err);
|
rc = sqlite3_exec(mDb, "PRAGMA cipher_migrate;", nullptr, nullptr, &err);
|
||||||
if (rc != SQLITE_OK)
|
if (rc != SQLITE_OK)
|
||||||
{
|
{
|
||||||
std::cerr << "RetroDb::RetroDb(): Error upgrading database, error code: " << rc;
|
RsErr() << __PRETTY_FUNCTION__ << " Error upgrading database, error "
|
||||||
if (err)
|
<< "code: " << rc << " " << err << std::endl;
|
||||||
{
|
|
||||||
std::cerr << ", " << err;
|
|
||||||
}
|
|
||||||
std::cerr << std::endl;
|
|
||||||
sqlite3_free(err);
|
sqlite3_free(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Test DB for correct sqlcipher version
|
// Test DB for correct sqlcipher version
|
||||||
if (sqlite3_exec(mDb, "PRAGMA user_version;", NULL, NULL, NULL) != SQLITE_OK)
|
if(sqlite3_exec(
|
||||||
|
mDb, "PRAGMA user_version;",
|
||||||
|
nullptr, nullptr, nullptr ) != SQLITE_OK)
|
||||||
{
|
{
|
||||||
std::cerr << "RetroDb::RetroDb(): Failed to open database: " << dbPath << std::endl << "Trying with settings for sqlcipher version 3...";
|
RsWarn() << __PRETTY_FUNCTION__ << " Failed to open database: "
|
||||||
|
<< dbPath << std::endl;
|
||||||
|
|
||||||
//Reopening the database with correct settings
|
//Reopening the database with correct settings
|
||||||
rc = sqlite3_close(mDb);
|
closeDb();
|
||||||
mDb = NULL;
|
if(!rc) rc = sqlite3_open_v2(dbPath.c_str(), &mDb, flags, nullptr);
|
||||||
if(!rc)
|
|
||||||
rc = sqlite3_open_v2(dbPath.c_str(), &mDb, flags, NULL);
|
|
||||||
if(!rc && !mKey.empty())
|
if(!rc && !mKey.empty())
|
||||||
rc = sqlite3_key(mDb, mKey.c_str(), mKey.size());
|
rc = sqlite3_key(mDb, mKey.c_str(), static_cast<int>(mKey.size()));
|
||||||
if(!rc)
|
if(!rc)
|
||||||
rc = sqlite3_exec(mDb, "PRAGMA kdf_iter = 64000;", NULL, NULL, NULL);
|
rc = sqlite3_exec( mDb, "PRAGMA kdf_iter = 64000;",
|
||||||
if (!rc && (sqlite3_exec(mDb, "PRAGMA user_version;", NULL, NULL, NULL) == SQLITE_OK))
|
nullptr, nullptr, nullptr );
|
||||||
|
if (!rc && (sqlite3_exec( mDb, "PRAGMA user_version;",
|
||||||
|
nullptr, nullptr, nullptr ) == SQLITE_OK))
|
||||||
{
|
{
|
||||||
std::cerr << "\tSuccess" << std::endl;
|
RsInfo() << __PRETTY_FUNCTION__ << " Re-trying with settings for "
|
||||||
} else {
|
<< "sqlcipher version 3 successed" << std::endl;
|
||||||
std::cerr << "\tFailed, giving up" << std::endl;
|
}
|
||||||
sqlite3_close(mDb);
|
else
|
||||||
mDb = NULL;
|
{
|
||||||
|
RsErr() << __PRETTY_FUNCTION__ << " Re-trying with settings for "
|
||||||
|
<< "sqlcipher version 3 failed, giving up" << std::endl;
|
||||||
|
closeDb();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif // ndef NO_SQLCIPHER
|
||||||
}
|
}
|
||||||
|
|
||||||
RetroDb::~RetroDb(){
|
RetroDb::~RetroDb() { closeDb(); }
|
||||||
|
|
||||||
sqlite3_close(mDb); // no-op if mDb is NULL (https://www.sqlite.org/c3ref/close.html)
|
void RetroDb::closeDb()
|
||||||
mDb = NULL ;
|
{
|
||||||
}
|
// no-op if mDb is nullptr (https://www.sqlite.org/c3ref/close.html)
|
||||||
|
int rc = sqlite3_close(mDb);
|
||||||
void RetroDb::closeDb(){
|
mDb = nullptr;
|
||||||
|
|
||||||
int rc= sqlite3_close(mDb);
|
|
||||||
mDb = NULL ;
|
|
||||||
|
|
||||||
#ifdef RETRODB_DEBUG
|
|
||||||
std::cerr << "RetroDb::closeDb(): Error code on close: " << rc << std::endl;
|
|
||||||
#else
|
|
||||||
(void)rc;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
Dbg2() << __PRETTY_FUNCTION__ << " sqlite3_close return: " << rc
|
||||||
|
<< std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TIME_LIMIT 3
|
#define TIME_LIMIT 3
|
||||||
|
|
|
@ -19,8 +19,7 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||||
* *
|
* *
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
#ifndef RSSQLITE_H
|
#pragma once
|
||||||
#define RSSQLITE_H
|
|
||||||
|
|
||||||
#ifdef NO_SQLCIPHER
|
#ifdef NO_SQLCIPHER
|
||||||
#include <sqlite3.h>
|
#include <sqlite3.h>
|
||||||
|
@ -32,9 +31,10 @@
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include "rsdbbind.h"
|
|
||||||
|
|
||||||
#include "contentvalue.h"
|
#include "util/rsdebug.h"
|
||||||
|
#include "util/rsdbbind.h"
|
||||||
|
#include "util/contentvalue.h"
|
||||||
|
|
||||||
class RetroCursor;
|
class RetroCursor;
|
||||||
|
|
||||||
|
@ -202,6 +202,8 @@ private:
|
||||||
|
|
||||||
sqlite3* mDb;
|
sqlite3* mDb;
|
||||||
const std::string mKey;
|
const std::string mKey;
|
||||||
|
|
||||||
|
RS_SET_CONTEXT_DEBUG_LEVEL(3)
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -318,5 +320,3 @@ public:
|
||||||
private:
|
private:
|
||||||
sqlite3_stmt* mStmt;
|
sqlite3_stmt* mStmt;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // RSSQLITE_H
|
|
||||||
|
|
|
@ -242,6 +242,10 @@ RsTickingThread::RsTickingThread()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RsTickingThread::~RsTickingThread()
|
||||||
|
{
|
||||||
|
fullstop();
|
||||||
|
}
|
||||||
void RsSingleJobThread::runloop()
|
void RsSingleJobThread::runloop()
|
||||||
{
|
{
|
||||||
run() ;
|
run() ;
|
||||||
|
|
|
@ -287,6 +287,7 @@ class RsTickingThread: public RsThread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RsTickingThread();
|
RsTickingThread();
|
||||||
|
virtual ~RsTickingThread();
|
||||||
|
|
||||||
void shutdown();
|
void shutdown();
|
||||||
void fullstop();
|
void fullstop();
|
||||||
|
|
|
@ -23,12 +23,10 @@
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#if defined(__linux__) && defined(__GLIBC__)
|
#ifdef __ANDROID__
|
||||||
|
# include "util/rsdebug.h"
|
||||||
#include <execinfo.h>
|
#endif
|
||||||
#include <cxxabi.h>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Print a backtrace to FILE* out.
|
* @brief Print a backtrace to FILE* out.
|
||||||
|
@ -40,7 +38,16 @@
|
||||||
* @param[in] maxFrames maximum number of stack frames you want to bu printed
|
* @param[in] maxFrames maximum number of stack frames you want to bu printed
|
||||||
*/
|
*/
|
||||||
static inline void print_stacktrace(
|
static inline void print_stacktrace(
|
||||||
bool demangle = true, FILE *out = stderr, unsigned int maxFrames = 63 )
|
bool demangle = true, FILE *out = stderr, unsigned int maxFrames = 63 );
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__linux__) && defined(__GLIBC__)
|
||||||
|
|
||||||
|
#include <execinfo.h>
|
||||||
|
#include <cxxabi.h>
|
||||||
|
|
||||||
|
static inline void print_stacktrace(
|
||||||
|
bool demangle, FILE* out, unsigned int maxFrames )
|
||||||
{
|
{
|
||||||
if(!out)
|
if(!out)
|
||||||
{
|
{
|
||||||
|
@ -140,15 +147,111 @@ static inline void print_stacktrace(
|
||||||
free(funcname);
|
free(funcname);
|
||||||
free(symbollist);
|
free(symbollist);
|
||||||
}
|
}
|
||||||
|
#elif defined(__ANDROID__) // defined(__linux__) && defined(__GLIBC__)
|
||||||
|
|
||||||
|
/* Inspired by the solution proposed by Louis Semprini on this thread
|
||||||
|
* https://stackoverflow.com/questions/8115192/android-ndk-getting-the-backtrace/35586148
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <unwind.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <cxxabi.h>
|
||||||
|
|
||||||
|
struct RsAndroidBacktraceState
|
||||||
|
{
|
||||||
|
void** current;
|
||||||
|
void** end;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline _Unwind_Reason_Code android_unwind_callback(
|
||||||
|
struct _Unwind_Context* context, void* arg )
|
||||||
|
{
|
||||||
|
RsAndroidBacktraceState* state = static_cast<RsAndroidBacktraceState*>(arg);
|
||||||
|
uintptr_t pc = _Unwind_GetIP(context);
|
||||||
|
if(pc)
|
||||||
|
{
|
||||||
|
if (state->current == state->end) return _URC_END_OF_STACK;
|
||||||
|
|
||||||
|
*state->current++ = reinterpret_cast<void*>(pc);
|
||||||
|
}
|
||||||
|
return _URC_NO_REASON;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void print_stacktrace(
|
||||||
|
bool demangle, FILE* /*out*/, unsigned int /*maxFrames*/)
|
||||||
|
{
|
||||||
|
constexpr int max = 5000;
|
||||||
|
void* buffer[max];
|
||||||
|
|
||||||
|
RsAndroidBacktraceState state;
|
||||||
|
state.current = buffer;
|
||||||
|
state.end = buffer + max;
|
||||||
|
|
||||||
|
_Unwind_Backtrace(android_unwind_callback, &state);
|
||||||
|
|
||||||
|
RsDbg() << std::endl << std::endl
|
||||||
|
<< 0 << " " << buffer[0] << " " << __PRETTY_FUNCTION__ << std::endl;
|
||||||
|
|
||||||
|
// Skip first frame which is print_stacktrace
|
||||||
|
int count = static_cast<int>(state.current - buffer);
|
||||||
|
for(int idx = 1; idx < count; ++idx)
|
||||||
|
{
|
||||||
|
const void* addr = buffer[idx];
|
||||||
|
|
||||||
|
/* Ignore null addresses.
|
||||||
|
* They sometimes happen when using _Unwind_Backtrace()
|
||||||
|
* with compiler optimizations, when the Link Register is overwritten by
|
||||||
|
* the inner stack frames. */
|
||||||
|
if(!addr) continue;
|
||||||
|
|
||||||
|
/* Ignore duplicate addresses.
|
||||||
|
* They sometimes happen when using _Unwind_Backtrace() with compiler
|
||||||
|
* optimizations. */
|
||||||
|
if(addr == buffer[idx-1]) continue;
|
||||||
|
|
||||||
|
Dl_info info;
|
||||||
|
if( !(dladdr(addr, &info) && info.dli_sname) )
|
||||||
|
{
|
||||||
|
RsDbg() << idx << " " << addr << " " << info.dli_fname
|
||||||
|
<< " symbol not found" << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(demangle)
|
||||||
|
{
|
||||||
|
int status = 0;
|
||||||
|
char* demangled = __cxxabiv1::__cxa_demangle(
|
||||||
|
info.dli_sname, nullptr, nullptr, &status );
|
||||||
|
|
||||||
|
if(demangled && (status == 0))
|
||||||
|
RsDbg() << idx << " " << addr << " " << demangled << std::endl;
|
||||||
|
else
|
||||||
|
RsDbg() << idx << " " << addr << " "
|
||||||
|
<< (info.dli_sname ? info.dli_sname : info.dli_fname)
|
||||||
|
<< " __cxa_demangle failed with: " << status
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
free(demangled);
|
||||||
|
}
|
||||||
|
else RsDbg() << idx << " " << addr << " "
|
||||||
|
<< (info.dli_sname ? info.dli_sname : info.dli_fname)
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
RsDbg() << std::endl << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
#else // defined(__linux__) && defined(__GLIBC__)
|
#else // defined(__linux__) && defined(__GLIBC__)
|
||||||
static inline void print_stacktrace(
|
|
||||||
bool demangle = true, FILE *out = stderr, unsigned int max_frames = 63 )
|
|
||||||
{
|
|
||||||
(void) demangle;
|
|
||||||
(void) max_frames;
|
|
||||||
|
|
||||||
fprintf(out, "TODO: 2016/01/01 print_stacktrace not implemented yet for WINDOWS_SYS and ANDROID\n");
|
static inline void print_stacktrace(
|
||||||
|
bool /*demangle*/, FILE* out, unsigned int /*max_frames*/ )
|
||||||
|
{
|
||||||
|
/** Notify the user which signal was caught. We use printf, because this
|
||||||
|
* is the most basic output function. Once you get a crash, it is
|
||||||
|
* possible that more complex output systems like streams and the like
|
||||||
|
* may be corrupted. So we make the most basic call possible to the
|
||||||
|
* lowest level, most standard print function. */
|
||||||
|
fprintf(out, "print_stacktrace Not implemented yet for this platform\n");
|
||||||
}
|
}
|
||||||
#endif // defined(__linux__) && defined(__GLIBC__)
|
#endif // defined(__linux__) && defined(__GLIBC__)
|
||||||
|
|
||||||
|
@ -169,6 +272,7 @@ struct CrashStackTrace
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[ noreturn ]]
|
||||||
static void abortHandler(int signum)
|
static void abortHandler(int signum)
|
||||||
{
|
{
|
||||||
// associate each signal with a signal name string.
|
// associate each signal with a signal name string.
|
||||||
|
@ -184,6 +288,7 @@ struct CrashStackTrace
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef __ANDROID__
|
||||||
/** Notify the user which signal was caught. We use printf, because this
|
/** Notify the user which signal was caught. We use printf, because this
|
||||||
* is the most basic output function. Once you get a crash, it is
|
* is the most basic output function. Once you get a crash, it is
|
||||||
* possible that more complex output systems like streams and the like
|
* possible that more complex output systems like streams and the like
|
||||||
|
@ -193,6 +298,11 @@ struct CrashStackTrace
|
||||||
fprintf(stderr, "Caught signal %d (%s)\n", signum, name);
|
fprintf(stderr, "Caught signal %d (%s)\n", signum, name);
|
||||||
else
|
else
|
||||||
fprintf(stderr, "Caught signal %d\n", signum);
|
fprintf(stderr, "Caught signal %d\n", signum);
|
||||||
|
#else // ndef __ANDROID__
|
||||||
|
/** On Android the best we can to is to rely on RS debug utils */
|
||||||
|
RsFatal() << __PRETTY_FUNCTION__ << " Caught signal " << signum << " "
|
||||||
|
<< (name ? name : "") << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
print_stacktrace(false);
|
print_stacktrace(false);
|
||||||
|
|
||||||
|
|
|
@ -322,8 +322,8 @@ void ChatLobbyWidget::lobbyTreeWidgetCustomPopupMenu(QPoint)
|
||||||
|
|
||||||
QPixmap pixmap ;
|
QPixmap pixmap ;
|
||||||
|
|
||||||
if(idd.mAvatar.mSize == 0 || !pixmap.loadFromData(idd.mAvatar.mData, idd.mAvatar.mSize, "PNG"))
|
if(idd.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(idd.mAvatar.mData, idd.mAvatar.mSize, pixmap, GxsIdDetails::SMALL))
|
||||||
pixmap = QPixmap::fromImage(GxsIdDetails::makeDefaultIcon(*it)) ;
|
pixmap = GxsIdDetails::makeDefaultIcon(*it,GxsIdDetails::SMALL) ;
|
||||||
|
|
||||||
QAction *action = mnu->addAction(QIcon(pixmap), QString("%1 (%2)").arg(QString::fromUtf8(idd.mNickname.c_str()), QString::fromStdString((*it).toStdString())), this, SLOT(subscribeChatLobbyAs()));
|
QAction *action = mnu->addAction(QIcon(pixmap), QString("%1 (%2)").arg(QString::fromUtf8(idd.mNickname.c_str()), QString::fromStdString((*it).toStdString())), this, SLOT(subscribeChatLobbyAs()));
|
||||||
action->setData(QString::fromStdString((*it).toStdString())) ;
|
action->setData(QString::fromStdString((*it).toStdString())) ;
|
||||||
|
@ -331,10 +331,14 @@ void ChatLobbyWidget::lobbyTreeWidgetCustomPopupMenu(QPoint)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef TO_BE_REMOVED
|
||||||
|
// This code is not needed anymore because AutoSubscribe is now automatically handled with chat room subscription.
|
||||||
|
|
||||||
if (item->data(COLUMN_DATA, ROLE_AUTOSUBSCRIBE).toBool())
|
if (item->data(COLUMN_DATA, ROLE_AUTOSUBSCRIBE).toBool())
|
||||||
contextMnu.addAction(QIcon(IMAGE_AUTOSUBSCRIBE), tr("Remove Auto Subscribe"), this, SLOT(autoSubscribeItem()));
|
contextMnu.addAction(QIcon(IMAGE_AUTOSUBSCRIBE), tr("Remove Auto Subscribe"), this, SLOT(autoSubscribeItem()));
|
||||||
else if(!own_identities.empty())
|
else if(!own_identities.empty())
|
||||||
contextMnu.addAction(QIcon(IMAGE_SUBSCRIBE), tr("Add Auto Subscribe"), this, SLOT(autoSubscribeItem()));
|
contextMnu.addAction(QIcon(IMAGE_SUBSCRIBE), tr("Add Auto Subscribe"), this, SLOT(autoSubscribeItem()));
|
||||||
|
#endif
|
||||||
|
|
||||||
contextMnu.addAction(QIcon(IMAGE_COPYRSLINK), tr("Copy RetroShare Link"), this, SLOT(copyItemLink()));
|
contextMnu.addAction(QIcon(IMAGE_COPYRSLINK), tr("Copy RetroShare Link"), this, SLOT(copyItemLink()));
|
||||||
}
|
}
|
||||||
|
@ -603,19 +607,16 @@ void ChatLobbyWidget::updateDisplay()
|
||||||
item->setIcon(COLUMN_NAME, subscribed ? icon : icon.pixmap(ui.lobbyTreeWidget->iconSize(), QIcon::Disabled));
|
item->setIcon(COLUMN_NAME, subscribed ? icon : icon.pixmap(ui.lobbyTreeWidget->iconSize(), QIcon::Disabled));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In the new model (after lobby save to disk) the auto-subscribe flag is used to automatically join lobbies that where
|
||||||
|
// previously being used when the t software quits.
|
||||||
|
|
||||||
bool autoSubscribe = rsMsgs->getLobbyAutoSubscribe(lobby.lobby_id);
|
bool autoSubscribe = rsMsgs->getLobbyAutoSubscribe(lobby.lobby_id);
|
||||||
|
|
||||||
if (autoSubscribe && subscribed)
|
if (autoSubscribe && subscribed && _lobby_infos.find(lobby.lobby_id) == _lobby_infos.end())
|
||||||
{
|
{
|
||||||
if(_lobby_infos.find(lobby.lobby_id) == _lobby_infos.end())
|
ChatDialog *cd = ChatDialog::getChat(ChatId(lobby.lobby_id), RS_CHAT_OPEN);
|
||||||
{
|
|
||||||
if (item == ui.lobbyTreeWidget->currentItem())
|
addChatPage(dynamic_cast<ChatLobbyDialog*>(cd));
|
||||||
{
|
|
||||||
ChatDialog::chatFriend(ChatId(lobby.lobby_id)) ;
|
|
||||||
}else{
|
|
||||||
ChatDialog::chatFriend(ChatId(lobby.lobby_id),false) ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateItem(ui.lobbyTreeWidget, item, lobby.lobby_id, lobby.lobby_name,lobby.lobby_topic, lobby.total_number_of_peers, subscribed, autoSubscribe,lobby_flags);
|
updateItem(ui.lobbyTreeWidget, item, lobby.lobby_id, lobby.lobby_name,lobby.lobby_topic, lobby.total_number_of_peers, subscribed, autoSubscribe,lobby_flags);
|
||||||
|
@ -674,6 +675,16 @@ void ChatLobbyWidget::updateDisplay()
|
||||||
bool autoSubscribe = rsMsgs->getLobbyAutoSubscribe(lobby.lobby_id);
|
bool autoSubscribe = rsMsgs->getLobbyAutoSubscribe(lobby.lobby_id);
|
||||||
|
|
||||||
updateItem(ui.lobbyTreeWidget, item, lobby.lobby_id, lobby.lobby_name,lobby.lobby_topic, lobby.gxs_ids.size(), true, autoSubscribe,lobby_flags);
|
updateItem(ui.lobbyTreeWidget, item, lobby.lobby_id, lobby.lobby_name,lobby.lobby_topic, lobby.gxs_ids.size(), true, autoSubscribe,lobby_flags);
|
||||||
|
|
||||||
|
std::map<ChatLobbyId,ChatLobbyInfoStruct>::iterator it = _lobby_infos.find(lobby.lobby_id) ;
|
||||||
|
|
||||||
|
// look for chat rooms that are subscribed but not displayed as such
|
||||||
|
|
||||||
|
if(it == _lobby_infos.end() && rsMsgs->joinVisibleChatLobby(lobby.lobby_id,lobby.gxs_id))
|
||||||
|
{
|
||||||
|
std::cerr << "Adding back ChatLobbyDialog for subscribed lobby " << std::hex << lobby.lobby_id << std::dec << std::endl;
|
||||||
|
ChatDialog::chatFriend(ChatId(lobby.lobby_id),true) ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
publicSubLobbyItem->setHidden(publicSubLobbyItem->childCount()==0);
|
publicSubLobbyItem->setHidden(publicSubLobbyItem->childCount()==0);
|
||||||
publicSubLobbyItem->setText(COLUMN_NAME, tr("Public Subscribed chat rooms")+ QString(" (") + QString::number(publicSubLobbyItem->childCount())+QString(")"));
|
publicSubLobbyItem->setText(COLUMN_NAME, tr("Public Subscribed chat rooms")+ QString(" (") + QString::number(publicSubLobbyItem->childCount())+QString(")"));
|
||||||
|
|
|
@ -270,8 +270,8 @@ void CreateCircleDialog::addMember(const RsGxsIdGroup &idGroup)
|
||||||
|
|
||||||
QPixmap pixmap ;
|
QPixmap pixmap ;
|
||||||
|
|
||||||
if(idGroup.mImage.mSize == 0 || !pixmap.loadFromData(idGroup.mImage.mData, idGroup.mImage.mSize, "PNG"))
|
if(idGroup.mImage.mSize == 0 || !GxsIdDetails::loadPixmapFromData(idGroup.mImage.mData, idGroup.mImage.mSize, pixmap, GxsIdDetails::SMALL))
|
||||||
pixmap = QPixmap::fromImage(GxsIdDetails::makeDefaultIcon(RsGxsId(idGroup.mMeta.mGroupId)));
|
pixmap = GxsIdDetails::makeDefaultIcon(RsGxsId(idGroup.mMeta.mGroupId),GxsIdDetails::SMALL);
|
||||||
|
|
||||||
if (idGroup.mPgpKnown){
|
if (idGroup.mPgpKnown){
|
||||||
RsPeerDetails details;
|
RsPeerDetails details;
|
||||||
|
@ -331,8 +331,8 @@ void CreateCircleDialog::addCircle(const RsGxsCircleDetails &cirDetails)
|
||||||
|
|
||||||
QPixmap pixmap ;
|
QPixmap pixmap ;
|
||||||
|
|
||||||
if(gxs_details.mAvatar.mSize == 0 || !pixmap.loadFromData(gxs_details.mAvatar.mData, gxs_details.mAvatar.mSize, "PNG"))
|
if(gxs_details.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(gxs_details.mAvatar.mData, gxs_details.mAvatar.mSize, pixmap, GxsIdDetails::SMALL))
|
||||||
pixmap = QPixmap::fromImage(GxsIdDetails::makeDefaultIcon(gxs_details.mId));
|
pixmap = GxsIdDetails::makeDefaultIcon(gxs_details.mId,GxsIdDetails::SMALL);
|
||||||
|
|
||||||
addMember(keyId, idtype, nickname, QIcon(pixmap));
|
addMember(keyId, idtype, nickname, QIcon(pixmap));
|
||||||
|
|
||||||
|
@ -814,8 +814,8 @@ void CreateCircleDialog::loadIdentities(uint32_t token)
|
||||||
|
|
||||||
QPixmap pixmap ;
|
QPixmap pixmap ;
|
||||||
|
|
||||||
if(idGroup.mImage.mSize == 0 || !pixmap.loadFromData(idGroup.mImage.mData, idGroup.mImage.mSize, "PNG"))
|
if(idGroup.mImage.mSize == 0 || !GxsIdDetails::loadPixmapFromData(idGroup.mImage.mData, idGroup.mImage.mSize, pixmap, GxsIdDetails::SMALL))
|
||||||
pixmap = QPixmap::fromImage(GxsIdDetails::makeDefaultIcon(RsGxsId(idGroup.mMeta.mGroupId))) ;
|
pixmap = GxsIdDetails::makeDefaultIcon(RsGxsId(idGroup.mMeta.mGroupId),GxsIdDetails::SMALL) ;
|
||||||
|
|
||||||
if (idGroup.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID_kept_for_compatibility)
|
if (idGroup.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID_kept_for_compatibility)
|
||||||
{
|
{
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
#include "FriendsDialog.h"
|
#include "FriendsDialog.h"
|
||||||
#include "NetworkView.h"
|
#include "NetworkView.h"
|
||||||
#include "NetworkDialog.h"
|
#include "NetworkDialog.h"
|
||||||
|
#include "gui/common/NewFriendList.h"
|
||||||
#include "gui/Identity/IdDialog.h"
|
#include "gui/Identity/IdDialog.h"
|
||||||
/* Images for Newsfeed icons */
|
/* Images for Newsfeed icons */
|
||||||
//#define IMAGE_NEWSFEED ""
|
//#define IMAGE_NEWSFEED ""
|
||||||
|
@ -73,10 +74,8 @@ FriendsDialog::FriendsDialog(QWidget *parent)
|
||||||
ui.chatWidget->setWelcomeMessage(msg);
|
ui.chatWidget->setWelcomeMessage(msg);
|
||||||
ui.chatWidget->init(ChatId::makeBroadcastId(), tr("Broadcast"));
|
ui.chatWidget->init(ChatId::makeBroadcastId(), tr("Broadcast"));
|
||||||
|
|
||||||
connect(NotifyQt::getInstance(), SIGNAL(chatMessageReceived(ChatMessage)),
|
connect(NotifyQt::getInstance(), SIGNAL(chatMessageReceived(ChatMessage)), this, SLOT(chatMessageReceived(ChatMessage)));
|
||||||
this, SLOT(chatMessageReceived(ChatMessage)));
|
connect(NotifyQt::getInstance(), SIGNAL(chatStatusChanged(ChatId,QString)), this, SLOT(chatStatusReceived(ChatId,QString)));
|
||||||
connect(NotifyQt::getInstance(), SIGNAL(chatStatusChanged(ChatId,QString)),
|
|
||||||
this, SLOT(chatStatusReceived(ChatId,QString)));
|
|
||||||
#else // def RS_DIRECT_CHAT
|
#else // def RS_DIRECT_CHAT
|
||||||
ui.tabWidget->removeTab(ui.tabWidget->indexOf(ui.groupChatTab));
|
ui.tabWidget->removeTab(ui.tabWidget->indexOf(ui.groupChatTab));
|
||||||
#endif // def RS_DIRECT_CHAT
|
#endif // def RS_DIRECT_CHAT
|
||||||
|
@ -93,47 +92,15 @@ FriendsDialog::FriendsDialog(QWidget *parent)
|
||||||
ui.tabWidget->addTab(networkView = new NetworkView(),QIcon(IMAGE_NETWORK2), tr("Network graph"));
|
ui.tabWidget->addTab(networkView = new NetworkView(),QIcon(IMAGE_NETWORK2), tr("Network graph"));
|
||||||
ui.tabWidget->addTab(networkDialog = new NetworkDialog(),QIcon(IMAGE_PEERS), tr("Keyring"));
|
ui.tabWidget->addTab(networkDialog = new NetworkDialog(),QIcon(IMAGE_PEERS), tr("Keyring"));
|
||||||
|
|
||||||
//ui.tabWidget->addTab(new ProfileWidget(), tr("Profile"));
|
|
||||||
//newsFeed = new NewsFeed();
|
|
||||||
//int newsFeedTabIndex = ui.tabWidget->insertTab(0, newsFeed, tr("News Feed"));
|
|
||||||
//ui.tabWidget->setCurrentIndex(newsFeedTabIndex);
|
|
||||||
|
|
||||||
ui.tabWidget->hideCloseButton(0);
|
ui.tabWidget->hideCloseButton(0);
|
||||||
ui.tabWidget->hideCloseButton(1);
|
ui.tabWidget->hideCloseButton(1);
|
||||||
ui.tabWidget->hideCloseButton(2);
|
ui.tabWidget->hideCloseButton(2);
|
||||||
ui.tabWidget->hideCloseButton(3);
|
ui.tabWidget->hideCloseButton(3);
|
||||||
ui.tabWidget->hideCloseButton(4);
|
ui.tabWidget->hideCloseButton(4);
|
||||||
|
|
||||||
/* get the current text and text color of the tab bar */
|
|
||||||
//newsFeedTabColor = ui.tabWidget->tabBar()->tabTextColor(newsFeedTabIndex);
|
|
||||||
//newsFeedText = ui.tabWidget->tabBar()->tabText(newsFeedTabIndex);
|
|
||||||
|
|
||||||
//connect(newsFeed, SIGNAL(newsFeedChanged(int)), this, SLOT(newsFeedChanged(int)));
|
|
||||||
|
|
||||||
// menu = new QMenu();
|
|
||||||
// menu->addAction(ui.actionAdd_Friend);
|
|
||||||
// menu->addAction(ui.actionAdd_Group);
|
|
||||||
// menu->addAction(ui.actionCreate_new_Chat_lobby);
|
|
||||||
//
|
|
||||||
// menu->addSeparator();
|
|
||||||
// menu->addAction(ui.actionSet_your_Avatar);
|
|
||||||
// menu->addAction(ui.actionSet_your_Personal_Message);
|
|
||||||
//
|
|
||||||
// ui.menutoolButton->setMenu(menu);
|
|
||||||
|
|
||||||
/*QToolButton *addFriendButton = new QToolButton(this);
|
|
||||||
addFriendButton->setIcon(QIcon(":/images/user/add_user24.png"));
|
|
||||||
addFriendButton->setToolTip(tr("Add friend node"));
|
|
||||||
connect(addFriendButton, SIGNAL(clicked()), this, SLOT(addFriend()));
|
|
||||||
ui.friendList->addToolButton(addFriendButton);*/
|
|
||||||
|
|
||||||
/* Set initial size the splitter */
|
/* Set initial size the splitter */
|
||||||
ui.splitter->setStretchFactor(0, 0);
|
ui.splitter->setStretchFactor(0, 0);
|
||||||
ui.splitter->setStretchFactor(1, 1);
|
ui.splitter->setStretchFactor(1, 1);
|
||||||
/*remove
|
|
||||||
QList<int> sizes;
|
|
||||||
sizes << height() << 100; // Qt calculates the right sizes
|
|
||||||
ui.splitter_2->setSizes(sizes);*/
|
|
||||||
|
|
||||||
loadmypersonalstatus();
|
loadmypersonalstatus();
|
||||||
|
|
||||||
|
@ -141,9 +108,9 @@ QList<int> sizes;
|
||||||
|
|
||||||
// load settings
|
// load settings
|
||||||
RsAutoUpdatePage::lockAllEvents();
|
RsAutoUpdatePage::lockAllEvents();
|
||||||
ui.friendList->setColumnVisible(FriendList::COLUMN_LAST_CONTACT, false);
|
ui.friendList->setColumnVisible(RsFriendListModel::COLUMN_THREAD_LAST_CONTACT, false);
|
||||||
ui.friendList->setColumnVisible(FriendList::COLUMN_IP, false);
|
ui.friendList->setColumnVisible(RsFriendListModel::COLUMN_THREAD_IP, false);
|
||||||
ui.friendList->setColumnVisible(FriendList::COLUMN_ID, false);
|
ui.friendList->setColumnVisible(RsFriendListModel::COLUMN_THREAD_ID, false);
|
||||||
ui.friendList->setShowGroups(true);
|
ui.friendList->setShowGroups(true);
|
||||||
processSettings(true);
|
processSettings(true);
|
||||||
RsAutoUpdatePage::unlockAllEvents();
|
RsAutoUpdatePage::unlockAllEvents();
|
||||||
|
|
|
@ -145,17 +145,14 @@
|
||||||
</property>
|
</property>
|
||||||
<item row="0" column="0" rowspan="2">
|
<item row="0" column="0" rowspan="2">
|
||||||
<widget class="AvatarWidget" name="avatar">
|
<widget class="AvatarWidget" name="avatar">
|
||||||
<property name="minimumSize">
|
<property name="sizePolicy">
|
||||||
<size>
|
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
||||||
<width>61</width>
|
<horstretch>0</horstretch>
|
||||||
<height>61</height>
|
<verstretch>0</verstretch>
|
||||||
</size>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximumSize">
|
<property name="scaledContents">
|
||||||
<size>
|
<bool>false</bool>
|
||||||
<width>61</width>
|
|
||||||
<height>61</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -199,7 +196,7 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="FriendList" name="friendList" native="true">
|
<widget class="NewFriendList" name="friendList" native="true">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
|
@ -353,11 +350,6 @@
|
||||||
</action>
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
<customwidget>
|
|
||||||
<class>StyledLabel</class>
|
|
||||||
<extends>QLabel</extends>
|
|
||||||
<header>gui/common/StyledLabel.h</header>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>AvatarWidget</class>
|
<class>AvatarWidget</class>
|
||||||
<extends>QLabel</extends>
|
<extends>QLabel</extends>
|
||||||
|
@ -365,9 +357,14 @@
|
||||||
<container>1</container>
|
<container>1</container>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>FriendList</class>
|
<class>StyledLabel</class>
|
||||||
|
<extends>QLabel</extends>
|
||||||
|
<header>gui/common/StyledLabel.h</header>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>ChatWidget</class>
|
||||||
<extends>QWidget</extends>
|
<extends>QWidget</extends>
|
||||||
<header>gui/common/FriendList.h</header>
|
<header location="global">gui/chat/ChatWidget.h</header>
|
||||||
<container>1</container>
|
<container>1</container>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
|
@ -382,9 +379,9 @@
|
||||||
<header>gui/common/StyledElidedLabel.h</header>
|
<header>gui/common/StyledElidedLabel.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>ChatWidget</class>
|
<class>NewFriendList</class>
|
||||||
<extends>QWidget</extends>
|
<extends>QWidget</extends>
|
||||||
<header location="global">gui/chat/ChatWidget.h</header>
|
<header>gui/common/NewFriendList.h</header>
|
||||||
<container>1</container>
|
<container>1</container>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
|
|
|
@ -183,11 +183,11 @@ void IdDetailsDialog::insertIdDetails(uint32_t token)
|
||||||
|
|
||||||
QPixmap pixmap;
|
QPixmap pixmap;
|
||||||
|
|
||||||
if(data.mImage.mSize > 0 && pixmap.loadFromData(data.mImage.mData, data.mImage.mSize, "PNG"))
|
if(data.mImage.mSize > 0 && GxsIdDetails::loadPixmapFromData(data.mImage.mData, data.mImage.mSize, pixmap, GxsIdDetails::LARGE))
|
||||||
ui->avatarLabel->setPixmap(pixmap) ;
|
ui->avatarLabel->setPixmap(pixmap);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pixmap = QPixmap::fromImage(GxsIdDetails::makeDefaultIcon(RsGxsId(data.mMeta.mGroupId)) ) ;
|
pixmap = GxsIdDetails::makeDefaultIcon(RsGxsId(data.mMeta.mGroupId),GxsIdDetails::LARGE) ;
|
||||||
ui->avatarLabel->setPixmap(pixmap) ; // we need to use the default pixmap here, generated from the ID
|
ui->avatarLabel->setPixmap(pixmap) ; // we need to use the default pixmap here, generated from the ID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -752,8 +752,8 @@ void IdDialog::loadCircleGroupMeta(const uint32_t &token)
|
||||||
|
|
||||||
QPixmap pixmap ;
|
QPixmap pixmap ;
|
||||||
|
|
||||||
if(idd.mAvatar.mSize == 0 || !pixmap.loadFromData(idd.mAvatar.mData, idd.mAvatar.mSize, "PNG"))
|
if(idd.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(idd.mAvatar.mData, idd.mAvatar.mSize, pixmap,GxsIdDetails::SMALL))
|
||||||
pixmap = QPixmap::fromImage(GxsIdDetails::makeDefaultIcon(it->first)) ;
|
pixmap = GxsIdDetails::makeDefaultIcon(it->first,GxsIdDetails::SMALL) ;
|
||||||
|
|
||||||
if(has_id)
|
if(has_id)
|
||||||
subitem->setText(CIRCLEGROUP_CIRCLE_COL_GROUPNAME, QString::fromUtf8(idd.mNickname.c_str())) ;
|
subitem->setText(CIRCLEGROUP_CIRCLE_COL_GROUPNAME, QString::fromUtf8(idd.mNickname.c_str())) ;
|
||||||
|
@ -1551,8 +1551,8 @@ bool IdDialog::fillIdListItem(const RsGxsIdGroup& data, QTreeWidgetItem *&item,
|
||||||
|
|
||||||
QPixmap pixmap ;
|
QPixmap pixmap ;
|
||||||
|
|
||||||
if(data.mImage.mSize == 0 || !pixmap.loadFromData(data.mImage.mData, data.mImage.mSize, "PNG"))
|
if(data.mImage.mSize == 0 || !GxsIdDetails::loadPixmapFromData(data.mImage.mData, data.mImage.mSize, pixmap,GxsIdDetails::SMALL))
|
||||||
pixmap = QPixmap::fromImage(GxsIdDetails::makeDefaultIcon(RsGxsId(data.mMeta.mGroupId))) ;
|
pixmap = GxsIdDetails::makeDefaultIcon(RsGxsId(data.mMeta.mGroupId),GxsIdDetails::SMALL) ;
|
||||||
|
|
||||||
item->setIcon(RSID_COL_NICKNAME, QIcon(pixmap));
|
item->setIcon(RSID_COL_NICKNAME, QIcon(pixmap));
|
||||||
|
|
||||||
|
@ -1797,8 +1797,8 @@ void IdDialog::insertIdDetails(uint32_t token)
|
||||||
|
|
||||||
QPixmap pixmap ;
|
QPixmap pixmap ;
|
||||||
|
|
||||||
if(data.mImage.mSize == 0 || !pixmap.loadFromData(data.mImage.mData, data.mImage.mSize, "PNG"))
|
if(data.mImage.mSize == 0 || !GxsIdDetails::loadPixmapFromData(data.mImage.mData, data.mImage.mSize, pixmap,GxsIdDetails::LARGE))
|
||||||
pixmap = QPixmap::fromImage(GxsIdDetails::makeDefaultIcon(RsGxsId(data.mMeta.mGroupId))) ;
|
pixmap = GxsIdDetails::makeDefaultIcon(RsGxsId(data.mMeta.mGroupId),GxsIdDetails::LARGE) ;
|
||||||
|
|
||||||
#ifdef ID_DEBUG
|
#ifdef ID_DEBUG
|
||||||
std::cerr << "Setting header frame image : " << pixmap.width() << " x " << pixmap.height() << std::endl;
|
std::cerr << "Setting header frame image : " << pixmap.width() << " x " << pixmap.height() << std::endl;
|
||||||
|
@ -1988,10 +1988,10 @@ QString IdDialog::createUsageString(const RsIdentityUsage& u) const
|
||||||
|
|
||||||
switch(u.mServiceId)
|
switch(u.mServiceId)
|
||||||
{
|
{
|
||||||
case RS_SERVICE_GXS_TYPE_CHANNELS: service_name = tr("Channels") ;service_type = RetroShareLink::TYPE_CHANNEL ; break ;
|
case RsServiceType::CHANNELS: service_name = tr("Channels") ;service_type = RetroShareLink::TYPE_CHANNEL ; break ;
|
||||||
case RS_SERVICE_GXS_TYPE_FORUMS: service_name = tr("Forums") ; service_type = RetroShareLink::TYPE_FORUM ; break ;
|
case RsServiceType::FORUMS: service_name = tr("Forums") ; service_type = RetroShareLink::TYPE_FORUM ; break ;
|
||||||
case RS_SERVICE_GXS_TYPE_POSTED: service_name = tr("Posted") ; service_type = RetroShareLink::TYPE_POSTED ; break ;
|
case RsServiceType::POSTED: service_name = tr("Posted") ; service_type = RetroShareLink::TYPE_POSTED ; break ;
|
||||||
case RS_SERVICE_TYPE_CHAT: service_name = tr("Chat") ; service_type = RetroShareLink::TYPE_CHAT_ROOM ; break ;
|
case RsServiceType::CHAT: service_name = tr("Chat") ; service_type = RetroShareLink::TYPE_CHAT_ROOM ; break ;
|
||||||
default:
|
default:
|
||||||
service_name = tr("Unknown"); service_type = RetroShareLink::TYPE_UNKNOWN ;
|
service_name = tr("Unknown"); service_type = RetroShareLink::TYPE_UNKNOWN ;
|
||||||
}
|
}
|
||||||
|
@ -2470,8 +2470,8 @@ void IdDialog::IdListCustomPopupMenu( QPoint )
|
||||||
|
|
||||||
QPixmap pixmap ;
|
QPixmap pixmap ;
|
||||||
|
|
||||||
if(idd.mAvatar.mSize == 0 || !pixmap.loadFromData(idd.mAvatar.mData, idd.mAvatar.mSize, "PNG"))
|
if(idd.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(idd.mAvatar.mData, idd.mAvatar.mSize, pixmap,GxsIdDetails::SMALL))
|
||||||
pixmap = QPixmap::fromImage(GxsIdDetails::makeDefaultIcon(*it)) ;
|
pixmap = GxsIdDetails::makeDefaultIcon(*it,GxsIdDetails::SMALL) ;
|
||||||
|
|
||||||
QAction *action = mnu->addAction(QIcon(pixmap), QString("%1 (%2)").arg(QString::fromUtf8(idd.mNickname.c_str()), QString::fromStdString((*it).toStdString())), this, SLOT(chatIdentity()));
|
QAction *action = mnu->addAction(QIcon(pixmap), QString("%1 (%2)").arg(QString::fromUtf8(idd.mNickname.c_str()), QString::fromStdString((*it).toStdString())), this, SLOT(chatIdentity()));
|
||||||
action->setData(QString::fromStdString((*it).toStdString())) ;
|
action->setData(QString::fromStdString((*it).toStdString())) ;
|
||||||
|
|
|
@ -195,7 +195,7 @@ void IdEditDialog::setAvatar(const QPixmap &avatar)
|
||||||
ui->avatarLabel->setPixmap(mAvatar);
|
ui->avatarLabel->setPixmap(mAvatar);
|
||||||
} else {
|
} else {
|
||||||
// we need to use the default pixmap here, generated from the ID
|
// we need to use the default pixmap here, generated from the ID
|
||||||
ui->avatarLabel->setPixmap(QPixmap::fromImage(GxsIdDetails::makeDefaultIcon(RsGxsId(mEditGroup.mMeta.mGroupId))));
|
ui->avatarLabel->setPixmap(GxsIdDetails::makeDefaultIcon(RsGxsId(mEditGroup.mMeta.mGroupId)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,9 +257,8 @@ void IdEditDialog::loadExistingId(uint32_t token)
|
||||||
mGroupId = mEditGroup.mMeta.mGroupId;
|
mGroupId = mEditGroup.mMeta.mGroupId;
|
||||||
|
|
||||||
QPixmap avatar;
|
QPixmap avatar;
|
||||||
if (mEditGroup.mImage.mSize > 0) {
|
if (mEditGroup.mImage.mSize > 0)
|
||||||
avatar.loadFromData(mEditGroup.mImage.mData, mEditGroup.mImage.mSize, "PNG");
|
GxsIdDetails::loadPixmapFromData(mEditGroup.mImage.mData, mEditGroup.mImage.mSize, avatar,GxsIdDetails::LARGE);
|
||||||
}
|
|
||||||
|
|
||||||
setAvatar(avatar);
|
setAvatar(avatar);
|
||||||
|
|
||||||
|
|
|
@ -31,10 +31,13 @@
|
||||||
#include <retroshare/rsplugin.h>
|
#include <retroshare/rsplugin.h>
|
||||||
#include <retroshare/rsconfig.h>
|
#include <retroshare/rsconfig.h>
|
||||||
|
|
||||||
|
#ifdef MESSENGER_WINDOW
|
||||||
|
#include "MessengerWindow.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "rshare.h"
|
#include "rshare.h"
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
#include "ui_MainWindow.h"
|
#include "ui_MainWindow.h"
|
||||||
#include "MessengerWindow.h"
|
|
||||||
#include "HomePage.h"
|
#include "HomePage.h"
|
||||||
#include "NetworkDialog.h"
|
#include "NetworkDialog.h"
|
||||||
#include "gui/FileTransfer/SearchDialog.h"
|
#include "gui/FileTransfer/SearchDialog.h"
|
||||||
|
@ -172,6 +175,16 @@ MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags flags)
|
||||||
ui = new Ui::MainWindow;
|
ui = new Ui::MainWindow;
|
||||||
trayIcon = NULL;
|
trayIcon = NULL;
|
||||||
|
|
||||||
|
friendsDialog=NULL;
|
||||||
|
idDialog=NULL;
|
||||||
|
chatLobbyDialog=NULL;
|
||||||
|
settingsDialog=NULL;
|
||||||
|
transfersDialog=NULL;
|
||||||
|
messagesDialog=NULL;
|
||||||
|
gxschannelDialog=NULL;
|
||||||
|
gxsforumDialog=NULL;
|
||||||
|
postedDialog=NULL;
|
||||||
|
|
||||||
/* Invoke the Qt Designer generated QObject setup routine */
|
/* Invoke the Qt Designer generated QObject setup routine */
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
@ -359,7 +372,9 @@ MainWindow::~MainWindow()
|
||||||
delete soundStatus;
|
delete soundStatus;
|
||||||
delete toasterDisable;
|
delete toasterDisable;
|
||||||
delete sysTrayStatus;
|
delete sysTrayStatus;
|
||||||
|
#ifdef MESSENGER_WINDOW
|
||||||
MessengerWindow::releaseInstance();
|
MessengerWindow::releaseInstance();
|
||||||
|
#endif
|
||||||
#ifdef UNFINISHED
|
#ifdef UNFINISHED
|
||||||
delete applicationWindow;
|
delete applicationWindow;
|
||||||
#endif
|
#endif
|
||||||
|
@ -586,7 +601,9 @@ void MainWindow::createTrayIcon()
|
||||||
notifyMenu->menuAction()->setVisible(false);
|
notifyMenu->menuAction()->setVisible(false);
|
||||||
|
|
||||||
trayMenu->addSeparator();
|
trayMenu->addSeparator();
|
||||||
|
#ifdef MESSENGER_WINDOW
|
||||||
trayMenu->addAction(QIcon(IMAGE_MESSENGER), tr("Open Messenger"), this, SLOT(showMessengerWindow()));
|
trayMenu->addAction(QIcon(IMAGE_MESSENGER), tr("Open Messenger"), this, SLOT(showMessengerWindow()));
|
||||||
|
#endif
|
||||||
trayMenu->addAction(QIcon(IMAGE_MESSAGES), tr("Open Messages"), this, SLOT(showMess()));
|
trayMenu->addAction(QIcon(IMAGE_MESSAGES), tr("Open Messages"), this, SLOT(showMess()));
|
||||||
#ifdef ENABLE_WEBUI
|
#ifdef ENABLE_WEBUI
|
||||||
trayMenu->addAction(QIcon(":/images/emblem-web.png"), tr("Show web interface"), this, SLOT(showWebinterface()));
|
trayMenu->addAction(QIcon(":/images/emblem-web.png"), tr("Show web interface"), this, SLOT(showWebinterface()));
|
||||||
|
@ -1085,11 +1102,13 @@ void MainWindow::showSettings()
|
||||||
showWindow(MainWindow::Options);
|
showWindow(MainWindow::Options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MESSENGER_WINDOW
|
||||||
/** Shows Messenger window */
|
/** Shows Messenger window */
|
||||||
void MainWindow::showMessengerWindow()
|
void MainWindow::showMessengerWindow()
|
||||||
{
|
{
|
||||||
MessengerWindow::showYourself();
|
MessengerWindow::showYourself();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/** Shows Statistics window */
|
/** Shows Statistics window */
|
||||||
void MainWindow::showStatisticsWindow()
|
void MainWindow::showStatisticsWindow()
|
||||||
|
|
|
@ -59,7 +59,6 @@ class NetworkDialog;
|
||||||
class SearchDialog;
|
class SearchDialog;
|
||||||
class TransfersDialog;
|
class TransfersDialog;
|
||||||
class MessagesDialog;
|
class MessagesDialog;
|
||||||
class MessengerWindow;
|
|
||||||
class PluginsPage;
|
class PluginsPage;
|
||||||
class HomePage;
|
class HomePage;
|
||||||
//class ChannelFeed;
|
//class ChannelFeed;
|
||||||
|
@ -68,6 +67,9 @@ class MainPage;
|
||||||
class NewsFeed;
|
class NewsFeed;
|
||||||
class UserNotify;
|
class UserNotify;
|
||||||
|
|
||||||
|
#ifdef MESSENGER_WINDOW
|
||||||
|
class MessengerWindow;
|
||||||
|
#endif
|
||||||
#ifdef UNFINISHED
|
#ifdef UNFINISHED
|
||||||
class ApplicationWindow;
|
class ApplicationWindow;
|
||||||
#endif
|
#endif
|
||||||
|
@ -224,7 +226,9 @@ private slots:
|
||||||
/** Toolbar fns. */
|
/** Toolbar fns. */
|
||||||
void addFriend();
|
void addFriend();
|
||||||
//void newRsCollection();
|
//void newRsCollection();
|
||||||
|
#ifdef MESSENGER_WINDOW
|
||||||
void showMessengerWindow();
|
void showMessengerWindow();
|
||||||
|
#endif
|
||||||
void showStatisticsWindow();
|
void showStatisticsWindow();
|
||||||
#ifdef ENABLE_WEBUI
|
#ifdef ENABLE_WEBUI
|
||||||
void showWebinterface();
|
void showWebinterface();
|
||||||
|
|
|
@ -100,7 +100,8 @@ void IdentityWidget::updateData(const RsGxsIdGroup &gxs_group_info)
|
||||||
ui->labelPositive->setText(QString::number(info.mFriendsPositiveVotes));
|
ui->labelPositive->setText(QString::number(info.mFriendsPositiveVotes));
|
||||||
ui->labelNegative->setText(QString::number(info.mFriendsNegativeVotes));
|
ui->labelNegative->setText(QString::number(info.mFriendsNegativeVotes));
|
||||||
|
|
||||||
if (!_havePGPDetail) {
|
if (!_havePGPDetail)
|
||||||
|
{
|
||||||
QFont font = ui->labelName->font();
|
QFont font = ui->labelName->font();
|
||||||
font.setItalic(false);
|
font.setItalic(false);
|
||||||
ui->labelName->setFont(font);
|
ui->labelName->setFont(font);
|
||||||
|
@ -111,20 +112,16 @@ void IdentityWidget::updateData(const RsGxsIdGroup &gxs_group_info)
|
||||||
ui->labelKeyId->setVisible(false);
|
ui->labelKeyId->setVisible(false);
|
||||||
|
|
||||||
/// (TODO) Get real ident icon
|
/// (TODO) Get real ident icon
|
||||||
QImage image;
|
QPixmap pixmap;
|
||||||
|
|
||||||
if(!( (_group_info.mImage.mSize > 0) && image.loadFromData(_group_info.mImage.mData, _group_info.mImage.mSize, "PNG") ))
|
if(!( (_group_info.mImage.mSize > 0) && GxsIdDetails::loadPixmapFromData(_group_info.mImage.mData, _group_info.mImage.mSize, pixmap) ))
|
||||||
image = GxsIdDetails::makeDefaultIcon(RsGxsId(_group_info.mMeta.mGroupId));
|
pixmap = GxsIdDetails::makeDefaultIcon(RsGxsId(_group_info.mMeta.mGroupId));
|
||||||
|
|
||||||
if (_avatar != image) {
|
_avatar = pixmap.toImage();
|
||||||
_avatar = image;
|
|
||||||
_scene->clear();
|
_scene->clear();
|
||||||
_scene->addPixmap(QPixmap::fromImage(image.scaled(ui->graphicsView->width(),ui->graphicsView->height())));
|
_scene->addPixmap(pixmap.scaled(ui->graphicsView->width(),ui->graphicsView->height()));
|
||||||
emit imageUpdated();
|
emit imageUpdated();
|
||||||
}//if (_avatar != image)
|
}
|
||||||
}//if (!_havePGPDetail)
|
|
||||||
|
|
||||||
//}//if (_group_info != gxs_group_info)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IdentityWidget::updateData(const RsPeerDetails &pgp_details)
|
void IdentityWidget::updateData(const RsPeerDetails &pgp_details)
|
||||||
|
@ -136,12 +133,10 @@ void IdentityWidget::updateData(const RsPeerDetails &pgp_details)
|
||||||
_nickname = QString::fromUtf8(_details.name.c_str());
|
_nickname = QString::fromUtf8(_details.name.c_str());
|
||||||
if (!_haveGXSId) m_myName = _nickname;
|
if (!_haveGXSId) m_myName = _nickname;
|
||||||
ui->labelName->setText(m_myName);
|
ui->labelName->setText(m_myName);
|
||||||
if (_haveGXSId) {
|
if (_haveGXSId)
|
||||||
ui->labelName->setToolTip(tr("GXS name:") + (" "+m_myName) + ("\n")
|
ui->labelName->setToolTip(tr("GXS name:") + (" "+m_myName) + ("\n") +(tr("PGP name:")+(" "+_nickname)));
|
||||||
+(tr("PGP name:")+(" "+_nickname)));
|
else
|
||||||
} else {//if (m_myName != _nickname)
|
|
||||||
ui->labelName->setToolTip(tr("PGP name:")+(" "+_nickname));
|
ui->labelName->setToolTip(tr("PGP name:")+(" "+_nickname));
|
||||||
}//else (m_myName != _nickname)
|
|
||||||
|
|
||||||
QFont font = ui->labelName->font();
|
QFont font = ui->labelName->font();
|
||||||
font.setItalic(true);
|
font.setItalic(true);
|
||||||
|
@ -210,11 +205,6 @@ void IdentityWidget::setIsSelected(bool value)
|
||||||
font.setBold(value);
|
font.setBold(value);
|
||||||
ui->labelName->setFont(font);
|
ui->labelName->setFont(font);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
bool IdentityWidget::isSelected()
|
|
||||||
{
|
|
||||||
return m_isSelected;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
void IdentityWidget::setIsCurrent(bool value)
|
void IdentityWidget::setIsCurrent(bool value)
|
||||||
{
|
{
|
||||||
|
@ -227,11 +217,6 @@ void IdentityWidget::setIsCurrent(bool value)
|
||||||
ui->label_NegIcon_2->setVisible(value);
|
ui->label_NegIcon_2->setVisible(value);
|
||||||
ui->pbAdd->setVisible(value);
|
ui->pbAdd->setVisible(value);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
bool IdentityWidget::isCurrent()
|
|
||||||
{
|
|
||||||
return m_isCurrent;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
void IdentityWidget::pbAdd_clicked()
|
void IdentityWidget::pbAdd_clicked()
|
||||||
{
|
{
|
||||||
|
|
|
@ -426,15 +426,15 @@ void PeopleDialog::iw_AddButtonClickedExt()
|
||||||
{
|
{
|
||||||
IdentityWidget *dest=
|
IdentityWidget *dest=
|
||||||
qobject_cast<IdentityWidget *>(QObject::sender());
|
qobject_cast<IdentityWidget *>(QObject::sender());
|
||||||
if (dest) {
|
if (dest)
|
||||||
|
{
|
||||||
QMenu contextMnu( this );
|
QMenu contextMnu( this );
|
||||||
|
|
||||||
QMenu *mnu = contextMnu.addMenu(QIcon(":/icons/png/circles.png"),tr("Invite to Circle")) ;
|
QMenu *mnu = contextMnu.addMenu(QIcon(":/icons/png/circles.png"),tr("Invite to Circle")) ;
|
||||||
|
|
||||||
std::map<RsGxsGroupId, CircleWidget*>::iterator itCurs;
|
std::map<RsGxsGroupId, CircleWidget*>::iterator itCurs;
|
||||||
for( itCurs =_ext_circles_widgets.begin();
|
for( itCurs =_ext_circles_widgets.begin(); itCurs != _ext_circles_widgets.end(); ++itCurs)
|
||||||
itCurs != _ext_circles_widgets.end();
|
{
|
||||||
++itCurs) {
|
|
||||||
CircleWidget *curs = itCurs->second;
|
CircleWidget *curs = itCurs->second;
|
||||||
QIcon icon = QIcon(curs->getImage());
|
QIcon icon = QIcon(curs->getImage());
|
||||||
QString name = curs->getName();
|
QString name = curs->getName();
|
||||||
|
@ -442,7 +442,7 @@ void PeopleDialog::iw_AddButtonClickedExt()
|
||||||
QAction *action = mnu->addAction(icon, name, this, SLOT(addToCircleExt()));
|
QAction *action = mnu->addAction(icon, name, this, SLOT(addToCircleExt()));
|
||||||
action->setData(QString::fromStdString(curs->groupInfo().mGroupId.toStdString())
|
action->setData(QString::fromStdString(curs->groupInfo().mGroupId.toStdString())
|
||||||
+ ";" + QString::fromStdString(dest->groupInfo().mMeta.mGroupId.toStdString()));
|
+ ";" + QString::fromStdString(dest->groupInfo().mMeta.mGroupId.toStdString()));
|
||||||
}//for( itCurs =_ext_circles_widgets.begin();
|
}
|
||||||
|
|
||||||
std::list<RsGxsId> own_identities ;
|
std::list<RsGxsId> own_identities ;
|
||||||
rsIdentity->getOwnIds(own_identities) ;
|
rsIdentity->getOwnIds(own_identities) ;
|
||||||
|
@ -467,8 +467,8 @@ void PeopleDialog::iw_AddButtonClickedExt()
|
||||||
|
|
||||||
QPixmap pixmap ;
|
QPixmap pixmap ;
|
||||||
|
|
||||||
if(idd.mAvatar.mSize == 0 || !pixmap.loadFromData(idd.mAvatar.mData, idd.mAvatar.mSize, "PNG"))
|
if(idd.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(idd.mAvatar.mData, idd.mAvatar.mSize, pixmap,GxsIdDetails::SMALL))
|
||||||
pixmap = QPixmap::fromImage(GxsIdDetails::makeDefaultIcon(*it)) ;
|
pixmap = GxsIdDetails::makeDefaultIcon(*it,GxsIdDetails::SMALL) ;
|
||||||
|
|
||||||
QAction *action = mnu->addAction(QIcon(pixmap), QString("%1 (%2)").arg(QString::fromUtf8(idd.mNickname.c_str()), QString::fromStdString((*it).toStdString())), this, SLOT(chatIdentity()));
|
QAction *action = mnu->addAction(QIcon(pixmap), QString("%1 (%2)").arg(QString::fromUtf8(idd.mNickname.c_str()), QString::fromStdString((*it).toStdString())), this, SLOT(chatIdentity()));
|
||||||
action->setData(QString::fromStdString((*it).toStdString()) + ";" + QString::fromStdString(dest->groupInfo().mMeta.mGroupId.toStdString())) ;
|
action->setData(QString::fromStdString((*it).toStdString()) + ";" + QString::fromStdString(dest->groupInfo().mMeta.mGroupId.toStdString())) ;
|
||||||
|
@ -492,7 +492,7 @@ void PeopleDialog::iw_AddButtonClickedExt()
|
||||||
actionDetails->setData( QString::fromStdString(dest->groupInfo().mMeta.mGroupId.toStdString()));
|
actionDetails->setData( QString::fromStdString(dest->groupInfo().mMeta.mGroupId.toStdString()));
|
||||||
|
|
||||||
contextMnu.exec(QCursor::pos());
|
contextMnu.exec(QCursor::pos());
|
||||||
}//if (dest)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeopleDialog::iw_AddButtonClickedInt()
|
void PeopleDialog::iw_AddButtonClickedInt()
|
||||||
|
@ -513,10 +513,10 @@ void PeopleDialog::iw_AddButtonClickedInt()
|
||||||
QAction *action = contextMnu.addAction(icon, name, this, SLOT(addToCircleInt()));
|
QAction *action = contextMnu.addAction(icon, name, this, SLOT(addToCircleInt()));
|
||||||
action->setData(QString::fromStdString(curs->groupInfo().mGroupId.toStdString())
|
action->setData(QString::fromStdString(curs->groupInfo().mGroupId.toStdString())
|
||||||
+ ";" + QString::fromStdString(dest->details().gpg_id.toStdString()));
|
+ ";" + QString::fromStdString(dest->details().gpg_id.toStdString()));
|
||||||
}//for( itCurs =_int_circles_widgets.begin();
|
}
|
||||||
|
|
||||||
contextMnu.exec(QCursor::pos());
|
contextMnu.exec(QCursor::pos());
|
||||||
}//if (dest)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeopleDialog::addToCircleExt()
|
void PeopleDialog::addToCircleExt()
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <QPixmap>
|
#include <QPixmap>
|
||||||
|
|
||||||
#include "AlbumDialog.h"
|
#include "AlbumDialog.h"
|
||||||
|
#include "gui/gxs/GxsIdDetails.h"
|
||||||
#include "ui_AlbumDialog.h"
|
#include "ui_AlbumDialog.h"
|
||||||
#include "retroshare/rsgxsflags.h"
|
#include "retroshare/rsgxsflags.h"
|
||||||
|
|
||||||
|
@ -60,7 +61,7 @@ void AlbumDialog::setUp()
|
||||||
|
|
||||||
|
|
||||||
QPixmap qtn;
|
QPixmap qtn;
|
||||||
qtn.loadFromData(mAlbum.mThumbnail.data, mAlbum.mThumbnail.size, mAlbum.mThumbnail.type.c_str());
|
GxsIdDetails::loadPixmapFromData(mAlbum.mThumbnail.data, mAlbum.mThumbnail.size, mAlbum.mThumbnail.type.c_str(),qtn);
|
||||||
|
|
||||||
if(mAlbum.mThumbnail.size != 0)
|
if(mAlbum.mThumbnail.size != 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -165,7 +165,7 @@ void PostedDialog::loadGroupSummaryToken(const uint32_t &token, std::list<RsGrou
|
||||||
|
|
||||||
if (group.mGroupImage.mData != NULL) {
|
if (group.mGroupImage.mData != NULL) {
|
||||||
QPixmap image;
|
QPixmap image;
|
||||||
image.loadFromData(group.mGroupImage.mData, group.mGroupImage.mSize, "PNG");
|
GxsIdDetails::loadPixmapFromData(group.mGroupImage.mData, group.mGroupImage.mSize, image,GxsIdDetails::ORIGINAL);
|
||||||
postedData->mIcon[group.mMeta.mGroupId] = image;
|
postedData->mIcon[group.mMeta.mGroupId] = image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <QBuffer>
|
#include <QBuffer>
|
||||||
|
|
||||||
#include "PostedGroupDialog.h"
|
#include "PostedGroupDialog.h"
|
||||||
|
#include "gui/gxs/GxsIdDetails.h"
|
||||||
|
|
||||||
#include <retroshare/rswiki.h>
|
#include <retroshare/rswiki.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
@ -163,9 +164,9 @@ bool PostedGroupDialog::service_loadGroup(uint32_t token, Mode /*mode*/, RsGroup
|
||||||
|
|
||||||
if (group.mGroupImage.mData) {
|
if (group.mGroupImage.mData) {
|
||||||
QPixmap pixmap;
|
QPixmap pixmap;
|
||||||
if (pixmap.loadFromData(group.mGroupImage.mData, group.mGroupImage.mSize, "PNG")) {
|
if (GxsIdDetails::loadPixmapFromData(group.mGroupImage.mData, group.mGroupImage.mSize, pixmap,GxsIdDetails::ORIGINAL))
|
||||||
setLogo(pixmap);
|
setLogo(pixmap);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
setLogo(QPixmap(":/icons/png/posted.png"));
|
setLogo(QPixmap(":/icons/png/posted.png"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "rshare.h"
|
#include "rshare.h"
|
||||||
#include "PostedItem.h"
|
#include "PostedItem.h"
|
||||||
#include "gui/feeds/FeedHolder.h"
|
#include "gui/feeds/FeedHolder.h"
|
||||||
|
#include "gui/gxs/GxsIdDetails.h"
|
||||||
#include "util/misc.h"
|
#include "util/misc.h"
|
||||||
|
|
||||||
#include "ui_PostedItem.h"
|
#include "ui_PostedItem.h"
|
||||||
|
@ -255,7 +256,7 @@ void PostedItem::fill()
|
||||||
if(mPost.mImage.mData != NULL)
|
if(mPost.mImage.mData != NULL)
|
||||||
{
|
{
|
||||||
QPixmap pixmap;
|
QPixmap pixmap;
|
||||||
pixmap.loadFromData(mPost.mImage.mData, mPost.mImage.mSize, "PNG");
|
GxsIdDetails::loadPixmapFromData(mPost.mImage.mData, mPost.mImage.mSize, pixmap,GxsIdDetails::ORIGINAL);
|
||||||
// Wiping data - as its been passed to thumbnail.
|
// Wiping data - as its been passed to thumbnail.
|
||||||
|
|
||||||
QPixmap sqpixmap = pixmap.scaled(desired_width,desired_height, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
|
QPixmap sqpixmap = pixmap.scaled(desired_width,desired_height, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
|
||||||
|
|
|
@ -424,9 +424,8 @@ ChatLobbyDialog::~ChatLobbyDialog()
|
||||||
// announce leaving of lobby
|
// announce leaving of lobby
|
||||||
|
|
||||||
// check that the lobby still exists.
|
// check that the lobby still exists.
|
||||||
if (mChatId.isLobbyId()) {
|
if (mChatId.isLobbyId())
|
||||||
rsMsgs->unsubscribeChatLobby(mChatId.toLobbyId());
|
rsMsgs->sendLobbyStatusPeerLeaving(mChatId.toLobbyId());
|
||||||
}
|
|
||||||
|
|
||||||
// save settings
|
// save settings
|
||||||
processSettings(false);
|
processSettings(false);
|
||||||
|
@ -912,7 +911,10 @@ void ChatLobbyDialog::showDialog(uint chatflags)
|
||||||
if (chatflags & RS_CHAT_FOCUS)
|
if (chatflags & RS_CHAT_FOCUS)
|
||||||
{
|
{
|
||||||
MainWindow::showWindow(MainWindow::ChatLobby);
|
MainWindow::showWindow(MainWindow::ChatLobby);
|
||||||
dynamic_cast<ChatLobbyWidget*>(MainWindow::getPage(MainWindow::ChatLobby))->setCurrentChatPage(this) ;
|
MainPage *p = MainWindow::getPage(MainWindow::ChatLobby);
|
||||||
|
|
||||||
|
if(p != NULL)
|
||||||
|
dynamic_cast<ChatLobbyWidget*>(p)->setCurrentChatPage(this) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,6 +94,8 @@ ChatWidget::ChatWidget(QWidget *parent)
|
||||||
//Resize Tool buttons
|
//Resize Tool buttons
|
||||||
ui->emoteiconButton->setFixedSize(buttonSize);
|
ui->emoteiconButton->setFixedSize(buttonSize);
|
||||||
ui->emoteiconButton->setIconSize(iconSize);
|
ui->emoteiconButton->setIconSize(iconSize);
|
||||||
|
ui->stickerButton->setFixedSize(buttonSize);
|
||||||
|
ui->stickerButton->setIconSize(iconSize);
|
||||||
ui->attachPictureButton->setFixedSize(buttonSize);
|
ui->attachPictureButton->setFixedSize(buttonSize);
|
||||||
ui->attachPictureButton->setIconSize(iconSize);
|
ui->attachPictureButton->setIconSize(iconSize);
|
||||||
ui->addFileButton->setFixedSize(buttonSize);
|
ui->addFileButton->setFixedSize(buttonSize);
|
||||||
|
@ -145,6 +147,7 @@ ChatWidget::ChatWidget(QWidget *parent)
|
||||||
ui->markButton->setToolTip(tr("<b>Mark this selected text</b><br><i>Ctrl+M</i>"));
|
ui->markButton->setToolTip(tr("<b>Mark this selected text</b><br><i>Ctrl+M</i>"));
|
||||||
|
|
||||||
connect(ui->emoteiconButton, SIGNAL(clicked()), this, SLOT(smileyWidget()));
|
connect(ui->emoteiconButton, SIGNAL(clicked()), this, SLOT(smileyWidget()));
|
||||||
|
connect(ui->stickerButton, SIGNAL(clicked()), this, SLOT(stickerWidget()));
|
||||||
connect(ui->attachPictureButton, SIGNAL(clicked()), this, SLOT(addExtraPicture()));
|
connect(ui->attachPictureButton, SIGNAL(clicked()), this, SLOT(addExtraPicture()));
|
||||||
connect(ui->addFileButton, SIGNAL(clicked()), this , SLOT(addExtraFile()));
|
connect(ui->addFileButton, SIGNAL(clicked()), this , SLOT(addExtraFile()));
|
||||||
connect(ui->sendButton, SIGNAL(clicked()), this, SLOT(sendChat()));
|
connect(ui->sendButton, SIGNAL(clicked()), this, SLOT(sendChat()));
|
||||||
|
@ -1545,6 +1548,22 @@ void ChatWidget::addSmiley()
|
||||||
ui->chatTextEdit->textCursor().insertText(smiley);
|
ui->chatTextEdit->textCursor().insertText(smiley);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChatWidget::stickerWidget()
|
||||||
|
{
|
||||||
|
Emoticons::showStickerWidget(this, ui->stickerButton, SLOT(sendSticker()), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatWidget::sendSticker()
|
||||||
|
{
|
||||||
|
QString sticker = qobject_cast<QPushButton*>(sender())->statusTip();
|
||||||
|
QString encodedImage;
|
||||||
|
if (RsHtml::makeEmbeddedImage(sticker, encodedImage, 640*480, maxMessageSize() - 200)) { //-200 for the html stuff
|
||||||
|
RsHtml::optimizeHtml(encodedImage, 0);
|
||||||
|
std::string msg = encodedImage.toUtf8().constData();
|
||||||
|
rsMsgs->sendChat(chatId, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ChatWidget::clearChatHistory()
|
void ChatWidget::clearChatHistory()
|
||||||
{
|
{
|
||||||
ui->textBrowser->clear();
|
ui->textBrowser->clear();
|
||||||
|
|
|
@ -159,6 +159,8 @@ private slots:
|
||||||
|
|
||||||
void smileyWidget();
|
void smileyWidget();
|
||||||
void addSmiley();
|
void addSmiley();
|
||||||
|
void stickerWidget();
|
||||||
|
void sendSticker();
|
||||||
|
|
||||||
void addExtraFile();
|
void addExtraFile();
|
||||||
void addExtraPicture();
|
void addExtraPicture();
|
||||||
|
|
|
@ -343,6 +343,32 @@ border-image: url(:/images/closepressed.png)
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="stickerButton">
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Insert sticker</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../icons.qrc">
|
||||||
|
<normaloff>:/icons/png/new.png</normaloff>:/icons/png/new.png</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="iconSize">
|
||||||
|
<size>
|
||||||
|
<width>28</width>
|
||||||
|
<height>28</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="autoRaise">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QToolButton" name="attachPictureButton">
|
<widget class="QToolButton" name="attachPictureButton">
|
||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
#include <QPixmap>
|
#include <QPixmap>
|
||||||
#include <QCloseEvent>
|
#include <QCloseEvent>
|
||||||
|
#include <QMenu>
|
||||||
|
|
||||||
#include "PopupChatWindow.h"
|
#include "PopupChatWindow.h"
|
||||||
#include "ChatDialog.h"
|
#include "ChatDialog.h"
|
||||||
|
@ -75,21 +76,30 @@ PopupChatWindow::PopupChatWindow(bool tabbed, QWidget *parent, Qt::WindowFlags f
|
||||||
|
|
||||||
ui.tabWidget->setVisible(tabbedWindow);
|
ui.tabWidget->setVisible(tabbedWindow);
|
||||||
|
|
||||||
if (Settings->getChatFlags() & RS_CHAT_TABBED_WINDOW) {
|
// if (Settings->getChatFlags() & RS_CHAT_TABBED_WINDOW) {
|
||||||
ui.actionDockTab->setVisible(tabbedWindow == false);
|
// ui.actionDockTab->setVisible(tabbedWindow == false);
|
||||||
ui.actionUndockTab->setVisible(tabbedWindow);
|
// ui.actionUndockTab->setVisible(tabbedWindow);
|
||||||
} else {
|
// } else {
|
||||||
ui.actionDockTab->setVisible(false);
|
// ui.actionDockTab->setVisible(false);
|
||||||
ui.actionUndockTab->setVisible(false);
|
// ui.actionUndockTab->setVisible(false);
|
||||||
}
|
//
|
||||||
|
// }
|
||||||
|
|
||||||
|
// ui.actionAvatar->setVisible(false); // removed because it is already handled by clicking on your own avatar.
|
||||||
|
// ui.actionSetOnTop->setVisible(false);// removed, because the window manager should handle this already.
|
||||||
|
// ui.actionColor->setVisible(false);// moved to the context menu
|
||||||
|
|
||||||
|
ui.chattoolBar->hide(); // no widgets left!
|
||||||
|
|
||||||
setAttribute(Qt::WA_DeleteOnClose, true);
|
setAttribute(Qt::WA_DeleteOnClose, true);
|
||||||
|
|
||||||
connect(ui.actionAvatar, SIGNAL(triggered()),this, SLOT(getAvatar()));
|
// connect(ui.actionAvatar, SIGNAL(triggered()),this, SLOT(getAvatar()));
|
||||||
connect(ui.actionColor, SIGNAL(triggered()), this, SLOT(setStyle()));
|
// connect(ui.actionColor, SIGNAL(triggered()), this, SLOT(setStyle()));
|
||||||
connect(ui.actionDockTab, SIGNAL(triggered()), this, SLOT(dockTab()));
|
// connect(ui.actionDockTab, SIGNAL(triggered()), this, SLOT(dockTab()));
|
||||||
connect(ui.actionUndockTab, SIGNAL(triggered()), this, SLOT(undockTab()));
|
// connect(ui.actionUndockTab, SIGNAL(triggered()), this, SLOT(undockTab()));
|
||||||
connect(ui.actionSetOnTop, SIGNAL(toggled(bool)), this, SLOT(setOnTop()));
|
// connect(ui.actionSetOnTop, SIGNAL(toggled(bool)), this, SLOT(setOnTop()));
|
||||||
|
|
||||||
|
connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint)));
|
||||||
|
|
||||||
connect(ui.tabWidget, SIGNAL(tabChanged(ChatDialog*)), this, SLOT(tabChanged(ChatDialog*)));
|
connect(ui.tabWidget, SIGNAL(tabChanged(ChatDialog*)), this, SLOT(tabChanged(ChatDialog*)));
|
||||||
connect(ui.tabWidget, SIGNAL(tabClosed(ChatDialog*)), this, SLOT(tabClosed(ChatDialog*)));
|
connect(ui.tabWidget, SIGNAL(tabClosed(ChatDialog*)), this, SLOT(tabClosed(ChatDialog*)));
|
||||||
|
@ -102,6 +112,21 @@ PopupChatWindow::PopupChatWindow(bool tabbed, QWidget *parent, Qt::WindowFlags f
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PopupChatWindow::showContextMenu(QPoint)
|
||||||
|
{
|
||||||
|
QMenu contextMnu(this);
|
||||||
|
contextMnu.addAction(QIcon(":/images/highlight.png"),tr("Choose window color..."),this,SLOT(setStyle()));
|
||||||
|
|
||||||
|
if (Settings->getChatFlags() & RS_CHAT_TABBED_WINDOW)
|
||||||
|
{
|
||||||
|
if(tabbedWindow)
|
||||||
|
contextMnu.addAction(QIcon(":/images/tab-dock.png"),tr("Dock window"),this,SLOT(docTab()));
|
||||||
|
|
||||||
|
contextMnu.addAction(QIcon(":/images/tab-undock.png"),tr("Dock window"),this,SLOT(undockTab()));
|
||||||
|
}
|
||||||
|
contextMnu.exec(QCursor::pos());
|
||||||
|
}
|
||||||
|
|
||||||
/** Destructor. */
|
/** Destructor. */
|
||||||
PopupChatWindow::~PopupChatWindow()
|
PopupChatWindow::~PopupChatWindow()
|
||||||
{
|
{
|
||||||
|
|
|
@ -55,6 +55,7 @@ protected:
|
||||||
void closeEvent(QCloseEvent *event);
|
void closeEvent(QCloseEvent *event);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
void setStyle();
|
||||||
void getAvatar();
|
void getAvatar();
|
||||||
void tabChanged(ChatDialog *dialog);
|
void tabChanged(ChatDialog *dialog);
|
||||||
void tabInfoChanged(ChatDialog *dialog);
|
void tabInfoChanged(ChatDialog *dialog);
|
||||||
|
@ -63,9 +64,9 @@ private slots:
|
||||||
void dialogClose(ChatDialog *dialog);
|
void dialogClose(ChatDialog *dialog);
|
||||||
void dockTab();
|
void dockTab();
|
||||||
void undockTab();
|
void undockTab();
|
||||||
void setStyle();
|
|
||||||
void setOnTop();
|
void setOnTop();
|
||||||
void blink(bool on);
|
void blink(bool on);
|
||||||
|
void showContextMenu(QPoint p);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool tabbedWindow;
|
bool tabbedWindow;
|
||||||
|
|
|
@ -10,6 +10,9 @@
|
||||||
<height>451</height>
|
<height>451</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="contextMenuPolicy">
|
||||||
|
<enum>Qt::CustomContextMenu</enum>
|
||||||
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string notr="true">MainWindow</string>
|
<string notr="true">MainWindow</string>
|
||||||
</property>
|
</property>
|
||||||
|
|
|
@ -41,11 +41,11 @@ void AvatarDefs::getOwnAvatar(QPixmap &avatar, const QString& defaultImage)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* load image */
|
/* load image */
|
||||||
avatar.loadFromData(data, size, "PNG") ;
|
GxsIdDetails::loadPixmapFromData(data, size, avatar,GxsIdDetails::ORIGINAL) ;
|
||||||
|
|
||||||
free(data);
|
free(data);
|
||||||
}
|
}
|
||||||
void AvatarDefs::getAvatarFromSslId(const RsPeerId& sslId, QPixmap &avatar, const QString& defaultImage)
|
bool AvatarDefs::getAvatarFromSslId(const RsPeerId& sslId, QPixmap &avatar, const QString& defaultImage)
|
||||||
{
|
{
|
||||||
unsigned char *data = NULL;
|
unsigned char *data = NULL;
|
||||||
int size = 0;
|
int size = 0;
|
||||||
|
@ -54,15 +54,16 @@ void AvatarDefs::getAvatarFromSslId(const RsPeerId& sslId, QPixmap &avatar, cons
|
||||||
rsMsgs->getAvatarData(RsPeerId(sslId), data, size);
|
rsMsgs->getAvatarData(RsPeerId(sslId), data, size);
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
avatar = QPixmap(defaultImage);
|
avatar = QPixmap(defaultImage);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* load image */
|
/* load image */
|
||||||
avatar.loadFromData(data, size, "PNG") ;
|
GxsIdDetails::loadPixmapFromData(data, size, avatar, GxsIdDetails::LARGE) ;
|
||||||
|
|
||||||
free(data);
|
free(data);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
void AvatarDefs::getAvatarFromGxsId(const RsGxsId& gxsId, QPixmap &avatar, const QString& defaultImage)
|
bool AvatarDefs::getAvatarFromGxsId(const RsGxsId& gxsId, QPixmap &avatar, const QString& defaultImage)
|
||||||
{
|
{
|
||||||
//int size = 0;
|
//int size = 0;
|
||||||
|
|
||||||
|
@ -72,16 +73,18 @@ void AvatarDefs::getAvatarFromGxsId(const RsGxsId& gxsId, QPixmap &avatar, const
|
||||||
if(!rsIdentity->getIdDetails(gxsId, details))
|
if(!rsIdentity->getIdDetails(gxsId, details))
|
||||||
{
|
{
|
||||||
avatar = QPixmap(defaultImage);
|
avatar = QPixmap(defaultImage);
|
||||||
return ;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* load image */
|
/* load image */
|
||||||
|
|
||||||
if(details.mAvatar.mSize == 0 || !avatar.loadFromData(details.mAvatar.mData, details.mAvatar.mSize, "PNG"))
|
if(details.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(details.mAvatar.mData, details.mAvatar.mSize, avatar,GxsIdDetails::LARGE))
|
||||||
avatar = QPixmap::fromImage(GxsIdDetails::makeDefaultIcon(gxsId));
|
avatar = GxsIdDetails::makeDefaultIcon(gxsId,GxsIdDetails::LARGE);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarDefs::getAvatarFromGpgId(const RsPgpId& gpgId, QPixmap &avatar, const QString& defaultImage)
|
bool AvatarDefs::getAvatarFromGpgId(const RsPgpId& gpgId, QPixmap &avatar, const QString& defaultImage)
|
||||||
{
|
{
|
||||||
unsigned char *data = NULL;
|
unsigned char *data = NULL;
|
||||||
int size = 0;
|
int size = 0;
|
||||||
|
@ -105,11 +108,13 @@ void AvatarDefs::getAvatarFromGpgId(const RsPgpId& gpgId, QPixmap &avatar, const
|
||||||
|
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
avatar = QPixmap(defaultImage);
|
avatar = QPixmap(defaultImage);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* load image */
|
/* load image */
|
||||||
avatar.loadFromData(data, size, "PNG") ;
|
GxsIdDetails::loadPixmapFromData(data, size, avatar);
|
||||||
|
|
||||||
free(data);
|
free(data);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,9 +35,9 @@ class AvatarDefs
|
||||||
public:
|
public:
|
||||||
static void getOwnAvatar(QPixmap &avatar, const QString& defaultImage = AVATAR_DEFAULT_IMAGE);
|
static void getOwnAvatar(QPixmap &avatar, const QString& defaultImage = AVATAR_DEFAULT_IMAGE);
|
||||||
|
|
||||||
static void getAvatarFromSslId(const RsPeerId& sslId, QPixmap &avatar, const QString& defaultImage = AVATAR_DEFAULT_IMAGE);
|
static bool getAvatarFromSslId(const RsPeerId& sslId, QPixmap &avatar, const QString& defaultImage = AVATAR_DEFAULT_IMAGE);
|
||||||
static void getAvatarFromGpgId(const RsPgpId & gpgId, QPixmap &avatar, const QString& defaultImage = AVATAR_DEFAULT_IMAGE);
|
static bool getAvatarFromGpgId(const RsPgpId & gpgId, QPixmap &avatar, const QString& defaultImage = AVATAR_DEFAULT_IMAGE);
|
||||||
static void getAvatarFromGxsId(const RsGxsId & gxsId, QPixmap &avatar, const QString& defaultImage = AVATAR_DEFAULT_IMAGE);
|
static bool getAvatarFromGxsId(const RsGxsId & gxsId, QPixmap &avatar, const QString& defaultImage = AVATAR_DEFAULT_IMAGE);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -45,6 +45,9 @@ AvatarDialog::AvatarDialog(QWidget *parent) :
|
||||||
updateInterface();
|
updateInterface();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const int AvatarDialog::RS_AVATAR_DEFAULT_IMAGE_W = 64;
|
||||||
|
const int AvatarDialog::RS_AVATAR_DEFAULT_IMAGE_H = 64;
|
||||||
|
|
||||||
AvatarDialog::~AvatarDialog()
|
AvatarDialog::~AvatarDialog()
|
||||||
{
|
{
|
||||||
delete(ui);
|
delete(ui);
|
||||||
|
@ -52,7 +55,7 @@ AvatarDialog::~AvatarDialog()
|
||||||
|
|
||||||
void AvatarDialog::changeAvatar()
|
void AvatarDialog::changeAvatar()
|
||||||
{
|
{
|
||||||
QPixmap img = misc::getOpenThumbnailedPicture(this, tr("Load Avatar"), 128, 128);
|
QPixmap img = misc::getOpenThumbnailedPicture(this, tr("Load Avatar"), RS_AVATAR_DEFAULT_IMAGE_W,RS_AVATAR_DEFAULT_IMAGE_H);
|
||||||
|
|
||||||
if (img.isNull())
|
if (img.isNull())
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -35,6 +35,9 @@ class AvatarDialog : public QDialog
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static const int RS_AVATAR_DEFAULT_IMAGE_W ;
|
||||||
|
static const int RS_AVATAR_DEFAULT_IMAGE_H ;
|
||||||
|
|
||||||
AvatarDialog(QWidget *parent = 0);
|
AvatarDialog(QWidget *parent = 0);
|
||||||
~AvatarDialog();
|
~AvatarDialog();
|
||||||
|
|
||||||
|
|
|
@ -18,12 +18,15 @@
|
||||||
* *
|
* *
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include <QBuffer>
|
||||||
|
|
||||||
#include <rshare.h>
|
#include <rshare.h>
|
||||||
#include <retroshare/rsstatus.h>
|
#include <retroshare/rsstatus.h>
|
||||||
#include <retroshare/rspeers.h>
|
#include <retroshare/rspeers.h>
|
||||||
#include <retroshare/rsmsgs.h>
|
#include <retroshare/rsmsgs.h>
|
||||||
|
|
||||||
#include "gui/notifyqt.h"
|
#include "gui/notifyqt.h"
|
||||||
|
#include "util/misc.h"
|
||||||
#include "gui/common/AvatarDefs.h"
|
#include "gui/common/AvatarDefs.h"
|
||||||
#include "gui/common/AvatarDialog.h"
|
#include "gui/common/AvatarDialog.h"
|
||||||
|
|
||||||
|
@ -85,19 +88,33 @@ void AvatarWidget::mouseReleaseEvent(QMouseEvent */*event*/)
|
||||||
if (!mFlag.isOwnId) {
|
if (!mFlag.isOwnId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
QPixmap img = misc::getOpenThumbnailedPicture(this, tr("Choose avatar"), AvatarDialog::RS_AVATAR_DEFAULT_IMAGE_W,AvatarDialog::RS_AVATAR_DEFAULT_IMAGE_H);
|
||||||
|
|
||||||
AvatarDialog dialog(this);
|
if (img.isNull())
|
||||||
|
return;
|
||||||
|
|
||||||
QPixmap avatar;
|
setPixmap(img);
|
||||||
AvatarDefs::getOwnAvatar(avatar, "");
|
|
||||||
|
|
||||||
dialog.setAvatar(avatar);
|
QByteArray data;
|
||||||
if (dialog.exec() == QDialog::Accepted) {
|
QBuffer buffer(&data);
|
||||||
QByteArray newAvatar;
|
|
||||||
dialog.getAvatar(newAvatar);
|
|
||||||
|
|
||||||
rsMsgs->setOwnAvatarData((unsigned char *)(newAvatar.data()), newAvatar.size()) ; // last char 0 included.
|
buffer.open(QIODevice::WriteOnly);
|
||||||
}
|
img.save(&buffer, "PNG"); // writes image into a in PNG format
|
||||||
|
|
||||||
|
rsMsgs->setOwnAvatarData((unsigned char *)(data.data()), data.size()) ; // last char 0 included.
|
||||||
|
|
||||||
|
// AvatarDialog dialog(this);
|
||||||
|
//
|
||||||
|
// QPixmap avatar;
|
||||||
|
// AvatarDefs::getOwnAvatar(avatar, "");
|
||||||
|
//
|
||||||
|
// dialog.setAvatar(avatar);
|
||||||
|
// if (dialog.exec() == QDialog::Accepted) {
|
||||||
|
// QByteArray newAvatar;
|
||||||
|
// dialog.getAvatar(newAvatar);
|
||||||
|
//
|
||||||
|
// rsMsgs->setOwnAvatarData((unsigned char *)(newAvatar.data()), newAvatar.size()) ; // last char 0 included.
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarWidget::setFrameType(FrameType type)
|
void AvatarWidget::setFrameType(FrameType type)
|
||||||
|
|
|
@ -21,23 +21,40 @@
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QDesktopWidget>
|
#include <QDesktopWidget>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
#include <QDir>
|
||||||
#include <QGridLayout>
|
#include <QGridLayout>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QTabWidget>
|
#include <QTabWidget>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include "Emoticons.h"
|
#include "Emoticons.h"
|
||||||
#include "util/HandleRichText.h"
|
#include "util/HandleRichText.h"
|
||||||
|
#include "retroshare/rsinit.h"
|
||||||
|
|
||||||
|
#define ICONNAME "groupicon.png"
|
||||||
|
|
||||||
static QHash<QString, QPair<QVector<QString>, QHash<QString, QString> > > Smileys;
|
static QHash<QString, QPair<QVector<QString>, QHash<QString, QString> > > Smileys;
|
||||||
static QVector<QString> grpOrdered;
|
static QVector<QString> grpOrdered;
|
||||||
|
static QVector<QString > StickerGroups;
|
||||||
|
static QStringList filters;
|
||||||
|
static QHash<QString, QString> tooltipcache;
|
||||||
|
|
||||||
void Emoticons::load()
|
void Emoticons::load()
|
||||||
|
{
|
||||||
|
loadSmiley();
|
||||||
|
filters << "*.png" << "*.jpg" << "*.gif";
|
||||||
|
loadSticker(QString::fromStdString(RsAccounts::ConfigDirectory()) + "/stickers"); //under .retroshare, shared between users
|
||||||
|
loadSticker(QString::fromStdString(RsAccounts::AccountDirectory()) + "/stickers"); //under account, unique for user
|
||||||
|
loadSticker(QString::fromStdString(RsAccounts::systemDataDirectory()) + "/stickers"); //exe's folder, shipped with RS
|
||||||
|
}
|
||||||
|
|
||||||
|
void Emoticons::loadSmiley()
|
||||||
{
|
{
|
||||||
QString sm_AllLines;
|
QString sm_AllLines;
|
||||||
bool internalFiles = true;
|
bool internalFiles = true;
|
||||||
|
@ -267,3 +284,184 @@ void Emoticons::showSmileyWidget(QWidget *parent, QWidget *button, const char *s
|
||||||
smWidget->move(x, y) ;
|
smWidget->move(x, y) ;
|
||||||
smWidget->show() ;
|
smWidget->show() ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Emoticons::loadSticker(QString foldername)
|
||||||
|
{
|
||||||
|
QDir dir(foldername);
|
||||||
|
if(!dir.exists()) return;
|
||||||
|
|
||||||
|
//If it contains at a least one png then add it as a group
|
||||||
|
QStringList files = dir.entryList(filters, QDir::Files);
|
||||||
|
if(files.count() > 0)
|
||||||
|
StickerGroups.append(foldername);
|
||||||
|
|
||||||
|
//Check subfolders
|
||||||
|
QFileInfoList subfolders = dir.entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot);
|
||||||
|
for(int i = 0; i<subfolders.length(); i++)
|
||||||
|
loadSticker(subfolders[i].filePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Emoticons::showStickerWidget(QWidget *parent, QWidget *button, const char *slotAddMethod, bool above)
|
||||||
|
{
|
||||||
|
QWidget *smWidget = new QWidget(parent, Qt::Popup) ;
|
||||||
|
smWidget->setAttribute(Qt::WA_DeleteOnClose) ;
|
||||||
|
smWidget->setWindowTitle("Stickers") ;
|
||||||
|
|
||||||
|
if(StickerGroups.count() == 0) {
|
||||||
|
QMessageBox::warning(parent, "Stickers", "No stickers installed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bool bOnlyOneGroup = (StickerGroups.count() == 1);
|
||||||
|
|
||||||
|
QTabWidget *smTab = nullptr;
|
||||||
|
if (! bOnlyOneGroup)
|
||||||
|
{
|
||||||
|
smTab = new QTabWidget(smWidget);
|
||||||
|
QGridLayout *smGLayout = new QGridLayout(smWidget);
|
||||||
|
smGLayout->setContentsMargins(0,0,0,0);
|
||||||
|
smGLayout->addWidget(smTab);
|
||||||
|
}
|
||||||
|
|
||||||
|
const int buttonWidth = QFontMetricsF(smWidget->font()).height()*5;
|
||||||
|
const int buttonHeight = QFontMetricsF(smWidget->font()).height()*5;
|
||||||
|
int maxRowCount = 0;
|
||||||
|
int maxCountPerLine = 0;
|
||||||
|
|
||||||
|
QVectorIterator<QString> grp(StickerGroups);
|
||||||
|
while(grp.hasNext())
|
||||||
|
{
|
||||||
|
QDir groupDir = QDir(grp.next());
|
||||||
|
QString groupName = groupDir.dirName();
|
||||||
|
groupDir.setNameFilters(filters);
|
||||||
|
|
||||||
|
QWidget *tabGrpWidget = nullptr;
|
||||||
|
if (! bOnlyOneGroup)
|
||||||
|
{
|
||||||
|
//Lazy load tooltips for the current tab
|
||||||
|
QObject::connect(smTab, &QTabWidget::currentChanged, [=](int index){
|
||||||
|
QWidget* current = smTab->widget(index);
|
||||||
|
loadToolTips(current);
|
||||||
|
});
|
||||||
|
|
||||||
|
tabGrpWidget = new QWidget(smTab);
|
||||||
|
|
||||||
|
// (Cyril) Never use an absolute size. It needs to be scaled to the actual font size on the screen.
|
||||||
|
//
|
||||||
|
QFontMetricsF fm(parent->font()) ;
|
||||||
|
smTab->setIconSize(QSize(28*fm.height()/14.0,28*fm.height()/14.0));
|
||||||
|
smTab->setMinimumWidth(400);
|
||||||
|
smTab->setTabPosition(QTabWidget::South);
|
||||||
|
smTab->setStyleSheet("QTabBar::tab { height: 44px; width: 44px; }");
|
||||||
|
|
||||||
|
int index;
|
||||||
|
if (groupDir.exists(ICONNAME)) //use groupicon.png if exists, else the first png as a group icon
|
||||||
|
index = smTab->addTab( tabGrpWidget, QIcon(groupDir.absoluteFilePath(ICONNAME)), "");
|
||||||
|
else
|
||||||
|
index = smTab->addTab( tabGrpWidget, QIcon(groupDir.entryInfoList(QDir::Files)[0].canonicalFilePath()), "");
|
||||||
|
smTab->setTabToolTip(index, groupName);
|
||||||
|
} else {
|
||||||
|
tabGrpWidget = smWidget;
|
||||||
|
}
|
||||||
|
|
||||||
|
QGridLayout *tabGLayout = new QGridLayout(tabGrpWidget);
|
||||||
|
tabGLayout->setContentsMargins(0,0,0,0);
|
||||||
|
tabGLayout->setSpacing(0);
|
||||||
|
|
||||||
|
QFileInfoList group = groupDir.entryInfoList(QDir::Files, QDir::Name);
|
||||||
|
int rowCount = (int)sqrt((double)group.size());
|
||||||
|
int countPerLine = (group.size()/rowCount) + ((group.size() % rowCount) ? 1 : 0);
|
||||||
|
maxRowCount = qMax(maxRowCount, rowCount);
|
||||||
|
maxCountPerLine = qMax(maxCountPerLine, countPerLine);
|
||||||
|
|
||||||
|
int lin = 0;
|
||||||
|
int col = 0;
|
||||||
|
for(int i = 0; i < group.length(); ++i)
|
||||||
|
{
|
||||||
|
QFileInfo fi = group[i];
|
||||||
|
if(fi.fileName().compare(ICONNAME, Qt::CaseInsensitive) == 0)
|
||||||
|
continue;
|
||||||
|
QPushButton *button = new QPushButton("", tabGrpWidget);
|
||||||
|
button->setIconSize(QSize(buttonWidth, buttonHeight));
|
||||||
|
button->setFixedSize(QSize(buttonWidth, buttonHeight));
|
||||||
|
button->setIcon(QPixmap(fi.absoluteFilePath()));
|
||||||
|
button->setToolTip(fi.fileName());
|
||||||
|
button->setStatusTip(fi.absoluteFilePath());
|
||||||
|
button->setStyleSheet("QPushButton:hover {border: 3px solid #0099cc; border-radius: 3px;}");
|
||||||
|
button->setFlat(true);
|
||||||
|
tabGLayout->addWidget(button,col,lin);
|
||||||
|
++lin;
|
||||||
|
if(lin >= countPerLine)
|
||||||
|
{
|
||||||
|
lin = 0;
|
||||||
|
++col;
|
||||||
|
}
|
||||||
|
QObject::connect(button, SIGNAL(clicked()), parent, slotAddMethod);
|
||||||
|
QObject::connect(button, SIGNAL(clicked()), smWidget, SLOT(close()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//Load tooltips for the first page
|
||||||
|
QWidget * firstpage;
|
||||||
|
if(bOnlyOneGroup) {
|
||||||
|
firstpage = smWidget;
|
||||||
|
} else {
|
||||||
|
firstpage = smTab->currentWidget();
|
||||||
|
}
|
||||||
|
loadToolTips(firstpage);
|
||||||
|
|
||||||
|
//Get left up pos of button
|
||||||
|
QPoint butTopLeft = button->mapToGlobal(QPoint(0,0));
|
||||||
|
//Get widget's size
|
||||||
|
QSize sizeWidget = smWidget->sizeHint();
|
||||||
|
//Get screen's size
|
||||||
|
QSize sizeScreen = QApplication::desktop()->size();
|
||||||
|
|
||||||
|
//Calculate left distance to screen start
|
||||||
|
int distToScreenLeft = butTopLeft.x();
|
||||||
|
//Calculate right distance to screen end
|
||||||
|
int distToRightScreen = sizeScreen.width() - (butTopLeft.x() + button->width());
|
||||||
|
|
||||||
|
//Calculate left position
|
||||||
|
int x;
|
||||||
|
if (distToScreenLeft >= distToRightScreen) //More distance in left than right in screen
|
||||||
|
x = butTopLeft.x() - sizeWidget.width(); //Place widget on left of button
|
||||||
|
else
|
||||||
|
x = butTopLeft.x() + button->width(); //Place widget on right of button
|
||||||
|
|
||||||
|
//Calculate top position
|
||||||
|
int y;
|
||||||
|
if (above) //Widget must be above the button
|
||||||
|
y = butTopLeft.y() + button->height() - sizeWidget.height();
|
||||||
|
else
|
||||||
|
y = butTopLeft.y() + button->height()/2 - sizeWidget.height()/2; //Centered on button height
|
||||||
|
|
||||||
|
if (y + sizeWidget.height() > sizeScreen.height()) //Widget will be too low
|
||||||
|
y = sizeScreen.height() - sizeWidget.height(); //Place widget bottom at screen bottom
|
||||||
|
|
||||||
|
if (y < 0) //Widget will be too high
|
||||||
|
y = 0; //Place widget top at screen top
|
||||||
|
|
||||||
|
smWidget->move(x, y);
|
||||||
|
smWidget->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Emoticons::loadToolTips(QWidget *container)
|
||||||
|
{
|
||||||
|
QList<QPushButton *> children = container->findChildren<QPushButton *>();
|
||||||
|
for(int i = 0; i < children.length(); ++i) {
|
||||||
|
if(!children[i]->toolTip().contains('<')) {
|
||||||
|
if(tooltipcache.contains(children[i]->statusTip())) {
|
||||||
|
children[i]->setToolTip(tooltipcache[children[i]->statusTip()]);
|
||||||
|
} else {
|
||||||
|
QString tooltip;
|
||||||
|
if(RsHtml::makeEmbeddedImage(children[i]->statusTip(), tooltip, 300*300)) {
|
||||||
|
tooltipcache.insert(children[i]->statusTip(), tooltip);
|
||||||
|
children[i]->setToolTip(tooltip);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -28,10 +28,14 @@ class Emoticons
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void load();
|
static void load();
|
||||||
|
static void loadSmiley();
|
||||||
|
static void loadSticker(QString foldername);
|
||||||
|
|
||||||
static void showSmileyWidget(QWidget *parent, QWidget *button, const char *slotAddMethod, bool above);
|
static void showSmileyWidget(QWidget *parent, QWidget *button, const char *slotAddMethod, bool above);
|
||||||
|
static void showStickerWidget(QWidget *parent, QWidget *button, const char *slotAddMethod, bool above);
|
||||||
|
|
||||||
// static void formatText(QString &text);
|
private:
|
||||||
|
static void loadToolTips(QWidget *container);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -126,8 +126,7 @@ FriendList::FriendList(QWidget *parent) :
|
||||||
#ifdef RS_DIRECT_CHAT
|
#ifdef RS_DIRECT_CHAT
|
||||||
connect(ui->peerTreeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(chatfriend(QTreeWidgetItem *)));
|
connect(ui->peerTreeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(chatfriend(QTreeWidgetItem *)));
|
||||||
#else
|
#else
|
||||||
connect( ui->peerTreeWidget, SIGNAL(itemClicked(QTreeWidgetItem *, int)),
|
connect( ui->peerTreeWidget, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, SLOT(expandItem(QTreeWidgetItem *)) );
|
||||||
this, SLOT(expandItem(QTreeWidgetItem *)) );
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
connect(NotifyQt::getInstance(), SIGNAL(groupsChanged(int)), this, SLOT(groupsChanged()));
|
connect(NotifyQt::getInstance(), SIGNAL(groupsChanged(int)), this, SLOT(groupsChanged()));
|
||||||
|
@ -553,275 +552,6 @@ static void getNameWidget(QTreeWidget *treeWidget, QTreeWidgetItem *item, Elided
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PgpItemInfo
|
|
||||||
{
|
|
||||||
PgpItemInfo() : gpg_connected(false),gpg_online(false),gpg_hasPrivateChat(false),bestPeerState(0),bestRSState(0) {}
|
|
||||||
|
|
||||||
bool gpg_connected ;
|
|
||||||
bool gpg_online ;
|
|
||||||
bool gpg_hasPrivateChat ;
|
|
||||||
int bestPeerState ;
|
|
||||||
unsigned int bestRSState ;
|
|
||||||
QString bestCustomStateString;// for gpg item
|
|
||||||
std::list<RsPeerId> sslContacts;
|
|
||||||
QDateTime bestLastContact;
|
|
||||||
QString bestIP;
|
|
||||||
QPixmap bestAvatar;
|
|
||||||
};
|
|
||||||
|
|
||||||
void FriendList::manageProfileLocations(QTreeWidgetItem *gpgItem,const RsPgpId& gpg_id,PgpItemInfo& info)
|
|
||||||
{
|
|
||||||
std::vector<RsPeerId> privateChatIds;
|
|
||||||
ChatUserNotify::getPeersWithWaitingChat(privateChatIds);
|
|
||||||
|
|
||||||
int columnCount = ui->peerTreeWidget->columnCount();
|
|
||||||
|
|
||||||
for (auto sslIt ( info.sslContacts.begin()); sslIt != info.sslContacts.end(); ++sslIt)
|
|
||||||
{
|
|
||||||
QTreeWidgetItem *sslItem = NULL;
|
|
||||||
RsPeerId sslId = *sslIt;
|
|
||||||
|
|
||||||
// find the corresponding sslItem child item of the gpg item
|
|
||||||
bool newChild = true;
|
|
||||||
int childCount = gpgItem->childCount();
|
|
||||||
for (int childIndex = 0; childIndex < childCount; ++childIndex) {
|
|
||||||
// we assume, that only ssl items are child of the gpg item, so we don't need to test the type
|
|
||||||
if (getRsId(gpgItem->child(childIndex)) == sslId.toStdString()) {
|
|
||||||
sslItem = gpgItem->child(childIndex);
|
|
||||||
newChild = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RsPeerDetails sslDetail;
|
|
||||||
if (!rsPeers->getPeerDetails(sslId, sslDetail) || !rsPeers->isFriend(sslId)) {
|
|
||||||
#ifdef FRIENDS_DEBUG
|
|
||||||
std::cerr << "Removing widget from the view : id : " << sslId << std::endl;
|
|
||||||
#endif
|
|
||||||
// child has disappeared, remove it from the gpg_item
|
|
||||||
if (sslItem) {
|
|
||||||
gpgItem->removeChild(sslItem);
|
|
||||||
delete(sslItem);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newChild) {
|
|
||||||
sslItem = new RSTreeWidgetItem(mCompareRole, TYPE_SSL); //set type to 1 for custom popup menu
|
|
||||||
|
|
||||||
#ifdef FRIENDS_DEBUG
|
|
||||||
std::cerr << "FriendList::insertPeers() inserting sslItem." << std::endl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Add ssl child to the list. Add here, because for setHidden the item must be added */
|
|
||||||
gpgItem->addChild(sslItem);
|
|
||||||
|
|
||||||
/* Sort data */
|
|
||||||
for (int i = 0; i < columnCount; ++i) {
|
|
||||||
sslItem->setData(i, ROLE_SORT_GROUP, 2);
|
|
||||||
sslItem->setData(i, ROLE_SORT_STANDARD_GROUP, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* not displayed, used to find back the item */
|
|
||||||
QString strID = QString::fromStdString(sslDetail.id.toStdString());
|
|
||||||
sslItem->setData(COLUMN_DATA, ROLE_ID, strID);
|
|
||||||
sslItem->setText(COLUMN_ID, strID);
|
|
||||||
sslItem->setData(COLUMN_ID, ROLE_SORT_NAME, strID);
|
|
||||||
sslItem->setData(COLUMN_ID, ROLE_FILTER, strID);
|
|
||||||
|
|
||||||
/* Custom state string */
|
|
||||||
QString customStateString;
|
|
||||||
if (sslDetail.state & RS_PEER_STATE_CONNECTED) {
|
|
||||||
customStateString = QString::fromUtf8(rsMsgs->getCustomStateString(sslDetail.id).c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
QPixmap sslAvatar;
|
|
||||||
AvatarDefs::getAvatarFromSslId(RsPeerId(sslDetail.id.toStdString()), sslAvatar);
|
|
||||||
|
|
||||||
/* last contact */
|
|
||||||
QDateTime sslLastContact = QDateTime::fromTime_t(sslDetail.lastConnect);
|
|
||||||
sslItem->setData(COLUMN_LAST_CONTACT, Qt::DisplayRole, QVariant(sslLastContact));
|
|
||||||
sslItem->setData(COLUMN_LAST_CONTACT, ROLE_SORT_NAME, QVariant(sslLastContact));
|
|
||||||
if (sslLastContact > info.bestLastContact) {
|
|
||||||
info.bestLastContact = sslLastContact;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* IP */
|
|
||||||
QString sslIP = (sslDetail.state & RS_PEER_STATE_CONNECTED) ? StatusDefs::connectStateIpString(sslDetail) : QString("---");
|
|
||||||
sslItem->setText(COLUMN_IP, sslIP);
|
|
||||||
sslItem->setData(COLUMN_IP, ROLE_SORT_NAME, sslIP);
|
|
||||||
|
|
||||||
/* change color and icon */
|
|
||||||
QPixmap sslOverlayIcon;
|
|
||||||
QFont sslFont;
|
|
||||||
QColor sslColor;
|
|
||||||
int peerState = 0;
|
|
||||||
QString connectStateString;
|
|
||||||
if (sslDetail.state & RS_PEER_STATE_CONNECTED)
|
|
||||||
{
|
|
||||||
// get the status info for this ssl id
|
|
||||||
int rsState = 0;
|
|
||||||
|
|
||||||
StatusInfo status_info ;
|
|
||||||
rsStatus->getStatus(sslDetail.id,status_info);
|
|
||||||
|
|
||||||
rsState = status_info.status;
|
|
||||||
switch (rsState) {
|
|
||||||
case RS_STATUS_INACTIVE:
|
|
||||||
peerState = PEER_STATE_INACTIVE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RS_STATUS_ONLINE:
|
|
||||||
peerState = PEER_STATE_ONLINE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RS_STATUS_AWAY:
|
|
||||||
peerState = PEER_STATE_AWAY;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RS_STATUS_BUSY:
|
|
||||||
peerState = PEER_STATE_BUSY;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* find the best ssl contact for the gpg item */
|
|
||||||
if (info.bestPeerState == 0 || peerState < info.bestPeerState) {
|
|
||||||
/* first ssl contact or higher state */
|
|
||||||
info.bestPeerState = peerState;
|
|
||||||
info.bestRSState = rsState;
|
|
||||||
info.bestCustomStateString = customStateString;
|
|
||||||
info.bestIP = sslIP;
|
|
||||||
if (!sslAvatar.isNull()) {
|
|
||||||
info.bestAvatar = sslAvatar;
|
|
||||||
}
|
|
||||||
} else if (peerState == info.bestPeerState) {
|
|
||||||
/* equal state */
|
|
||||||
if (info.bestCustomStateString.isEmpty() && !customStateString.isEmpty()) {
|
|
||||||
/* when customStateString is shown in name item, use sslId with customStateString.
|
|
||||||
second with a custom state string ... use second */
|
|
||||||
info.bestPeerState = peerState;
|
|
||||||
info.bestRSState = rsState;
|
|
||||||
info.bestCustomStateString = customStateString;
|
|
||||||
}
|
|
||||||
if (info.bestAvatar.isNull() && !sslAvatar.isNull()) {
|
|
||||||
/* Use available avatar */
|
|
||||||
info.bestAvatar = sslAvatar;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sslItem->setHidden(false);
|
|
||||||
info.gpg_connected = true;
|
|
||||||
|
|
||||||
sslOverlayIcon = QPixmap(StatusDefs::imageStatus(info.bestRSState));
|
|
||||||
|
|
||||||
connectStateString = StatusDefs::name(rsState);
|
|
||||||
|
|
||||||
if (rsState == 0) {
|
|
||||||
sslFont.setBold(true);
|
|
||||||
sslColor = mTextColorStatus[RS_STATUS_ONLINE];
|
|
||||||
} else {
|
|
||||||
sslFont = StatusDefs::font(rsState);
|
|
||||||
sslColor = mTextColorStatus[rsState];
|
|
||||||
}
|
|
||||||
} else if (sslDetail.state & RS_PEER_STATE_ONLINE) {
|
|
||||||
sslItem->setHidden(mHideUnconnected);
|
|
||||||
info.gpg_online = true;
|
|
||||||
peerState = PEER_STATE_AVAILABLE;
|
|
||||||
|
|
||||||
if (sslDetail.connectState) {
|
|
||||||
sslOverlayIcon = QPixmap(":/images/connect_creating.png");
|
|
||||||
} else {
|
|
||||||
sslOverlayIcon = QPixmap(StatusDefs::imageStatus(RS_STATUS_ONLINE));
|
|
||||||
}
|
|
||||||
|
|
||||||
connectStateString = StatusDefs::name(RS_STATUS_ONLINE);
|
|
||||||
|
|
||||||
sslFont.setBold(true);
|
|
||||||
sslColor = mTextColorStatus[RS_STATUS_ONLINE];
|
|
||||||
} else {
|
|
||||||
peerState = PEER_STATE_OFFLINE;
|
|
||||||
sslItem->setHidden(mHideUnconnected);
|
|
||||||
if (sslDetail.connectState) {
|
|
||||||
sslOverlayIcon = QPixmap(":/images/connect_creating.png");
|
|
||||||
} else {
|
|
||||||
sslOverlayIcon = QPixmap(StatusDefs::imageStatus(RS_STATUS_OFFLINE));
|
|
||||||
}
|
|
||||||
|
|
||||||
connectStateString = StatusDefs::connectStateWithoutTransportTypeString(sslDetail);
|
|
||||||
|
|
||||||
sslFont.setBold(false);
|
|
||||||
sslColor = mTextColorStatus[RS_STATUS_OFFLINE];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Location */
|
|
||||||
QString sslName = QString::fromUtf8(sslDetail.location.c_str());
|
|
||||||
QString sslText;
|
|
||||||
|
|
||||||
if (mShowState) {
|
|
||||||
if (!connectStateString.isEmpty()) {
|
|
||||||
sslText = connectStateString;
|
|
||||||
if (!customStateString.isEmpty()) {
|
|
||||||
sslText += " [" + customStateString + "]";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!customStateString.isEmpty()) {
|
|
||||||
sslText = customStateString;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sslItem->setToolTip(COLUMN_NAME, "");
|
|
||||||
} else {
|
|
||||||
if (!customStateString.isEmpty()) {
|
|
||||||
sslText = customStateString;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Show the state as tooltip */
|
|
||||||
sslItem->setToolTip(COLUMN_NAME, connectStateString);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create or get ssl label */
|
|
||||||
ElidedLabel *sslNameLabel = NULL;
|
|
||||||
ElidedLabel *sslTextLabel = NULL;
|
|
||||||
|
|
||||||
getNameWidget(ui->peerTreeWidget, sslItem, sslNameLabel, sslTextLabel);
|
|
||||||
|
|
||||||
if (sslNameLabel) {
|
|
||||||
sslNameLabel->setText(sslName);
|
|
||||||
sslNameLabel->setFont(sslFont);
|
|
||||||
|
|
||||||
QPalette palette = sslNameLabel->palette();
|
|
||||||
palette.setColor(sslNameLabel->foregroundRole(), sslColor);
|
|
||||||
|
|
||||||
sslNameLabel->setPalette(palette);
|
|
||||||
}
|
|
||||||
if (sslTextLabel) {
|
|
||||||
sslTextLabel->setText(sslText);
|
|
||||||
sslTextLabel->setVisible(!sslText.isEmpty());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter
|
|
||||||
sslItem->setData(COLUMN_NAME, ROLE_FILTER, sslName);
|
|
||||||
|
|
||||||
if (std::find(privateChatIds.begin(), privateChatIds.end(), sslDetail.id) != privateChatIds.end()) {
|
|
||||||
// private chat is available
|
|
||||||
sslOverlayIcon = QPixmap(":/images/chat.png");
|
|
||||||
info.gpg_hasPrivateChat = true;
|
|
||||||
}
|
|
||||||
sslItem->setIcon(COLUMN_NAME, createAvatar(sslAvatar, sslOverlayIcon));
|
|
||||||
|
|
||||||
/* Sort data */
|
|
||||||
sslItem->setData(COLUMN_NAME, ROLE_SORT_NAME, sslName);
|
|
||||||
|
|
||||||
for (int i = 0; i < columnCount; ++i) {
|
|
||||||
sslItem->setData(i, ROLE_SORT_STATE, peerState);
|
|
||||||
|
|
||||||
sslItem->setTextColor(i, sslColor);
|
|
||||||
sslItem->setFont(i, sslFont);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the list of peers from the RsIface.
|
* Get the list of peers from the RsIface.
|
||||||
* Adds all friend gpg ids, with their nodes as children to the peerTreeWidget.
|
* Adds all friend gpg ids, with their nodes as children to the peerTreeWidget.
|
||||||
|
@ -839,8 +569,8 @@ void FriendList::insertPeers()
|
||||||
|
|
||||||
int columnCount = ui->peerTreeWidget->columnCount();
|
int columnCount = ui->peerTreeWidget->columnCount();
|
||||||
|
|
||||||
//std::list<StatusInfo> statusInfo;
|
std::list<StatusInfo> statusInfo;
|
||||||
//rsStatus->getStatusList(statusInfo);
|
rsStatus->getStatusList(statusInfo);
|
||||||
|
|
||||||
if (!rsPeers) {
|
if (!rsPeers) {
|
||||||
/* not ready yet! */
|
/* not ready yet! */
|
||||||
|
@ -849,6 +579,9 @@ void FriendList::insertPeers()
|
||||||
}
|
}
|
||||||
|
|
||||||
// get peers with waiting incoming chats
|
// get peers with waiting incoming chats
|
||||||
|
std::vector<RsPeerId> privateChatIds;
|
||||||
|
ChatUserNotify::getPeersWithWaitingChat(privateChatIds);
|
||||||
|
|
||||||
// get existing groups
|
// get existing groups
|
||||||
std::list<RsGroupInfo> groupInfoList;
|
std::list<RsGroupInfo> groupInfoList;
|
||||||
std::list<RsGroupInfo>::iterator groupIt;
|
std::list<RsGroupInfo>::iterator groupIt;
|
||||||
|
@ -858,8 +591,7 @@ void FriendList::insertPeers()
|
||||||
std::list<RsPgpId>::iterator gpgIt;
|
std::list<RsPgpId>::iterator gpgIt;
|
||||||
rsPeers->getGPGAcceptedList(gpgFriends);
|
rsPeers->getGPGAcceptedList(gpgFriends);
|
||||||
|
|
||||||
// add own gpg id, if we have more than on node (ssl client)
|
//add own gpg id, if we have more than on node (ssl client)
|
||||||
|
|
||||||
std::list<RsPeerId> ownSslContacts;
|
std::list<RsPeerId> ownSslContacts;
|
||||||
RsPgpId ownId = rsPeers->getGPGOwnId();
|
RsPgpId ownId = rsPeers->getGPGOwnId();
|
||||||
rsPeers->getAssociatedSSLIds(ownId, ownSslContacts);
|
rsPeers->getAssociatedSSLIds(ownId, ownSslContacts);
|
||||||
|
@ -867,24 +599,6 @@ void FriendList::insertPeers()
|
||||||
gpgFriends.push_back(ownId);
|
gpgFriends.push_back(ownId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Also add SSL peers which PGP key is not available yet.
|
|
||||||
|
|
||||||
std::list<RsPeerId> ssl_friends ;
|
|
||||||
rsPeers->getFriendList(ssl_friends);
|
|
||||||
std::map<RsPgpId,std::list<RsPeerDetails> > pgp_friends_without_validation;
|
|
||||||
|
|
||||||
std::cerr << "List of accepted ssl peers: " << std::endl;
|
|
||||||
for(auto it(ssl_friends.begin());it!=ssl_friends.end();++it)
|
|
||||||
{
|
|
||||||
RsPeerDetails pd;
|
|
||||||
if(rsPeers->getPeerDetails(*it,pd) && pd.skip_signature_validation)
|
|
||||||
{
|
|
||||||
std::cerr << " adding " << *it << " - " << pd.gpg_id << std::endl;
|
|
||||||
gpgFriends.push_back(pd.gpg_id);
|
|
||||||
pgp_friends_without_validation[pd.gpg_id].push_back(pd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get a link to the table */
|
/* get a link to the table */
|
||||||
QTreeWidget *peerTreeWidget = ui->peerTreeWidget;
|
QTreeWidget *peerTreeWidget = ui->peerTreeWidget;
|
||||||
|
|
||||||
|
@ -1086,8 +800,7 @@ void FriendList::insertPeers()
|
||||||
}
|
}
|
||||||
|
|
||||||
RsPeerDetails detail;
|
RsPeerDetails detail;
|
||||||
if (pgp_friends_without_validation.find(gpgId) == pgp_friends_without_validation.end() &&
|
if ((!rsPeers->getGPGDetails(gpgId, detail) || !detail.accept_connection) && detail.gpg_id != ownId) {
|
||||||
(!rsPeers->getGPGDetails(gpgId, detail) || !detail.accept_connection) && detail.gpg_id != ownId) {
|
|
||||||
// don't accept anymore connection, remove from the view
|
// don't accept anymore connection, remove from the view
|
||||||
if (gpgItem) {
|
if (gpgItem) {
|
||||||
if (groupItem) {
|
if (groupItem) {
|
||||||
|
@ -1096,13 +809,10 @@ void FriendList::insertPeers()
|
||||||
delete (peerTreeWidget->takeTopLevelItem(peerTreeWidget->indexOfTopLevelItem(gpgItem)));
|
delete (peerTreeWidget->takeTopLevelItem(peerTreeWidget->indexOfTopLevelItem(gpgItem)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We still want to add the item if it is unvalidated, in which case getGPGDetails returns false.
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gpgItem == NULL)
|
if (gpgItem == NULL) {
|
||||||
{
|
|
||||||
// create gpg item and add it to tree
|
// create gpg item and add it to tree
|
||||||
gpgItem = new RSTreeWidgetItem(mCompareRole, TYPE_GPG); //set type to 0 for custom popup menu
|
gpgItem = new RSTreeWidgetItem(mCompareRole, TYPE_GPG); //set type to 0 for custom popup menu
|
||||||
|
|
||||||
|
@ -1117,7 +827,7 @@ void FriendList::insertPeers()
|
||||||
gpgItem->setTextAlignment(COLUMN_NAME, Qt::AlignLeft | Qt::AlignVCenter);
|
gpgItem->setTextAlignment(COLUMN_NAME, Qt::AlignLeft | Qt::AlignVCenter);
|
||||||
|
|
||||||
/* not displayed, used to find back the item */
|
/* not displayed, used to find back the item */
|
||||||
QString strID = QString::fromStdString(gpgId.toStdString());
|
QString strID = QString::fromStdString(detail.gpg_id.toStdString());
|
||||||
gpgItem->setData(COLUMN_DATA, ROLE_ID, strID);
|
gpgItem->setData(COLUMN_DATA, ROLE_ID, strID);
|
||||||
gpgItem->setText(COLUMN_ID, strID);
|
gpgItem->setText(COLUMN_ID, strID);
|
||||||
gpgItem->setData(COLUMN_ID, ROLE_SORT_NAME, strID);
|
gpgItem->setData(COLUMN_ID, ROLE_SORT_NAME, strID);
|
||||||
|
@ -1147,22 +857,263 @@ void FriendList::insertPeers()
|
||||||
}
|
}
|
||||||
|
|
||||||
// update the childs (ssl certs)
|
// update the childs (ssl certs)
|
||||||
|
bool gpg_connected = false;
|
||||||
|
bool gpg_online = false;
|
||||||
|
bool gpg_hasPrivateChat = false;
|
||||||
|
int bestPeerState = 0; // for gpg item
|
||||||
|
unsigned int bestRSState = 0; // for gpg item
|
||||||
|
QString bestCustomStateString;// for gpg item
|
||||||
|
std::list<RsPeerId> sslContacts;
|
||||||
|
QDateTime bestLastContact;
|
||||||
|
QString bestIP;
|
||||||
|
QPixmap bestAvatar;
|
||||||
|
|
||||||
PgpItemInfo info;
|
rsPeers->getAssociatedSSLIds(detail.gpg_id, sslContacts);
|
||||||
|
for (std::list<RsPeerId>::iterator sslIt = sslContacts.begin(); sslIt != sslContacts.end(); ++sslIt) {
|
||||||
|
QTreeWidgetItem *sslItem = NULL;
|
||||||
|
RsPeerId sslId = *sslIt;
|
||||||
|
|
||||||
auto itt = pgp_friends_without_validation.find(gpgId);
|
// find the corresponding sslItem child item of the gpg item
|
||||||
if(itt != pgp_friends_without_validation.end())
|
bool newChild = true;
|
||||||
{
|
childCount = gpgItem->childCount();
|
||||||
info.sslContacts.clear();
|
for (int childIndex = 0; childIndex < childCount; ++childIndex) {
|
||||||
for(auto itt2(itt->second.begin());itt2!=itt->second.end();++itt2)
|
// we assume, that only ssl items are child of the gpg item, so we don't need to test the type
|
||||||
info.sslContacts.push_back(itt2->id);
|
if (getRsId(gpgItem->child(childIndex)) == sslId.toStdString()) {
|
||||||
|
sslItem = gpgItem->child(childIndex);
|
||||||
detail.name = gpgId.toStdString() + tr(" (Unverified yet)").toStdString();
|
newChild = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
rsPeers->getAssociatedSSLIds(gpgId, info.sslContacts);
|
|
||||||
|
|
||||||
manageProfileLocations(gpgItem,gpgId,info);
|
RsPeerDetails sslDetail;
|
||||||
|
if (!rsPeers->getPeerDetails(sslId, sslDetail) || !rsPeers->isFriend(sslId)) {
|
||||||
|
#ifdef FRIENDS_DEBUG
|
||||||
|
std::cerr << "Removing widget from the view : id : " << sslId << std::endl;
|
||||||
|
#endif
|
||||||
|
// child has disappeared, remove it from the gpg_item
|
||||||
|
if (sslItem) {
|
||||||
|
gpgItem->removeChild(sslItem);
|
||||||
|
delete(sslItem);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newChild) {
|
||||||
|
sslItem = new RSTreeWidgetItem(mCompareRole, TYPE_SSL); //set type to 1 for custom popup menu
|
||||||
|
|
||||||
|
#ifdef FRIENDS_DEBUG
|
||||||
|
std::cerr << "FriendList::insertPeers() inserting sslItem." << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Add ssl child to the list. Add here, because for setHidden the item must be added */
|
||||||
|
gpgItem->addChild(sslItem);
|
||||||
|
|
||||||
|
/* Sort data */
|
||||||
|
for (int i = 0; i < columnCount; ++i) {
|
||||||
|
sslItem->setData(i, ROLE_SORT_GROUP, 2);
|
||||||
|
sslItem->setData(i, ROLE_SORT_STANDARD_GROUP, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not displayed, used to find back the item */
|
||||||
|
QString strID = QString::fromStdString(sslDetail.id.toStdString());
|
||||||
|
sslItem->setData(COLUMN_DATA, ROLE_ID, strID);
|
||||||
|
sslItem->setText(COLUMN_ID, strID);
|
||||||
|
sslItem->setData(COLUMN_ID, ROLE_SORT_NAME, strID);
|
||||||
|
sslItem->setData(COLUMN_ID, ROLE_FILTER, strID);
|
||||||
|
|
||||||
|
/* Custom state string */
|
||||||
|
QString customStateString;
|
||||||
|
if (sslDetail.state & RS_PEER_STATE_CONNECTED) {
|
||||||
|
customStateString = QString::fromUtf8(rsMsgs->getCustomStateString(sslDetail.id).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
QPixmap sslAvatar;
|
||||||
|
AvatarDefs::getAvatarFromSslId(RsPeerId(sslDetail.id.toStdString()), sslAvatar);
|
||||||
|
|
||||||
|
/* last contact */
|
||||||
|
QDateTime sslLastContact = QDateTime::fromTime_t(sslDetail.lastConnect);
|
||||||
|
sslItem->setData(COLUMN_LAST_CONTACT, Qt::DisplayRole, QVariant(sslLastContact));
|
||||||
|
sslItem->setData(COLUMN_LAST_CONTACT, ROLE_SORT_NAME, QVariant(sslLastContact));
|
||||||
|
if (sslLastContact > bestLastContact) {
|
||||||
|
bestLastContact = sslLastContact;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* IP */
|
||||||
|
QString sslIP = (sslDetail.state & RS_PEER_STATE_CONNECTED) ? StatusDefs::connectStateIpString(sslDetail) : QString("---");
|
||||||
|
sslItem->setText(COLUMN_IP, sslIP);
|
||||||
|
sslItem->setData(COLUMN_IP, ROLE_SORT_NAME, sslIP);
|
||||||
|
|
||||||
|
/* change color and icon */
|
||||||
|
QPixmap sslOverlayIcon;
|
||||||
|
QFont sslFont;
|
||||||
|
QColor sslColor;
|
||||||
|
int peerState = 0;
|
||||||
|
QString connectStateString;
|
||||||
|
if (sslDetail.state & RS_PEER_STATE_CONNECTED) {
|
||||||
|
// get the status info for this ssl id
|
||||||
|
int rsState = 0;
|
||||||
|
std::list<StatusInfo>::iterator it;
|
||||||
|
for (it = statusInfo.begin(); it != statusInfo.end(); ++it) {
|
||||||
|
if (it->id == sslId) {
|
||||||
|
rsState = it->status;
|
||||||
|
switch (rsState) {
|
||||||
|
case RS_STATUS_INACTIVE:
|
||||||
|
peerState = PEER_STATE_INACTIVE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RS_STATUS_ONLINE:
|
||||||
|
peerState = PEER_STATE_ONLINE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RS_STATUS_AWAY:
|
||||||
|
peerState = PEER_STATE_AWAY;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RS_STATUS_BUSY:
|
||||||
|
peerState = PEER_STATE_BUSY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find the best ssl contact for the gpg item */
|
||||||
|
if (bestPeerState == 0 || peerState < bestPeerState) {
|
||||||
|
/* first ssl contact or higher state */
|
||||||
|
bestPeerState = peerState;
|
||||||
|
bestRSState = rsState;
|
||||||
|
bestCustomStateString = customStateString;
|
||||||
|
bestIP = sslIP;
|
||||||
|
if (!sslAvatar.isNull()) {
|
||||||
|
bestAvatar = sslAvatar;
|
||||||
|
}
|
||||||
|
} else if (peerState == bestPeerState) {
|
||||||
|
/* equal state */
|
||||||
|
if (bestCustomStateString.isEmpty() && !customStateString.isEmpty()) {
|
||||||
|
/* when customStateString is shown in name item, use sslId with customStateString.
|
||||||
|
second with a custom state string ... use second */
|
||||||
|
bestPeerState = peerState;
|
||||||
|
bestRSState = rsState;
|
||||||
|
bestCustomStateString = customStateString;
|
||||||
|
}
|
||||||
|
if (bestAvatar.isNull() && !sslAvatar.isNull()) {
|
||||||
|
/* Use available avatar */
|
||||||
|
bestAvatar = sslAvatar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sslItem->setHidden(false);
|
||||||
|
gpg_connected = true;
|
||||||
|
|
||||||
|
sslOverlayIcon = QPixmap(StatusDefs::imageStatus(bestRSState));
|
||||||
|
|
||||||
|
connectStateString = StatusDefs::name(rsState);
|
||||||
|
|
||||||
|
if (rsState == 0) {
|
||||||
|
sslFont.setBold(true);
|
||||||
|
sslColor = mTextColorStatus[RS_STATUS_ONLINE];
|
||||||
|
|
||||||
|
} else {
|
||||||
|
sslFont = StatusDefs::font(rsState);
|
||||||
|
sslColor = mTextColorStatus[rsState];
|
||||||
|
}
|
||||||
|
} else if (sslDetail.state & RS_PEER_STATE_ONLINE) {
|
||||||
|
sslItem->setHidden(mHideUnconnected);
|
||||||
|
gpg_online = true;
|
||||||
|
peerState = PEER_STATE_AVAILABLE;
|
||||||
|
|
||||||
|
if (sslDetail.connectState) {
|
||||||
|
sslOverlayIcon = QPixmap(":/images/connect_creating.png");
|
||||||
|
} else {
|
||||||
|
sslOverlayIcon = QPixmap(StatusDefs::imageStatus(RS_STATUS_ONLINE));
|
||||||
|
}
|
||||||
|
|
||||||
|
connectStateString = StatusDefs::name(RS_STATUS_ONLINE);
|
||||||
|
|
||||||
|
sslFont.setBold(true);
|
||||||
|
sslColor = mTextColorStatus[RS_STATUS_ONLINE];
|
||||||
|
} else {
|
||||||
|
peerState = PEER_STATE_OFFLINE;
|
||||||
|
sslItem->setHidden(mHideUnconnected);
|
||||||
|
if (sslDetail.connectState) {
|
||||||
|
sslOverlayIcon = QPixmap(":/images/connect_creating.png");
|
||||||
|
} else {
|
||||||
|
sslOverlayIcon = QPixmap(StatusDefs::imageStatus(RS_STATUS_OFFLINE));
|
||||||
|
}
|
||||||
|
|
||||||
|
connectStateString = StatusDefs::connectStateWithoutTransportTypeString(sslDetail);
|
||||||
|
|
||||||
|
sslFont.setBold(false);
|
||||||
|
sslColor = mTextColorStatus[RS_STATUS_OFFLINE];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Location */
|
||||||
|
QString sslName = QString::fromUtf8(sslDetail.location.c_str());
|
||||||
|
QString sslText;
|
||||||
|
|
||||||
|
if (mShowState) {
|
||||||
|
if (!connectStateString.isEmpty()) {
|
||||||
|
sslText = connectStateString;
|
||||||
|
if (!customStateString.isEmpty()) {
|
||||||
|
sslText += " [" + customStateString + "]";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!customStateString.isEmpty()) {
|
||||||
|
sslText = customStateString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sslItem->setToolTip(COLUMN_NAME, "");
|
||||||
|
} else {
|
||||||
|
if (!customStateString.isEmpty()) {
|
||||||
|
sslText = customStateString;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Show the state as tooltip */
|
||||||
|
sslItem->setToolTip(COLUMN_NAME, connectStateString);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create or get ssl label */
|
||||||
|
ElidedLabel *sslNameLabel = NULL;
|
||||||
|
ElidedLabel *sslTextLabel = NULL;
|
||||||
|
|
||||||
|
getNameWidget(ui->peerTreeWidget, sslItem, sslNameLabel, sslTextLabel);
|
||||||
|
|
||||||
|
if (sslNameLabel) {
|
||||||
|
sslNameLabel->setText(sslName);
|
||||||
|
sslNameLabel->setFont(sslFont);
|
||||||
|
|
||||||
|
QPalette palette = sslNameLabel->palette();
|
||||||
|
palette.setColor(sslNameLabel->foregroundRole(), sslColor);
|
||||||
|
|
||||||
|
sslNameLabel->setPalette(palette);
|
||||||
|
}
|
||||||
|
if (sslTextLabel) {
|
||||||
|
sslTextLabel->setText(sslText);
|
||||||
|
sslTextLabel->setVisible(!sslText.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter
|
||||||
|
sslItem->setData(COLUMN_NAME, ROLE_FILTER, sslName);
|
||||||
|
|
||||||
|
if (std::find(privateChatIds.begin(), privateChatIds.end(), sslDetail.id) != privateChatIds.end()) {
|
||||||
|
// private chat is available
|
||||||
|
sslOverlayIcon = QPixmap(":/images/chat.png");
|
||||||
|
gpg_hasPrivateChat = true;
|
||||||
|
}
|
||||||
|
sslItem->setIcon(COLUMN_NAME, createAvatar(sslAvatar, sslOverlayIcon));
|
||||||
|
|
||||||
|
/* Sort data */
|
||||||
|
sslItem->setData(COLUMN_NAME, ROLE_SORT_NAME, sslName);
|
||||||
|
|
||||||
|
for (int i = 0; i < columnCount; ++i) {
|
||||||
|
sslItem->setData(i, ROLE_SORT_STATE, peerState);
|
||||||
|
|
||||||
|
sslItem->setTextColor(i, sslColor);
|
||||||
|
sslItem->setFont(i, sslFont);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QString gpgName = QString::fromUtf8(detail.name.c_str());
|
QString gpgName = QString::fromUtf8(detail.name.c_str());
|
||||||
QString gpgText;
|
QString gpgText;
|
||||||
|
@ -1172,38 +1123,38 @@ void FriendList::insertPeers()
|
||||||
bool showInfoAtGpgItem = !gpgItem->isExpanded();
|
bool showInfoAtGpgItem = !gpgItem->isExpanded();
|
||||||
|
|
||||||
QPixmap gpgOverlayIcon;
|
QPixmap gpgOverlayIcon;
|
||||||
if (info.gpg_connected) {
|
if (gpg_connected) {
|
||||||
gpgItem->setHidden(false);
|
gpgItem->setHidden(false);
|
||||||
|
|
||||||
++onlineCount;
|
++onlineCount;
|
||||||
|
|
||||||
if (info.bestPeerState == 0) {
|
if (bestPeerState == 0) {
|
||||||
// show as online
|
// show as online
|
||||||
info.bestPeerState = PEER_STATE_ONLINE;
|
bestPeerState = PEER_STATE_ONLINE;
|
||||||
info.bestRSState = RS_STATUS_ONLINE;
|
bestRSState = RS_STATUS_ONLINE;
|
||||||
}
|
}
|
||||||
|
|
||||||
gpgColor = mTextColorStatus[info.bestRSState];
|
gpgColor = mTextColorStatus[bestRSState];
|
||||||
gpgFont = StatusDefs::font(info.bestRSState);
|
gpgFont = StatusDefs::font(bestRSState);
|
||||||
|
|
||||||
if (showInfoAtGpgItem) {
|
if (showInfoAtGpgItem) {
|
||||||
gpgOverlayIcon = QPixmap(StatusDefs::imageStatus(info.bestRSState));
|
gpgOverlayIcon = QPixmap(StatusDefs::imageStatus(bestRSState));
|
||||||
|
|
||||||
if (mShowState) {
|
if (mShowState) {
|
||||||
gpgText = StatusDefs::name(info.bestRSState);
|
gpgText = StatusDefs::name(bestRSState);
|
||||||
if (!info.bestCustomStateString.isEmpty()) {
|
if (!bestCustomStateString.isEmpty()) {
|
||||||
gpgText += " [" + info.bestCustomStateString + "]";
|
gpgText += " [" + bestCustomStateString + "]";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!info.bestCustomStateString.isEmpty()) {
|
if (!bestCustomStateString.isEmpty()) {
|
||||||
gpgText = info.bestCustomStateString;
|
gpgText = bestCustomStateString;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (info.gpg_online) {
|
} else if (gpg_online) {
|
||||||
gpgItem->setHidden(mHideUnconnected);
|
gpgItem->setHidden(mHideUnconnected);
|
||||||
++onlineCount;
|
++onlineCount;
|
||||||
info.bestPeerState = PEER_STATE_AVAILABLE;
|
bestPeerState = PEER_STATE_AVAILABLE;
|
||||||
|
|
||||||
gpgFont.setBold(true);
|
gpgFont.setBold(true);
|
||||||
gpgColor = mTextColorStatus[RS_STATUS_ONLINE];
|
gpgColor = mTextColorStatus[RS_STATUS_ONLINE];
|
||||||
|
@ -1216,7 +1167,7 @@ void FriendList::insertPeers()
|
||||||
gpgOverlayIcon = QPixmap(IMAGE_AVAILABLE);
|
gpgOverlayIcon = QPixmap(IMAGE_AVAILABLE);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
info.bestPeerState = PEER_STATE_OFFLINE;
|
bestPeerState = PEER_STATE_OFFLINE;
|
||||||
gpgItem->setHidden(mHideUnconnected);
|
gpgItem->setHidden(mHideUnconnected);
|
||||||
|
|
||||||
gpgFont = StatusDefs::font(RS_STATUS_OFFLINE);
|
gpgFont = StatusDefs::font(RS_STATUS_OFFLINE);
|
||||||
|
@ -1231,11 +1182,11 @@ void FriendList::insertPeers()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info.gpg_hasPrivateChat) {
|
if (gpg_hasPrivateChat) {
|
||||||
gpgOverlayIcon = QPixmap(":/images/chat.png");
|
gpgOverlayIcon = QPixmap(":/images/chat.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
gpgItem->setIcon(COLUMN_NAME, createAvatar(info.bestAvatar.isNull() ? QPixmap(AVATAR_DEFAULT_IMAGE) : info.bestAvatar, gpgOverlayIcon));
|
gpgItem->setIcon(COLUMN_NAME, createAvatar(bestAvatar.isNull() ? QPixmap(AVATAR_DEFAULT_IMAGE) : bestAvatar, gpgOverlayIcon));
|
||||||
|
|
||||||
/* Create or get gpg label */
|
/* Create or get gpg label */
|
||||||
ElidedLabel *gpgNameLabel = NULL;
|
ElidedLabel *gpgNameLabel = NULL;
|
||||||
|
@ -1260,16 +1211,16 @@ void FriendList::insertPeers()
|
||||||
// Filter
|
// Filter
|
||||||
gpgItem->setData(COLUMN_NAME, ROLE_FILTER, gpgName);
|
gpgItem->setData(COLUMN_NAME, ROLE_FILTER, gpgName);
|
||||||
|
|
||||||
gpgItem->setData(COLUMN_LAST_CONTACT, Qt::DisplayRole, showInfoAtGpgItem ? QVariant(info.bestLastContact) : "");
|
gpgItem->setData(COLUMN_LAST_CONTACT, Qt::DisplayRole, showInfoAtGpgItem ? QVariant(bestLastContact) : "");
|
||||||
gpgItem->setData(COLUMN_LAST_CONTACT, ROLE_SORT_NAME, QVariant(info.bestLastContact));
|
gpgItem->setData(COLUMN_LAST_CONTACT, ROLE_SORT_NAME, QVariant(bestLastContact));
|
||||||
gpgItem->setText(COLUMN_IP, showInfoAtGpgItem ? info.bestIP : "");
|
gpgItem->setText(COLUMN_IP, showInfoAtGpgItem ? bestIP : "");
|
||||||
gpgItem->setData(COLUMN_IP, ROLE_SORT_NAME, info.bestIP);
|
gpgItem->setData(COLUMN_IP, ROLE_SORT_NAME, bestIP);
|
||||||
|
|
||||||
/* Sort data */
|
/* Sort data */
|
||||||
gpgItem->setData(COLUMN_NAME, ROLE_SORT_NAME, gpgName);
|
gpgItem->setData(COLUMN_NAME, ROLE_SORT_NAME, gpgName);
|
||||||
|
|
||||||
for (int i = 0; i < columnCount; ++i) {
|
for (int i = 0; i < columnCount; ++i) {
|
||||||
gpgItem->setData(i, ROLE_SORT_STATE, info.bestPeerState);
|
gpgItem->setData(i, ROLE_SORT_STATE, bestPeerState);
|
||||||
|
|
||||||
gpgItem->setTextColor(i, gpgColor);
|
gpgItem->setTextColor(i, gpgColor);
|
||||||
gpgItem->setFont(i, gpgFont);
|
gpgItem->setFont(i, gpgFont);
|
||||||
|
@ -2014,7 +1965,7 @@ bool FriendList::exportFriendlist(QString &fileName)
|
||||||
/**
|
/**
|
||||||
* @brief helper function to show a message box
|
* @brief helper function to show a message box
|
||||||
*/
|
*/
|
||||||
void showXMLParsingError()
|
static void showXMLParsingError()
|
||||||
{
|
{
|
||||||
// show error to user
|
// show error to user
|
||||||
QMessageBox mbox;
|
QMessageBox mbox;
|
||||||
|
|
1220
retroshare-gui/src/gui/common/FriendListModel.cpp
Normal file
1220
retroshare-gui/src/gui/common/FriendListModel.cpp
Normal file
File diff suppressed because it is too large
Load diff
235
retroshare-gui/src/gui/common/FriendListModel.h
Normal file
235
retroshare-gui/src/gui/common/FriendListModel.h
Normal file
|
@ -0,0 +1,235 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* retroshare-gui/src/gui/msgs/RsFriendListModel.h *
|
||||||
|
* *
|
||||||
|
* Copyright 2019 by Cyril Soler <csoler@users.sourceforge.net> *
|
||||||
|
* *
|
||||||
|
* This program is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU Affero General Public License as *
|
||||||
|
* published by the Free Software Foundation, either version 3 of the *
|
||||||
|
* License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU Affero General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU Affero General Public License *
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QModelIndex>
|
||||||
|
#include <QColor>
|
||||||
|
|
||||||
|
#include "retroshare/rsstatus.h"
|
||||||
|
#include "retroshare/rsmsgs.h"
|
||||||
|
#include "retroshare/rspeers.h"
|
||||||
|
|
||||||
|
typedef uint32_t ForumModelIndex;
|
||||||
|
|
||||||
|
// This class is the item model used by Qt to display the information
|
||||||
|
|
||||||
|
class RsFriendListModel : public QAbstractItemModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit RsFriendListModel(QObject *parent = NULL);
|
||||||
|
~RsFriendListModel(){}
|
||||||
|
|
||||||
|
class RsNodeDetails: public RsPeerDetails {};// in the near future, there will be a specific class for Profile/Node details in replacement of RsPeerDetails
|
||||||
|
class RsProfileDetails: public RsPeerDetails {};
|
||||||
|
|
||||||
|
struct HierarchicalGroupInformation
|
||||||
|
{
|
||||||
|
RsGroupInfo group_info;
|
||||||
|
std::vector<uint32_t> child_profile_indices; // index in the array of hierarchical profiles
|
||||||
|
};
|
||||||
|
struct HierarchicalProfileInformation
|
||||||
|
{
|
||||||
|
RsProfileDetails profile_info;
|
||||||
|
std::vector<uint32_t> child_node_indices; // indices of nodes in the array of nodes.
|
||||||
|
};
|
||||||
|
struct HierarchicalNodeInformation
|
||||||
|
{
|
||||||
|
HierarchicalNodeInformation() : last_update_ts(0) {}
|
||||||
|
|
||||||
|
rstime_t last_update_ts;
|
||||||
|
RsNodeDetails node_info;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Columns {
|
||||||
|
COLUMN_THREAD_NAME = 0x00,
|
||||||
|
COLUMN_THREAD_LAST_CONTACT = 0x01,
|
||||||
|
COLUMN_THREAD_IP = 0x02,
|
||||||
|
COLUMN_THREAD_ID = 0x03,
|
||||||
|
COLUMN_THREAD_NB_COLUMNS = 0x04
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Roles{ SortRole = Qt::UserRole+1,
|
||||||
|
StatusRole = Qt::UserRole+2,
|
||||||
|
UnreadRole = Qt::UserRole+3,
|
||||||
|
FilterRole = Qt::UserRole+4,
|
||||||
|
OnlineRole = Qt::UserRole+5,
|
||||||
|
TypeRole = Qt::UserRole+6
|
||||||
|
};
|
||||||
|
|
||||||
|
enum FilterType{ FILTER_TYPE_NONE = 0x00,
|
||||||
|
FILTER_TYPE_ID = 0x01,
|
||||||
|
FILTER_TYPE_NAME = 0x02
|
||||||
|
};
|
||||||
|
|
||||||
|
enum EntryType{ ENTRY_TYPE_UNKNOWN = 0x00,
|
||||||
|
ENTRY_TYPE_GROUP = 0x01,
|
||||||
|
ENTRY_TYPE_PROFILE = 0x02,
|
||||||
|
ENTRY_TYPE_NODE = 0x03
|
||||||
|
};
|
||||||
|
|
||||||
|
// This structure encodes the position of a node in the hierarchy. The type tells which of the index fields are valid.
|
||||||
|
|
||||||
|
struct EntryIndex
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
EntryIndex();
|
||||||
|
|
||||||
|
EntryType type; // type of the entry (group,profile,location)
|
||||||
|
|
||||||
|
// Indices w.r.t. parent. The set of indices entirely determines the position of the entry in the hierarchy.
|
||||||
|
// An index of 0xff means "undefined"
|
||||||
|
|
||||||
|
uint16_t group_index; // index of the group in mGroups tab
|
||||||
|
uint16_t profile_index; // index of the child profile in its own group if group_index < 0xff, or in the mProfiles tab otherwise.
|
||||||
|
uint16_t node_index; // index of the child node in its own profile
|
||||||
|
|
||||||
|
EntryIndex parent() const;
|
||||||
|
EntryIndex child(int row,const std::vector<EntryIndex>& top_level) const;
|
||||||
|
uint32_t parentRow(uint32_t nb_groups) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
QModelIndex root() const{ return createIndex(0,0,(void*)NULL) ;}
|
||||||
|
QModelIndex getIndexOfGroup(const RsNodeGroupId& mid) const;
|
||||||
|
|
||||||
|
static const QString FilterString ;
|
||||||
|
|
||||||
|
// This method will asynchroneously update the data
|
||||||
|
|
||||||
|
void setDisplayGroups(bool b);
|
||||||
|
bool getDisplayGroups() const { return mDisplayGroups; }
|
||||||
|
|
||||||
|
void setDisplayStatusString(bool b);
|
||||||
|
bool getDisplayStatusString() const { return mDisplayStatusString; }
|
||||||
|
|
||||||
|
EntryType getType(const QModelIndex&) const;
|
||||||
|
|
||||||
|
bool getGroupData (const QModelIndex&,RsGroupInfo &) const;
|
||||||
|
bool getProfileData(const QModelIndex&,RsProfileDetails&) const;
|
||||||
|
bool getNodeData (const QModelIndex&,RsNodeDetails &) const;
|
||||||
|
|
||||||
|
void setFilter(FilterType filter_type, const QStringList& strings) ;
|
||||||
|
|
||||||
|
void expandItem(const QModelIndex&) ;
|
||||||
|
void collapseItem(const QModelIndex&) ;
|
||||||
|
|
||||||
|
// Overloaded methods from QAbstractItemModel
|
||||||
|
|
||||||
|
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||||
|
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
bool hasChildren(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
|
||||||
|
QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const override;
|
||||||
|
QModelIndex parent(const QModelIndex& child) const override;
|
||||||
|
Qt::ItemFlags flags(const QModelIndex& index) const override;
|
||||||
|
|
||||||
|
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||||
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
|
|
||||||
|
void clear() ;
|
||||||
|
|
||||||
|
/* Color definitions (for standard see qss.default) */
|
||||||
|
QColor mTextColorGroup;
|
||||||
|
QColor mTextColorStatus[RS_STATUS_COUNT];
|
||||||
|
|
||||||
|
private:
|
||||||
|
const HierarchicalGroupInformation *getGroupInfo (const EntryIndex&) const;
|
||||||
|
const HierarchicalProfileInformation *getProfileInfo(const EntryIndex&)const;
|
||||||
|
const HierarchicalNodeInformation *getNodeInfo(const EntryIndex&) const;
|
||||||
|
|
||||||
|
bool isProfileExpanded(const EntryIndex& e) const;
|
||||||
|
void checkNode(HierarchicalNodeInformation& node);
|
||||||
|
bool getPeerOnlineStatus(const EntryIndex& e) const;
|
||||||
|
std::map<RsPgpId,uint32_t>::const_iterator checkProfileIndex(const RsPgpId& pgp_id,
|
||||||
|
std::map<RsPgpId,uint32_t>& pgp_indices,
|
||||||
|
std::vector<HierarchicalProfileInformation>& mProfiles,
|
||||||
|
bool create);
|
||||||
|
|
||||||
|
QVariant sizeHintRole (const EntryIndex& e, int col) const;
|
||||||
|
QVariant displayRole (const EntryIndex& e, int col) const;
|
||||||
|
QVariant decorationRole(const EntryIndex& e, int col) const;
|
||||||
|
QVariant toolTipRole (const EntryIndex& e, int col) const;
|
||||||
|
QVariant statusRole (const EntryIndex& e, int col) const;
|
||||||
|
QVariant sortRole (const EntryIndex& e, int col) const;
|
||||||
|
QVariant fontRole (const EntryIndex& e, int col) const;
|
||||||
|
QVariant textColorRole (const EntryIndex& e, int col) const;
|
||||||
|
QVariant onlineRole (const EntryIndex& e, int col) const;
|
||||||
|
QVariant filterRole (const EntryIndex& e, int col) const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief debug_dump
|
||||||
|
* Dumps the hierarchy of posts in the terminal, to allow checking whether the internal representation is correct.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void checkInternalData(bool force);
|
||||||
|
void debug_dump() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void dataLoaded(); // emitted after the messages have been set. Can be used to updated the UI.
|
||||||
|
void friendListChanged(); // emitted after the messages have been set. Can be used to updated the UI.
|
||||||
|
void dataAboutToLoad();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void updateInternalData();
|
||||||
|
bool passesFilter(const EntryIndex &e, int column) const;
|
||||||
|
|
||||||
|
void preMods() ;
|
||||||
|
void postMods() ;
|
||||||
|
|
||||||
|
void *getParentRef(void *ref,int& row) const;
|
||||||
|
void *getChildRef(void *ref,int row) const;
|
||||||
|
int getChildrenCount(void *ref) const;
|
||||||
|
|
||||||
|
template<uint8_t> static bool convertIndexToInternalId(const EntryIndex& e,quintptr& ref);
|
||||||
|
template<uint8_t> static bool convertInternalIdToIndex(quintptr ref, EntryIndex& e);
|
||||||
|
|
||||||
|
uint32_t updateFilterStatus(ForumModelIndex i,int column,const QStringList& strings);
|
||||||
|
|
||||||
|
QStringList mFilterStrings;
|
||||||
|
FilterType mFilterType;
|
||||||
|
|
||||||
|
bool mDisplayGroups ;
|
||||||
|
bool mDisplayStatusString ;
|
||||||
|
rstime_t mLastInternalDataUpdate;
|
||||||
|
rstime_t mLastNodeUpdate;;
|
||||||
|
|
||||||
|
// The 3 vectors below store thehierarchical information for groups, profiles and locations,
|
||||||
|
// meaning which is the child/parent of which. The actual group/profile/node data are also stored in the
|
||||||
|
// structure.
|
||||||
|
|
||||||
|
mutable std::vector<HierarchicalGroupInformation> mGroups;
|
||||||
|
mutable std::vector<HierarchicalProfileInformation> mProfiles;
|
||||||
|
mutable std::vector<HierarchicalNodeInformation> mLocations;
|
||||||
|
|
||||||
|
// The top level list contains all nodes to display, which type depends on the option to display groups or not.
|
||||||
|
// Idices in the list may be profile indices or group indices. In the former case the profile child index refers to
|
||||||
|
// the inde in the mProfiles tab, whereas in the the later case, the child index refers to the index of the profile in the
|
||||||
|
// group it belows to.
|
||||||
|
|
||||||
|
std::vector<EntryIndex> mTopLevel;
|
||||||
|
|
||||||
|
// keeps track of expanded/collapsed items, so as to only show icon for collapsed profiles
|
||||||
|
|
||||||
|
std::set<std::string> mExpandedProfiles;
|
||||||
|
};
|
||||||
|
|
1511
retroshare-gui/src/gui/common/NewFriendList.cpp
Normal file
1511
retroshare-gui/src/gui/common/NewFriendList.cpp
Normal file
File diff suppressed because it is too large
Load diff
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue