mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-02-05 01:25:39 -05:00
merged upstream/master
This commit is contained in:
commit
6419b03a2a
@ -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();
|
||||||
$%sessionEarlyClose%$
|
|
||||||
|
mService.schedule( [weakSession, message]()
|
||||||
|
{
|
||||||
|
auto session = weakSession.lock();
|
||||||
|
if(!session || session->is_closed()) return;
|
||||||
|
session->yield(message);
|
||||||
|
$%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%$ );
|
||||||
|
|
||||||
|
@ -39,12 +39,12 @@
|
|||||||
|
|
||||||
//#define DEBUG_CHAT_LOBBIES 1
|
//#define DEBUG_CHAT_LOBBIES 1
|
||||||
|
|
||||||
static const int CONNECTION_CHALLENGE_MAX_COUNT = 20 ; // sends a connection challenge every 20 messages
|
static const int CONNECTION_CHALLENGE_MAX_COUNT = 20 ; // sends a connection challenge every 20 messages
|
||||||
static const rstime_t CONNECTION_CHALLENGE_MAX_MSG_AGE = 30 ; // maximum age of a message to be used in a connection challenge
|
static const rstime_t CONNECTION_CHALLENGE_MAX_MSG_AGE = 30 ; // maximum age of a message to be used in a connection challenge
|
||||||
static const int CONNECTION_CHALLENGE_MIN_DELAY = 15 ; // sends a connection at most every 15 seconds
|
static const int CONNECTION_CHALLENGE_MIN_DELAY = 15 ; // sends a connection at most every 15 seconds
|
||||||
static const int LOBBY_CACHE_CLEANING_PERIOD = 10 ; // clean lobby caches every 10 secs (remove old messages)
|
static const int LOBBY_CACHE_CLEANING_PERIOD = 10 ; // clean lobby caches every 10 secs (remove old messages)
|
||||||
|
|
||||||
static const rstime_t MAX_KEEP_MSG_RECORD = 1200 ; // keep msg record for 1200 secs max.
|
static const rstime_t MAX_KEEP_MSG_RECORD = 1200 ; // keep msg record for 1200 secs max.
|
||||||
static const rstime_t MAX_KEEP_INACTIVE_NICKNAME = 180 ; // keep inactive nicknames for 3 mn max.
|
static const rstime_t MAX_KEEP_INACTIVE_NICKNAME = 180 ; // keep inactive nicknames for 3 mn max.
|
||||||
static const rstime_t MAX_DELAY_BETWEEN_LOBBY_KEEP_ALIVE = 120 ; // send keep alive packet every 2 minutes.
|
static const rstime_t MAX_DELAY_BETWEEN_LOBBY_KEEP_ALIVE = 120 ; // send keep alive packet every 2 minutes.
|
||||||
static const rstime_t MAX_KEEP_PUBLIC_LOBBY_RECORD = 60 ; // keep inactive lobbies records for 60 secs max.
|
static const rstime_t MAX_KEEP_PUBLIC_LOBBY_RECORD = 60 ; // keep inactive lobbies records for 60 secs max.
|
||||||
@ -52,7 +52,7 @@ static const rstime_t MIN_DELAY_BETWEEN_PUBLIC_LOBBY_REQ = 20 ; // don't ask
|
|||||||
static const rstime_t LOBBY_LIST_AUTO_UPDATE_TIME = 121 ; // regularly ask for available lobbies every 5 minutes, to allow auto-subscribe to work
|
static const rstime_t LOBBY_LIST_AUTO_UPDATE_TIME = 121 ; // regularly ask for available lobbies every 5 minutes, to allow auto-subscribe to work
|
||||||
|
|
||||||
static const uint32_t MAX_ALLOWED_LOBBIES_IN_LIST_WARNING = 50 ;
|
static const uint32_t MAX_ALLOWED_LOBBIES_IN_LIST_WARNING = 50 ;
|
||||||
//static const uint32_t MAX_MESSAGES_PER_SECONDS_NUMBER = 5 ; // max number of messages from a given peer in a window for duration below
|
//static const uint32_t MAX_MESSAGES_PER_SECONDS_NUMBER = 5 ; // max number of messages from a given peer in a window for duration below
|
||||||
static const uint32_t MAX_MESSAGES_PER_SECONDS_PERIOD = 10 ; // duration window for max number of messages before messages get dropped.
|
static const uint32_t MAX_MESSAGES_PER_SECONDS_PERIOD = 10 ; // duration window for max number of messages before messages get dropped.
|
||||||
|
|
||||||
#define IS_PUBLIC_LOBBY(flags) (flags & RS_CHAT_LOBBY_FLAGS_PUBLIC )
|
#define IS_PUBLIC_LOBBY(flags) (flags & RS_CHAT_LOBBY_FLAGS_PUBLIC )
|
||||||
@ -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,15 +1833,27 @@ 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){
|
|
||||||
_known_lobbies_flags[lobby_id] |= RS_CHAT_LOBBY_FLAGS_AUTO_SUBSCRIBE;
|
if(autoSubscribe)
|
||||||
RsGxsId gxsId;
|
{
|
||||||
if (getIdentityForChatLobby(lobby_id, gxsId))
|
{
|
||||||
_lobby_default_identity[lobby_id] = gxsId;
|
RS_STACK_MUTEX(mDistributedChatMtx);
|
||||||
} else {
|
_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);
|
RsGxsId gxsId;
|
||||||
}
|
|
||||||
|
if (getIdentityForChatLobby(lobby_id, gxsId))
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(mDistributedChatMtx);
|
||||||
|
_lobby_default_identity[lobby_id] = gxsId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RS_STACK_MUTEX(mDistributedChatMtx);
|
||||||
|
_known_lobbies_flags[lobby_id] &= ~RS_CHAT_LOBBY_FLAGS_AUTO_SUBSCRIBE ;
|
||||||
|
_lobby_default_identity.erase(lobby_id);
|
||||||
|
}
|
||||||
|
|
||||||
RsServer::notify()->notifyListChange(NOTIFY_LIST_CHAT_LOBBY_LIST, NOTIFY_TYPE_ADD) ;
|
RsServer::notify()->notifyListChange(NOTIFY_LIST_CHAT_LOBBY_LIST, NOTIFY_TYPE_ADD) ;
|
||||||
triggerConfigSave();
|
triggerConfigSave();
|
||||||
@ -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) ;
|
||||||
|
|
||||||
@ -93,7 +94,7 @@ class DistributedChatService
|
|||||||
bool sendLobbyChat(const ChatLobbyId &lobby_id, const std::string&) ;
|
bool sendLobbyChat(const ChatLobbyId &lobby_id, const std::string&) ;
|
||||||
bool handleRecvChatLobbyMsgItem(RsChatMsgItem *item) ;
|
bool handleRecvChatLobbyMsgItem(RsChatMsgItem *item) ;
|
||||||
|
|
||||||
bool checkSignature(RsChatLobbyBouncingObject *obj,const RsPeerId& peer_id) ;
|
bool checkSignature(RsChatLobbyBouncingObject *obj,const RsPeerId& peer_id) ;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// make some statistics about time shifts, to prevent various issues.
|
/// make some statistics about time shifts, to prevent various issues.
|
||||||
@ -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
|
||||||
|
@ -109,8 +109,8 @@ class p3FileDatabase: public p3Service, public p3Config, public ftSearch //, pub
|
|||||||
virtual int SearchKeywords(const std::list<std::string>& keywords, std::list<DirDetails>& results,FileSearchFlags flags,const RsPeerId& peer_id) ;
|
virtual int SearchKeywords(const std::list<std::string>& keywords, std::list<DirDetails>& results,FileSearchFlags flags,const RsPeerId& peer_id) ;
|
||||||
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();
|
||||||
|
|
||||||
rsEvents->registerEventsHandler(
|
if(rsEvents)
|
||||||
[this](const RsEvent& event){ rsEventsHandler(event); },
|
rsEvents->registerEventsHandler(
|
||||||
mRsEventsHandle );
|
[this](std::shared_ptr<const RsEvent> event)
|
||||||
|
{
|
||||||
|
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,9 +963,9 @@ 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;
|
||||||
}
|
}
|
||||||
case RsGxsTransEncryptionMode::RSA:
|
case RsGxsTransEncryptionMode::RSA:
|
||||||
@ -986,15 +985,15 @@ 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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,24 +303,28 @@ 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)
|
||||||
{
|
{
|
||||||
auto session = weakSession.lock();
|
mService.schedule( [weakSession, hId, event]()
|
||||||
if(!session || session->is_closed())
|
|
||||||
{
|
{
|
||||||
if(rsEvents) rsEvents->unregisterEventsHandler(hId);
|
auto session = weakSession.lock();
|
||||||
return;
|
if(!session || session->is_closed())
|
||||||
}
|
{
|
||||||
|
if(rsEvents) rsEvents->unregisterEventsHandler(hId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
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,12 +477,24 @@ 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
|
||||||
virtual bool ExtraFileRemove(const RsFileHash& hash) = 0;
|
* @return return false on error, true otherwise
|
||||||
virtual bool ExtraFileHash(std::string localpath, uint32_t period, TransferRequestFlags flags) = 0;
|
*/
|
||||||
virtual bool ExtraFileStatus(std::string localpath, FileInfo &info) = 0;
|
virtual bool ExtraFileRemove(const RsFileHash& hash) = 0;
|
||||||
virtual bool ExtraFileMove(std::string fname, const RsFileHash& hash, uint64_t size, std::string destpath) = 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 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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -43,8 +43,10 @@ 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,14 +140,20 @@ 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
|
||||||
uint32_t mMsgFlags;
|
* @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;
|
||||||
|
|
||||||
// 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
|
||||||
uint32_t mMsgStatus;
|
* @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;
|
||||||
|
|
||||||
rstime_t mChildTs;
|
rstime_t mChildTs;
|
||||||
std::string mServiceString; // Service Specific Free-Form extra storage.
|
std::string mServiceString; // Service Specific Free-Form extra storage.
|
||||||
@ -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;
|
||||||
|
|
||||||
|
@ -347,12 +347,12 @@ 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,7 +488,8 @@ 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];
|
||||||
errcode = UpnpResolveURL(
|
errcode = UpnpResolveURL(
|
||||||
@ -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>
|
||||||
|
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
* *
|
* *
|
||||||
* 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 //
|
||||||
//============================================================================//
|
//============================================================================//
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
* *
|
* *
|
||||||
* 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 RsGxsMessageId& threadId,
|
const RsGxsGroupId& channelId,
|
||||||
const RsGxsMessageId& parentId,
|
const RsGxsMessageId& threadId,
|
||||||
const RsGxsId& authorId,
|
const std::string& comment,
|
||||||
const std::string& comment,
|
const RsGxsId& authorId,
|
||||||
RsGxsMessageId& commentMessageId,
|
const RsGxsMessageId& parentId,
|
||||||
std::string& errorMessage)
|
const RsGxsMessageId& origCommentId,
|
||||||
|
RsGxsMessageId& commentMessageId,
|
||||||
|
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
|
||||||
{ // is the comment parent actually a comment?
|
{
|
||||||
errorMessage = "You cannot comment post " + parentId.toStdString()
|
if(comments.size() != 1 || comments[0].mMeta.mParentId.isNull())
|
||||||
+ " of channel with Id " + channelId.toStdString() +
|
{ // is the comment parent actually a comment?
|
||||||
": supplied mParentMsgId is not a comment Id!";
|
errorMessage = "You cannot comment post "
|
||||||
std::cerr << __PRETTY_FUNCTION__ << " Error: " << errorMessage
|
+ parentId.toStdString()
|
||||||
<< std::endl;
|
+ " of channel with Id " + channelId.toStdString() +
|
||||||
|
": supplied mParentMsgId is not a comment Id!";
|
||||||
|
std::cerr << __PRETTY_FUNCTION__ << " Error: " << errorMessage
|
||||||
|
<< std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!rsIdentity->isOwnId(authorId)) // is the voter ID actually ours?
|
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,11 +213,14 @@ 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,
|
||||||
RsGxsMessageId& commentMessageId = RS_DEFAULT_STORAGE_PARAM(RsGxsMessageId),
|
const RsGxsId& authorId,
|
||||||
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
|
const RsGxsMessageId& parentId = RsGxsMessageId(),
|
||||||
|
const RsGxsMessageId& origCommentId = RsGxsMessageId(),
|
||||||
|
RsGxsMessageId& commentMessageId = RS_DEFAULT_STORAGE_PARAM(RsGxsMessageId),
|
||||||
|
std::string& errorMessage = RS_DEFAULT_STORAGE_PARAM(std::string)
|
||||||
) override;
|
) override;
|
||||||
|
|
||||||
/// Implementation of @see RsGxsChannels::editChannel
|
/// Implementation of @see RsGxsChannels::editChannel
|
||||||
|
@ -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,8 +621,9 @@ bool p3GxsForums::getForumsInfo(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool p3GxsForums::getForumContent(
|
bool p3GxsForums::getForumContent(
|
||||||
const RsGxsGroupId& forumId, std::set<RsGxsMessageId>& msgs_to_request,
|
const RsGxsGroupId& forumId,
|
||||||
std::vector<RsGxsForumMsg>& msgs )
|
const std::set<RsGxsMessageId>& msgs_to_request,
|
||||||
|
std::vector<RsGxsForumMsg>& msgs )
|
||||||
{
|
{
|
||||||
uint32_t token;
|
uint32_t token;
|
||||||
RsTokReqOptions opts;
|
RsTokReqOptions opts;
|
||||||
@ -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,30 +3355,23 @@ 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 =
|
||||||
if(mit->second.keyFlags == (RSTLV_KEY_DISTRIB_ADMIN | RSTLV_KEY_TYPE_FULL))
|
keySet.private_keys.begin(); mit != keySet.private_keys.end(); ++mit )
|
||||||
|
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);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
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) ;
|
||||||
|
|
||||||
/********************* TEMP HACK UNTIL GXS FILLS IN GROUP_ID *****************/
|
/********************* TEMP HACK UNTIL GXS FILLS IN GROUP_ID *****************/
|
||||||
@ -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,12 +3434,12 @@ 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!
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_IDS
|
#ifdef DEBUG_IDS
|
||||||
std::cerr << "p3IdService::service_CreateGroup() OwnFingerprint: " << ownFinger.toStdString();
|
std::cerr << "p3IdService::service_CreateGroup() OwnFingerprint: " << ownFinger.toStdString();
|
||||||
@ -3427,60 +3461,69 @@ 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;
|
||||||
|
|
||||||
/* error */
|
/* This method is DEPRECATED we call it only for retrocompatibility with
|
||||||
switch(result)
|
* retroshare-gui, when called from something different then
|
||||||
{
|
* retroshare-gui for example retroshare-service it miserably fail! */
|
||||||
case SELF_SIGNATURE_RESULT_PENDING : createStatus = SERVICE_CREATE_FAIL_TRY_LATER;
|
mPgpUtils->askForDeferredSelfSignature(
|
||||||
std::cerr << "p3IdService::service_CreateGroup() signature still pending" << std::endl;
|
static_cast<const void*>(hash.toByteArray()),
|
||||||
break ;
|
hash.SIZE_IN_BYTES, signarray, &sign_size, result,
|
||||||
default:
|
__PRETTY_FUNCTION__ );
|
||||||
case SELF_SIGNATURE_RESULT_FAILED: return SERVICE_CREATE_FAIL ;
|
|
||||||
std::cerr << "p3IdService::service_CreateGroup() signature failed" << std::endl;
|
|
||||||
break ;
|
|
||||||
|
|
||||||
case SELF_SIGNATURE_RESULT_SUCCESS:
|
/* If askForDeferredSelfSignature left result untouched it means
|
||||||
{
|
* libretroshare is being used by something different then
|
||||||
// Additional consistency checks.
|
* 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;
|
||||||
|
|
||||||
if(sign_size == MAX_SIGN_SIZE)
|
switch(result)
|
||||||
{
|
{
|
||||||
std::cerr << "Inconsistent result. Signature uses full buffer. This is probably an error." << std::endl;
|
case SELF_SIGNATURE_RESULT_PENDING:
|
||||||
return SERVICE_CREATE_FAIL; // abandon attempt!
|
createStatus = SERVICE_CREATE_FAIL_TRY_LATER;
|
||||||
}
|
Dbg1() << __PRETTY_FUNCTION__ << " signature still pending"
|
||||||
#ifdef DEBUG_IDS
|
<< std::endl;
|
||||||
std::cerr << "p3IdService::service_CreateGroup() Signature: ";
|
break;
|
||||||
std::string strout;
|
case SELF_SIGNATURE_RESULT_SUCCESS:
|
||||||
#endif
|
{
|
||||||
/* push binary into string -> really bad! */
|
// Additional consistency checks.
|
||||||
item->mPgpIdSign = "";
|
if(sign_size == MAX_SIGN_SIZE)
|
||||||
for(unsigned int i = 0; i < sign_size; i++)
|
{
|
||||||
{
|
RsErr() << __PRETTY_FUNCTION__ << "Inconsistent result. "
|
||||||
#ifdef DEBUG_IDS
|
<< "Signature uses full buffer. This is probably an "
|
||||||
rs_sprintf_append(strout, "%02x", (uint32_t) signarray[i]);
|
<< "error." << std::endl;
|
||||||
#endif
|
return SERVICE_CREATE_FAIL;
|
||||||
item->mPgpIdSign += signarray[i];
|
}
|
||||||
}
|
|
||||||
createStatus = SERVICE_CREATE_SUCCESS;
|
|
||||||
|
|
||||||
#ifdef DEBUG_IDS
|
/* push binary into string -> really bad! */
|
||||||
std::cerr << strout;
|
item->mPgpIdSign = "";
|
||||||
std::cerr << std::endl;
|
for(unsigned int i = 0; i < sign_size; i++)
|
||||||
#endif
|
item->mPgpIdSign += static_cast<char>(signarray[i]);
|
||||||
}
|
|
||||||
}
|
createStatus = SERVICE_CREATE_SUCCESS;
|
||||||
/* done! */
|
break;
|
||||||
}
|
}
|
||||||
else
|
case SELF_SIGNATURE_RESULT_FAILED: /* fall-through */
|
||||||
{
|
default:
|
||||||
createStatus = SERVICE_CREATE_SUCCESS;
|
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() ;
|
||||||
@ -3491,17 +3534,18 @@ RsGenExchange::ServiceCreate_Return p3IdService::service_CreateGroup(RsGxsGrpIte
|
|||||||
// do it like p3gxscircles: save the new grp id
|
// do it like p3gxscircles: save the new grp id
|
||||||
// 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return createStatus;
|
Dbg2() << __PRETTY_FUNCTION__ << " returns: " << createStatus << std::endl;
|
||||||
|
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)
|
|
||||||
<< std::endl;
|
|
||||||
sqlite3_close(mDb);
|
|
||||||
mDb = NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ENABLE_ENCRYPTED_DB
|
|
||||||
if(!mKey.empty())
|
|
||||||
{
|
|
||||||
rc = sqlite3_key(mDb, mKey.c_str(), mKey.size());
|
|
||||||
|
|
||||||
if(rc){
|
|
||||||
std::cerr << "Can't key database: " << sqlite3_errmsg(mDb)
|
|
||||||
<< std::endl;
|
|
||||||
|
|
||||||
sqlite3_close(mDb);
|
|
||||||
mDb = NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char *err = NULL;
|
|
||||||
rc = sqlite3_exec(mDb, "PRAGMA cipher_migrate;", NULL, NULL, &err);
|
|
||||||
if (rc != SQLITE_OK)
|
|
||||||
{
|
|
||||||
std::cerr << "RetroDb::RetroDb(): Error upgrading database, error code: " << rc;
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
std::cerr << ", " << err;
|
|
||||||
}
|
|
||||||
std::cerr << std::endl;
|
|
||||||
sqlite3_free(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Test DB for correct sqlcipher version
|
|
||||||
if (sqlite3_exec(mDb, "PRAGMA user_version;", NULL, NULL, NULL) != SQLITE_OK)
|
|
||||||
{
|
{
|
||||||
std::cerr << "RetroDb::RetroDb(): Failed to open database: " << dbPath << std::endl << "Trying with settings for sqlcipher version 3...";
|
RsErr() << __PRETTY_FUNCTION__ << " Can't open database, Error: "
|
||||||
//Reopening the database with correct settings
|
<< rc << " " << sqlite3_errmsg(mDb) << std::endl;
|
||||||
rc = sqlite3_close(mDb);
|
closeDb();
|
||||||
mDb = NULL;
|
print_stacktrace();
|
||||||
if(!rc)
|
return;
|
||||||
rc = sqlite3_open_v2(dbPath.c_str(), &mDb, flags, NULL);
|
}
|
||||||
if(!rc && !mKey.empty())
|
|
||||||
rc = sqlite3_key(mDb, mKey.c_str(), mKey.size());
|
if(alreadyExists)
|
||||||
if(!rc)
|
{
|
||||||
rc = sqlite3_exec(mDb, "PRAGMA kdf_iter = 64000;", NULL, NULL, NULL);
|
/* If the database has been created by a RetroShare compiled without
|
||||||
if (!rc && (sqlite3_exec(mDb, "PRAGMA user_version;", NULL, NULL, NULL) == SQLITE_OK))
|
* 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 )
|
||||||
{
|
{
|
||||||
std::cerr << "\tSuccess" << std::endl;
|
#ifndef NO_SQLCIPHER
|
||||||
} else {
|
RsWarn() << __PRETTY_FUNCTION__ << " The database is not encrypted: "
|
||||||
std::cerr << "\tFailed, giving up" << std::endl;
|
<< dbPath << std::endl;
|
||||||
sqlite3_close(mDb);
|
#endif // ndef NO_SQLCIPHER
|
||||||
mDb = NULL;
|
|
||||||
|
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())
|
||||||
|
{
|
||||||
|
rc = sqlite3_key(mDb, mKey.c_str(), static_cast<int>(mKey.size()));
|
||||||
|
|
||||||
|
if(rc)
|
||||||
|
{
|
||||||
|
RsErr() << __PRETTY_FUNCTION__ << " Can't key database: " << rc
|
||||||
|
<< " " << sqlite3_errmsg(mDb) << std::endl;
|
||||||
|
closeDb();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
char* err = nullptr;
|
||||||
|
rc = sqlite3_exec(mDb, "PRAGMA cipher_migrate;", nullptr, nullptr, &err);
|
||||||
|
if (rc != SQLITE_OK)
|
||||||
|
{
|
||||||
|
RsErr() << __PRETTY_FUNCTION__ << " Error upgrading database, error "
|
||||||
|
<< "code: " << rc << " " << err << std::endl;
|
||||||
|
sqlite3_free(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test DB for correct sqlcipher version
|
||||||
|
if(sqlite3_exec(
|
||||||
|
mDb, "PRAGMA user_version;",
|
||||||
|
nullptr, nullptr, nullptr ) != SQLITE_OK)
|
||||||
|
{
|
||||||
|
RsWarn() << __PRETTY_FUNCTION__ << " Failed to open database: "
|
||||||
|
<< dbPath << std::endl;
|
||||||
|
|
||||||
|
//Reopening the database with correct settings
|
||||||
|
closeDb();
|
||||||
|
if(!rc) rc = sqlite3_open_v2(dbPath.c_str(), &mDb, flags, nullptr);
|
||||||
|
if(!rc && !mKey.empty())
|
||||||
|
rc = sqlite3_key(mDb, mKey.c_str(), static_cast<int>(mKey.size()));
|
||||||
|
if(!rc)
|
||||||
|
rc = sqlite3_exec( mDb, "PRAGMA kdf_iter = 64000;",
|
||||||
|
nullptr, nullptr, nullptr );
|
||||||
|
if (!rc && (sqlite3_exec( mDb, "PRAGMA user_version;",
|
||||||
|
nullptr, nullptr, nullptr ) == SQLITE_OK))
|
||||||
|
{
|
||||||
|
RsInfo() << __PRETTY_FUNCTION__ << " Re-trying with settings for "
|
||||||
|
<< "sqlcipher version 3 successed" << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RsErr() << __PRETTY_FUNCTION__ << " Re-trying with settings for "
|
||||||
|
<< "sqlcipher version 3 failed, giving up" << std::endl;
|
||||||
|
closeDb();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#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;
|
||||||
@ -1987,11 +1987,11 @@ QString IdDialog::createUsageString(const RsIdentityUsage& u) const
|
|||||||
RetroShareLink::enumType service_type = RetroShareLink::TYPE_UNKNOWN;
|
RetroShareLink::enumType service_type = RetroShareLink::TYPE_UNKNOWN;
|
||||||
|
|
||||||
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 = image;
|
|
||||||
_scene->clear();
|
|
||||||
_scene->addPixmap(QPixmap::fromImage(image.scaled(ui->graphicsView->width(),ui->graphicsView->height())));
|
|
||||||
emit imageUpdated();
|
|
||||||
}//if (_avatar != image)
|
|
||||||
}//if (!_havePGPDetail)
|
|
||||||
|
|
||||||
//}//if (_group_info != gxs_group_info)
|
_avatar = pixmap.toImage();
|
||||||
|
_scene->clear();
|
||||||
|
_scene->addPixmap(pixmap.scaled(ui->graphicsView->width(),ui->graphicsView->height()));
|
||||||
|
emit imageUpdated();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
// We still want to add the item if it is unvalidated, in which case getGPGDetails returns false.
|
|
||||||
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);
|
||||||
|
newChild = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
detail.name = gpgId.toStdString() + tr(" (Unverified yet)").toStdString();
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
rsPeers->getAssociatedSSLIds(gpgId, info.sslContacts);
|
|
||||||
|
|
||||||
manageProfileLocations(gpgItem,gpgId,info);
|
|
||||||
|
|
||||||
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…
x
Reference in New Issue
Block a user